Visualization.js 15 KB

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