Visualizatio.js 15 KB

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