Visualization.js 16 KB

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