Visualizatio.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. Page({
  2. data: {
  3. isEditing: false,
  4. tableName: 'current_reduce', // 确保这个表名在页面中是有效的
  5. fileFormat: 'excel', // 默认是 Excel 格式
  6. shoopingtext: "", // 搜索框内容
  7. filteredRows: [], // 表格过滤后的数据
  8. rows: [], // 所有表格数据
  9. showModal: false, // 控制底部编辑删除弹窗的显示与否
  10. showAddModal: false, // 控制新增数据弹窗的显示与否
  11. currentRow: null, // 当前选中的表格行
  12. // 新增数据弹窗的输入框内容
  13. newData: {
  14. id: "",
  15. OM: "",
  16. CL: "",
  17. CEC: "",
  18. H_plus: "",
  19. HN: "",
  20. Al3_plus: "",
  21. Delta_pH: ""
  22. },
  23. // 中文表头内容,动态生成
  24. tableHeaders: [
  25. "序号", "Q/ΔpH", "初始pH", "有机质含量", "土壤粘粒",
  26. "交换性氢","交换性铝"
  27. ],
  28. unit: [
  29. " ", " ", " ", "(g/kg)", "(g/kg)",
  30. "(cmol/kg)", "(cmol/kg)"
  31. ]
  32. },
  33. // 页面加载时获取表格数据
  34. onLoad: function() {
  35. this.LoadData();
  36. },
  37. LoadData: function() {
  38. wx.request({
  39. url: 'https://soilgd.com:5000/table',
  40. method: 'POST',
  41. header: {
  42. 'Content-Type': 'application/json'
  43. },
  44. data: {
  45. table: 'current_reduce'
  46. },
  47. success: (res) => {
  48. console.log('后端返回数据:', res.data.rows); // 打印返回数据,确认格式
  49. if (res.data && Array.isArray(res.data.rows)) {
  50. const rows = res.data.rows.map(row => {
  51. return {
  52. 'id': row.id,
  53. 'Q_over_b': parseFloat(row.Q_over_b).toFixed(2),
  54. 'pH': parseFloat(row.pH).toFixed(2),
  55. 'OM': parseFloat(row.OM).toFixed(2),
  56. 'CL': parseFloat(row.CL).toFixed(2),
  57. 'H': parseFloat(row.H).toFixed(2),
  58. 'Al': parseFloat(row.Al).toFixed(2)
  59. };
  60. });
  61. this.setData({
  62. rows: rows,
  63. filteredRows: rows
  64. });
  65. } else {
  66. wx.showToast({
  67. title: '获取数据失败',
  68. icon: 'none'
  69. });
  70. }
  71. },
  72. fail: (err) => {
  73. wx.showToast({
  74. title: '请求失败,请重试',
  75. icon: 'none'
  76. });
  77. console.error('请求失败:', err);
  78. }
  79. });
  80. },
  81. // 下载模板函数
  82. onDownloadTemplate: function() {
  83. wx.showLoading({
  84. title: '下载中...',
  85. });
  86. const tableName = 'current_reduce'; // 或者根据需要选择表名
  87. const format = 'excel'; // 或者 'csv' 作为模板格式
  88. wx.request({
  89. url: `https://soilgd.com:5000/download_template?table=${tableName}&format=${format}`,
  90. method: 'GET',
  91. responseType: 'arraybuffer', // 处理二进制文件
  92. success: (res) => {
  93. wx.hideLoading();
  94. // 确保响应体返回的数据是有效的文件
  95. if (res.statusCode === 200) {
  96. const fileType = format === 'excel' ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'text/csv';
  97. // 生成唯一的文件名,添加时间戳以确保唯一性
  98. const timestamp = new Date().getTime();
  99. const fileName = `${tableName}_template_${timestamp}.${format}`;
  100. const filePath = wx.env.USER_DATA_PATH + '/' + fileName;
  101. // 使用文件系统管理器保存文件
  102. const fs = wx.getFileSystemManager();
  103. fs.writeFile({
  104. filePath: filePath,
  105. data: res.data,
  106. encoding: 'binary',
  107. success: () => {
  108. wx.showToast({
  109. title: '文件已保存',
  110. icon: 'success'
  111. });
  112. // 触发文件下载
  113. wx.openDocument({
  114. filePath: filePath,
  115. fileType: format === 'excel' ? 'xlsx' : 'csv',
  116. success: () => {
  117. console.log('文件打开成功');
  118. },
  119. fail: (error) => {
  120. console.error('文件打开失败', error);
  121. wx.showToast({
  122. title: '打开文件失败',
  123. icon: 'none'
  124. });
  125. }
  126. });
  127. },
  128. fail: (err) => {
  129. wx.showToast({
  130. title: '文件保存失败',
  131. icon: 'none'
  132. });
  133. console.error('文件保存失败', err);
  134. }
  135. });
  136. } else {
  137. wx.showToast({
  138. title: '下载失败',
  139. icon: 'none'
  140. });
  141. }
  142. },
  143. fail: (err) => {
  144. wx.hideLoading();
  145. wx.showToast({
  146. title: '请求失败,请重试',
  147. icon: 'none'
  148. });
  149. console.error('请求失败:', err);
  150. }
  151. });
  152. },
  153. // 导出数据按钮点击事件
  154. onExport: function () {
  155. const tableName = this.data.tableName;
  156. const fileFormat = this.data.fileFormat;
  157. wx.showLoading({
  158. title: '导出中...',
  159. });
  160. // 向后端发送请求,获取表格数据并导出
  161. wx.request({
  162. url: `https://soilgd.com:5000/export_data?table=${tableName}&format=${fileFormat}`,
  163. method: 'GET',
  164. responseType: 'arraybuffer', // 处理二进制文件
  165. success: (res) => {
  166. wx.hideLoading();
  167. // 确保响应体返回的数据是有效的文件
  168. if (res.statusCode === 200) {
  169. const fileName = `${tableName}_data.${fileFormat === 'excel' ? 'xlsx' : 'csv'}`;
  170. const filePath = wx.env.USER_DATA_PATH + '/' + fileName;
  171. // 保存文件到本地
  172. wx.getFileSystemManager().writeFile({
  173. filePath: filePath,
  174. data: res.data,
  175. encoding: 'binary',
  176. success: () => {
  177. wx.showToast({
  178. title: '文件已保存',
  179. icon: 'success'
  180. });
  181. // 打开已保存的文件
  182. wx.openDocument({
  183. filePath: filePath,
  184. fileType: fileFormat === 'excel' ? 'xlsx' : 'csv',
  185. success: () => {
  186. console.log('文件打开成功');
  187. },
  188. fail: (error) => {
  189. console.error('文件打开失败', error);
  190. wx.showToast({
  191. title: '打开文件失败',
  192. icon: 'none'
  193. });
  194. }
  195. });
  196. },
  197. fail: (err) => {
  198. wx.showToast({
  199. title: '文件保存失败',
  200. icon: 'none'
  201. });
  202. console.error('文件保存失败', err);
  203. }
  204. });
  205. } else {
  206. wx.showToast({
  207. title: '导出失败,请重试',
  208. icon: 'none'
  209. });
  210. }
  211. },
  212. fail: (err) => {
  213. wx.hideLoading();
  214. wx.showToast({
  215. title: '请求失败,请重试',
  216. icon: 'none'
  217. });
  218. console.error('请求失败:', err);
  219. }
  220. });
  221. },
  222. // 导入数据功能
  223. onImport: function () {
  224. wx.chooseMessageFile({
  225. count: 1,
  226. type: 'file',
  227. extension: ['xlsx', 'csv'], // 允许上传的文件类型
  228. success: (res) => {
  229. const filePath = res.tempFiles[0].path;
  230. const fileName = res.tempFiles[0].name;
  231. wx.showLoading({ title: '上传中...' });
  232. // 上传文件到后端
  233. wx.uploadFile({
  234. url: 'https://soilgd.com:5000/import_data', // 后端接口
  235. filePath: filePath,
  236. name: 'file',
  237. formData: {
  238. table: this.data.tableName, // 表名
  239. fileName: fileName
  240. },
  241. success: (res) => {
  242. wx.hideLoading();
  243. const responseData = JSON.parse(res.data);
  244. if (responseData.success) {
  245. // 获取后端返回的结果
  246. const { total_data, new_data, duplicate_data, duplicate_details } = responseData;
  247. // 显示导入结果
  248. wx.showModal({
  249. title: '导入结果',
  250. content: `总数据: ${total_data} 条\n新增: ${new_data} 条\n重复: ${duplicate_data} 条`,
  251. success: () => {
  252. // 如果有重复数据,跳转到重复数据详情页面
  253. if (duplicate_data > 0) {
  254. wx.navigateTo({
  255. url: '/pages/duplicateDetails/duplicateDetails', // 重复数据详情页面
  256. success: (page) => {
  257. // 将重复数据传递给详情页面
  258. page.setData({ duplicateDetails: duplicate_details });
  259. }
  260. });
  261. }
  262. }
  263. });
  264. // 重新加载数据
  265. this.LoadData();
  266. } else {
  267. wx.showToast({
  268. title: responseData.message || '导入失败,请检查文件格式',
  269. icon: 'none'
  270. });
  271. }
  272. },
  273. fail: (err) => {
  274. wx.hideLoading();
  275. wx.showToast({
  276. title: '导入失败,请重试',
  277. icon: 'none'
  278. });
  279. console.error('文件上传失败:', err);
  280. }
  281. });
  282. },
  283. fail: (err) => {
  284. console.error('文件选择失败:', err);
  285. }
  286. });
  287. },
  288. // 新增按钮点击,显示新增弹窗
  289. onAdd: function() {
  290. console.log("新增按钮被点击了"); // 调试日志
  291. this.setData({
  292. showAddModal: true,
  293. newData: { // 重置新增数据
  294. Q_over_b: "",
  295. pH: "",
  296. OM: "",
  297. CL: "",
  298. H: "",
  299. Al: ""
  300. }
  301. });
  302. console.log("showAddModal: ", this.data.showAddModal); // 确认数据更新
  303. },
  304. // 输入框绑定:更新新增数据的对应字段
  305. onInputQ_over_b: function(e) {
  306. this.setData({
  307. 'newData.Q_over_b': e.detail.value
  308. });
  309. },
  310. onInputpH: function(e) {
  311. this.setData({
  312. 'newData.pH': e.detail.value
  313. });
  314. },
  315. onInputOM: function(e) {
  316. this.setData({
  317. 'newData.OM': e.detail.value
  318. });
  319. },
  320. onInputCL: function(e) {
  321. this.setData({
  322. 'newData.CL': e.detail.value
  323. });
  324. },
  325. onInputH: function(e) {
  326. this.setData({
  327. 'newData.H': e.detail.value
  328. });
  329. },
  330. onInputAl: function(e) {
  331. this.setData({
  332. 'newData.Al': e.detail.value
  333. });
  334. },
  335. // 提交新增数据
  336. onSubmitAdd: function() {
  337. const newRow = this.data.newData;
  338. if (Object.values(newRow).some(value => !value)) {
  339. wx.showToast({
  340. title: '所有字段都必须填写!',
  341. icon: 'none'
  342. });
  343. return;
  344. }
  345. wx.request({
  346. url: 'https://soilgd.com:5000/add_item',
  347. method: 'POST',
  348. header: {
  349. 'Content-Type': 'application/json'
  350. },
  351. data: {
  352. table: 'current_reduce',
  353. item: newRow
  354. },
  355. success: (res) => {
  356. if (res.data.success) {
  357. this.setData({
  358. rows: [...this.data.rows, newRow],
  359. showAddModal: false
  360. });
  361. wx.showToast({
  362. title: '新增成功',
  363. icon: 'success'
  364. });
  365. this.LoadData();
  366. } else {
  367. wx.showToast({
  368. title: '新增失败',
  369. icon: 'none'
  370. });
  371. }
  372. },
  373. fail: (err) => {
  374. wx.showToast({
  375. title: '请求失败,请重试',
  376. icon: 'none'
  377. });
  378. console.error('请求失败:', err);
  379. }
  380. });
  381. },
  382. // 取消新增数据
  383. onCancel: function() {
  384. this.setData({
  385. showAddModal: false
  386. });
  387. },
  388. // 编辑按钮点击
  389. onEdit: function(e) {
  390. const { index, row } = this.data.currentRow;
  391. console.log(row);
  392. // 检查 currentRow 是否有定义并且包含数据
  393. if (row) {
  394. this.setData({
  395. isEditing: true,
  396. showModal: false,
  397. showAddModal: true, // 显示编辑弹窗
  398. newData: row, // 将当前行的数据复制到 newData 中,以便在表单中显示
  399. currentRow: { index: index, row: row } // 保存当前行的信息,以便在提交时使用
  400. });
  401. } else {
  402. wx.showToast({
  403. title: '数据加载失败,请重试',
  404. icon: 'none'
  405. });
  406. }
  407. },
  408. // 提交编辑数据
  409. onSubmitEdit: function() {
  410. const updatedRow = this.data.newData;
  411. const { index } = this.data.currentRow;
  412. if (Object.values(updatedRow).some(value => !value)) {
  413. wx.showToast({
  414. title: '所有字段都必须填写!',
  415. icon: 'none'
  416. });
  417. return;
  418. }
  419. wx.request({
  420. url: 'https://soilgd.com:5000/update_item',
  421. method: 'PUT',
  422. header: {
  423. 'Content-Type': 'application/json'
  424. },
  425. data: {
  426. table: 'current_reduce',
  427. item: updatedRow
  428. },
  429. success: (res) => {
  430. if (res.data.success) {
  431. // 更新成功后,更新前端数据
  432. let rows = this.data.rows;
  433. rows[index] = updatedRow; // 用更新后的数据替换旧数据
  434. this.setData({
  435. rows: rows,
  436. showAddModal: false // 关闭编辑弹窗
  437. });
  438. wx.showToast({
  439. title: '编辑成功',
  440. icon: 'success'
  441. });
  442. this.LoadData();
  443. } else {
  444. wx.showToast({
  445. title: '编辑失败',
  446. icon: 'none'
  447. });
  448. }
  449. },
  450. fail: (err) => {
  451. wx.showToast({
  452. title: '请求失败,请重试',
  453. icon: 'none'
  454. });
  455. console.error('请求失败:', err);
  456. }
  457. });
  458. },
  459. // 删除按钮点击
  460. onDelete: function() {
  461. const { index, row } = this.data.currentRow;
  462. console.log("当前选中行的数据:", this.data.currentRow);
  463. const condition = `id=${row.id}`; // 使用条件进行删除
  464. // 发送 DELETE 请求
  465. wx.request({
  466. url: 'https://soilgd.com:5000/delete_item', // 后端接口地址
  467. method: 'POST', // 使用 POST 请求
  468. data: {
  469. table: 'current_reduce', // 目标表
  470. condition: condition // 删除条件
  471. },
  472. success: (res) => {
  473. if (res.data.success) {
  474. // 删除成功后,更新前端数据
  475. let rows = this.data.rows;
  476. rows.splice(index, 1); // 从数据中删除选中的行
  477. this.setData({
  478. rows: rows,
  479. showModal: false // 隐藏编辑删除弹窗
  480. });
  481. wx.showToast({
  482. title: '删除成功',
  483. icon: 'success'
  484. });
  485. // 重新获取数据
  486. this.LoadData(); // 重新加载数据
  487. } else {
  488. wx.showToast({
  489. title: '删除失败',
  490. icon: 'none'
  491. });
  492. }
  493. },
  494. fail: (err) => {
  495. wx.showToast({
  496. title: '请求失败,请重试',
  497. icon: 'none'
  498. });
  499. console.error('请求失败:', err);
  500. }
  501. });
  502. },
  503. onSubmit: function() {
  504. if (this.data.isEditing) {
  505. this.onSubmitEdit();
  506. } else {
  507. this.onSubmitAdd();
  508. }
  509. },
  510. // 取消编辑删除弹窗
  511. onCancel: function() {
  512. if (this.data.showModal) {
  513. this.setData({
  514. showModal: false
  515. });
  516. } else {
  517. this.setData({
  518. showAddModal: false
  519. });
  520. }
  521. },
  522. // 行点击事件:显示编辑和删除弹窗
  523. onRowClick: function(e) {
  524. const index = e.currentTarget.dataset.index;
  525. const row = e.currentTarget.dataset.row;
  526. this.setData({
  527. currentRow: { index: index, row: row },
  528. showModal: true // 显示编辑删除弹窗
  529. });
  530. }
  531. });