From a0dd2bd1be4e97a93443a48b86c719930d0a268a Mon Sep 17 00:00:00 2001
From: yaowanxin <3588231647@qq.com>
Date: 星期二, 12 八月 2025 16:13:44 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_ai' into ywx

---
 src/views/personnelManagement/payrollManagement/components/formDia.vue     |  315 +++
 src/views/personnelManagement/payrollManagement/index.vue                  |  291 +++
 src/assets/img/emoji/slightly-smiling-face.png                             |    0 
 src/assets/img/fileImg/txt.png                                             |    0 
 src/views/qualityManagement/rawMaterialInspection/index.vue                |  157 +
 src/views/inventoryManagement/stockWarning/index.vue                       | 1137 ++++++++++++
 src/assets/img/emoji/取消.png                                                |    0 
 src/views/chatHome/chatHomeIndex/home.vue                                  |  175 +
 src/assets/img/emoji/thumbs-up-yellow.png                                  |    0 
 src/views/equipmentManagement/ledger/Form.vue                              |    2 
 src/assets/img/emoji/money-bag.png                                         |    0 
 src/assets/img/emoji/new-moon-face.png                                     |    0 
 src/views/equipmentManagement/gasTank/simple.vue                           |  566 ++++++
 src/api/personnelManagement/payrollManagement.js                           |   35 
 src/api/inventoryManagement/stockWarning.js                                |   81 
 src/api/qualityManagement/rawMaterialInspection.js                         |   23 
 src/views/energyManagement/waterManagement/components/waterBillForm.vue    |  210 ++
 src/assets/img/emoji/clown-face.png                                        |    0 
 src/assets/img/emoji/ok-hand-yellow.png                                    |    0 
 src/views/equipmentManagement/ledger/index.vue                             |   73 
 src/assets/img/emoji/rainbow.png                                           |    0 
 src/assets/img/fileImg/unknowfile.png                                      |    0 
 src/views/energyManagement/waterManagement/waterBill.vue                   |  181 ++
 src/assets/img/emoji/thinking-face.png                                     |    0 
 src/assets/img/emoji/hibiscus.png                                          |    0 
 src/api/qualityManagement/metricMaintenance.js                             |   11 
 src/assets/img/fileImg/word.png                                            |    0 
 src/router/index.js                                                        |   15 
 src/assets/img/emoji/jack-o-lantern.png                                    |    0 
 src/views/energyManagement/waterManagement/components/formDia.vue          |  221 ++
 src/assets/img/emoji/rocket.png                                            |    0 
 src/views/qualityManagement/rawMaterialInspection/components/formDia.vue   |  137 +
 src/assets/img/fileImg/ppt.png                                             |    0 
 src/assets/img/emoji/money-mouth-face.png                                  |    0 
 src/assets/img/emoji/smiling-face-with-horns.png                           |    0 
 src/assets/img/emoji/shamrock.png                                          |    0 
 src/assets/img/emoji/face-screaming-in-fear.png                            |    0 
 src/assets/img/emoji/lips.png                                              |    0 
 src/assets/img/emoji/two-hearts.png                                        |    0 
 src/assets/img/head_portrait.jpg                                           |    0 
 src/assets/img/emoji/face-with-tongue.png                                  |    0 
 src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue |  127 +
 src/assets/img/emoji/smiling-face-with-sunglasses.png                      |    0 
 src/assets/img/emoji/thought-balloon.png                                   |    0 
 src/components/FileCard.vue                                                |   81 
 src/utils/util.js                                                          |   92 +
 src/assets/img/emoji/smiling-face-with-heart-eyes.png                      |    0 
 src/assets/img/emoji/victory-hand-yellow.png                               |    0 
 src/assets/img/fileImg/excel.png                                           |    0 
 src/assets/img/fileImg/zpi.png                                             |    0 
 src/assets/img/emoji/pouting-face.png                                      |    0 
 src/views/chatHome/chatHomeIndex/ai-jz.js                                  |    3 
 src/assets/img/emoji/shangchuan.png                                        |    0 
 src/assets/img/emoji/sparkles.png                                          |    0 
 src/assets/img/emoji/loudly-crying-face.png                                |    0 
 src/views/chatHome/chatHomeIndex/MobileChat.vue                            |  461 +++++
 src/assets/img/emoji/star.png                                              |    0 
 src/views/energyManagement/waterManagement/index.vue                       |  312 +++
 src/views/energyManagement/waterManagement/waterTrends.vue                 |  118 +
 src/assets/img/emoji/tired-face.png                                        |    0 
 src/assets/styles/element-ui.scss                                          |    2 
 src/views/chatHome/chatHomeIndex/ai-wd.js                                  |  393 ++++
 src/assets/img/emoji/face-vomiting.png                                     |    0 
 src/assets/img/logo.png                                                    |    0 
 src/assets/img/emoji/ghost.png                                             |    0 
 src/assets/img/emoji/pile-of-poo.png                                       |    0 
 package.json                                                               |    2 
 src/assets/img/fileImg/pdf.png                                             |    0 
 src/assets/img/emoji/face-without-mouth.png                                |    0 
 src/assets/img/emoji/smiling-face.png                                      |    0 
 src/api/energyManagement/waterManagement.js                                |   92 +
 src/assets/img/head_portrait1.png                                          |    0 
 72 files changed, 5,246 insertions(+), 67 deletions(-)

diff --git a/package.json b/package.json
index 15334fa..2ffdd34 100644
--- a/package.json
+++ b/package.json
@@ -33,10 +33,12 @@
     "jsencrypt": "3.3.2",
     "nprogress": "0.2.0",
     "pinia": "2.1.7",
+    "qrcode": "^1.5.4",
     "sortablejs": "^1.15.6",
     "splitpanes": "3.1.5",
     "vue": "3.4.31",
     "vue-cropper": "1.1.1",
+    "vue-esign": "^1.1.4",
     "vue-router": "4.4.0",
     "vuedraggable": "4.1.0"
   },
diff --git a/src/api/energyManagement/waterManagement.js b/src/api/energyManagement/waterManagement.js
new file mode 100644
index 0000000..caa82bf
--- /dev/null
+++ b/src/api/energyManagement/waterManagement.js
@@ -0,0 +1,92 @@
+// 鐢ㄦ按绠$悊
+import request from "@/utils/request";
+
+// 鐢ㄦ按璁惧-鍒嗛〉鏌ヨ
+export function waterEquipmentListPage(query) {
+  return request({
+    url: '/waterRecord/listPage',
+    method: 'get',
+    params: query,
+  })
+}
+
+// 鐢ㄦ按瓒嬪娍-鍒嗛〉鏌ヨ
+export function listPageByWaterTrend(query) {
+  return request({
+    url: '/waterRecord/listPageByTrend',
+    method: 'get',
+    params: query,
+  })
+}
+
+// 鐢ㄦ按璁惧-鍒犻櫎
+export function waterEquipmentDelete(query) {
+  return request({
+    url: '/waterRecord/delete',
+    method: 'delete',
+    data: query,
+  })
+}
+
+// 鐢ㄦ按璁惧-鏂板
+export function waterEquipmentAdd(query) {
+  return request({
+    url: '/waterRecord/add',
+    method: 'post',
+    data: query,
+  })
+}
+
+// 鐢ㄦ按璁惧-淇敼
+export function waterEquipmentUpdate(query) {
+  return request({
+    url: '/waterRecord/update',
+    method: 'post',
+    data: query,
+  })
+}
+
+// 鐢ㄦ按璁惧涓嬫媺妗嗘煡璇�
+export function waterDeviceList(query) {
+  return request({
+    url: '/device/ledger/page',
+    method: 'get',
+    params: query,
+  })
+}
+
+// 姘磋垂绠$悊-鍒嗛〉鏌ヨ
+export function waterBillListPage(query) {
+  return request({
+    url: '/waterBill/listPage',
+    method: 'get',
+    params: query,
+  })
+}
+
+// 姘磋垂绠$悊-鏂板
+export function waterBillAdd(query) {
+  return request({
+    url: '/waterBill/add',
+    method: 'post',
+    data: query,
+  })
+}
+
+// 姘磋垂绠$悊-淇敼
+export function waterBillUpdate(query) {
+  return request({
+    url: '/waterBill/update',
+    method: 'post',
+    data: query,
+  })
+}
+
+// 姘磋垂绠$悊-鍒犻櫎
+export function waterBillDelete(query) {
+  return request({
+    url: '/waterBill/delete',
+    method: 'delete',
+    data: query,
+  })
+}
diff --git a/src/api/inventoryManagement/stockWarning.js b/src/api/inventoryManagement/stockWarning.js
new file mode 100644
index 0000000..092fb80
--- /dev/null
+++ b/src/api/inventoryManagement/stockWarning.js
@@ -0,0 +1,81 @@
+import request from "@/utils/request";
+
+// 鏌ヨ鍌ㄦ皵缃愰璀﹀垪琛�
+export const getStockWarningPage = (params) => {
+    return request({
+        url: "/gasTankWarning/listPage",
+        method: "get",
+        params,
+    });
+};
+
+// 鏂板鍌ㄦ皵缃愰璀﹁鍒�
+export const addStockWarning = (data) => {
+    return request({
+        url: "/gasTankWarning/add",
+        method: "post",
+        data,
+    });
+};
+
+// 淇敼鍌ㄦ皵缃愰璀﹁鍒�
+export const updateStockWarning = (data) => {
+    return request({
+        url: "/gasTankWarning/update",
+        method: "put",
+        data,
+    });
+};
+
+// 鍒犻櫎鍌ㄦ皵缃愰璀﹁鍒�
+export const deleteStockWarning = (ids) => {
+    return request({
+        url: "/gasTankWarning/delete",
+        method: "delete",
+        data: { ids },
+    });
+};
+
+// 鎵归噺澶勭悊鍌ㄦ皵缃愰璀�
+export const batchProcessStockWarning = (data) => {
+    return request({
+        url: "/gasTankWarning/batchProcess",
+        method: "post",
+        data,
+    });
+};
+
+// 瀵煎嚭鍌ㄦ皵缃愰璀︽暟鎹�
+export const exportStockWarning = (params) => {
+    return request({
+        url: "/gasTankWarning/export",
+        method: "get",
+        params,
+        responseType: "blob",
+    });
+};
+
+// 鏍规嵁ID鑾峰彇鍌ㄦ皵缃愰璀﹁鎯�
+export const getStockWarningById = (id) => {
+    return request({
+        url: `/gasTankWarning/${id}`,
+        method: "get",
+    });
+};
+
+// 鍚敤/绂佺敤棰勮瑙勫垯
+export const toggleStockWarningStatus = (data) => {
+    return request({
+        url: "/gasTankWarning/toggleStatus",
+        method: "put",
+        data,
+    });
+};
+
+// 鑾峰彇棰勮缁熻淇℃伅
+export const getStockWarningStatistics = () => {
+    return request({
+        url: "/gasTankWarning/statistics",
+        method: "get",
+    });
+};
diff --git a/src/api/personnelManagement/payrollManagement.js b/src/api/personnelManagement/payrollManagement.js
new file mode 100644
index 0000000..c29a6b1
--- /dev/null
+++ b/src/api/personnelManagement/payrollManagement.js
@@ -0,0 +1,35 @@
+// 钖叕绠$悊
+import request from "@/utils/request";
+
+// 鏌ヨ鍒楄〃
+export function compensationListPage(query) {
+  return request({
+    url: "/compensationPerformance/listPage",
+    method: "get",
+    params: query,
+  });
+}
+// 鏂板
+export function compensationAdd(query) {
+  return request({
+    url: "/compensationPerformance/add",
+    method: "post",
+    data: query,
+  });
+}
+// 淇敼
+export function compensationUpdate(query) {
+  return request({
+    url: "/compensationPerformance/update",
+    method: "post",
+    data: query,
+  });
+}
+// 鍒犻櫎
+export function compensationDelete(query) {
+  return request({
+    url: "/compensationPerformance/delete",
+    method: "delete",
+    data: query,
+  });
+}
\ No newline at end of file
diff --git a/src/api/qualityManagement/metricMaintenance.js b/src/api/qualityManagement/metricMaintenance.js
index 8857387..9bdff23 100644
--- a/src/api/qualityManagement/metricMaintenance.js
+++ b/src/api/qualityManagement/metricMaintenance.js
@@ -8,6 +8,7 @@
         params: query,
     })
 }
+
 // 鏂板鎸囨爣鍒楄〃
 export function qualityTestStandardAdd(query) {
     return request({
@@ -16,6 +17,7 @@
         data: query,
     })
 }
+
 // 淇敼鎸囨爣鍒楄〃
 export function qualityTestStandardUpdate(query) {
     return request({
@@ -24,6 +26,7 @@
         data: query,
     })
 }
+
 // 鍒犻櫎鎸囨爣鍒楄〃
 export function qualityTestStandardDel(query) {
     return request({
@@ -31,4 +34,12 @@
         method: 'delete',
         data: query,
     })
+}
+
+// 鍒犻櫎鎸囨爣鍒楄〃
+export function qualityInspectDetailByProductId(productId) {
+    return request({
+        url: '/quality/qualityTestStandard/product/' + productId,
+        method: 'get',
+    })
 }
\ No newline at end of file
diff --git a/src/api/qualityManagement/rawMaterialInspection.js b/src/api/qualityManagement/rawMaterialInspection.js
index e909d1a..dcb3869 100644
--- a/src/api/qualityManagement/rawMaterialInspection.js
+++ b/src/api/qualityManagement/rawMaterialInspection.js
@@ -8,6 +8,7 @@
         params: query,
     })
 }
+
 // 鏂板鍘熸潗鏂欐楠�
 export function qualityInspectAdd(query) {
     return request({
@@ -16,6 +17,7 @@
         data: query,
     })
 }
+
 // 淇敼鍘熸潗鏂欐楠�
 export function qualityInspectUpdate(query) {
     return request({
@@ -24,6 +26,7 @@
         data: query,
     })
 }
+
 // 鍒犻櫎鍘熸潗鏂欐楠�
 export function qualityInspectDel(query) {
     return request({
@@ -32,3 +35,23 @@
         data: query,
     })
 }
+
+// 鎻愪氦鍘熸潗鏂欐楠�
+export function submitQualityInspect(data) {
+    return request({
+        url: '/quality/qualityInspect/submit',
+        method: 'post',
+        data: data,
+    })
+}
+
+// 鎻愪氦鍘熸潗鏂欐楠�
+export function downloadQualityInspect(data) {
+    return request({
+        url: '/quality/qualityInspect/down',
+        method: 'post',
+        data: data,
+        responseType: "blob",
+    })
+}
+
diff --git a/src/assets/img/emoji/clown-face.png b/src/assets/img/emoji/clown-face.png
new file mode 100644
index 0000000..fd77228
--- /dev/null
+++ b/src/assets/img/emoji/clown-face.png
Binary files differ
diff --git a/src/assets/img/emoji/face-screaming-in-fear.png b/src/assets/img/emoji/face-screaming-in-fear.png
new file mode 100644
index 0000000..d6332ce
--- /dev/null
+++ b/src/assets/img/emoji/face-screaming-in-fear.png
Binary files differ
diff --git a/src/assets/img/emoji/face-vomiting.png b/src/assets/img/emoji/face-vomiting.png
new file mode 100644
index 0000000..dcc556f
--- /dev/null
+++ b/src/assets/img/emoji/face-vomiting.png
Binary files differ
diff --git a/src/assets/img/emoji/face-with-tongue.png b/src/assets/img/emoji/face-with-tongue.png
new file mode 100644
index 0000000..b2e228e
--- /dev/null
+++ b/src/assets/img/emoji/face-with-tongue.png
Binary files differ
diff --git a/src/assets/img/emoji/face-without-mouth.png b/src/assets/img/emoji/face-without-mouth.png
new file mode 100644
index 0000000..e48a05a
--- /dev/null
+++ b/src/assets/img/emoji/face-without-mouth.png
Binary files differ
diff --git a/src/assets/img/emoji/ghost.png b/src/assets/img/emoji/ghost.png
new file mode 100644
index 0000000..8a4b03a
--- /dev/null
+++ b/src/assets/img/emoji/ghost.png
Binary files differ
diff --git a/src/assets/img/emoji/hibiscus.png b/src/assets/img/emoji/hibiscus.png
new file mode 100644
index 0000000..5fddeb5
--- /dev/null
+++ b/src/assets/img/emoji/hibiscus.png
Binary files differ
diff --git a/src/assets/img/emoji/jack-o-lantern.png b/src/assets/img/emoji/jack-o-lantern.png
new file mode 100644
index 0000000..7014639
--- /dev/null
+++ b/src/assets/img/emoji/jack-o-lantern.png
Binary files differ
diff --git a/src/assets/img/emoji/lips.png b/src/assets/img/emoji/lips.png
new file mode 100644
index 0000000..40915bd
--- /dev/null
+++ b/src/assets/img/emoji/lips.png
Binary files differ
diff --git a/src/assets/img/emoji/loudly-crying-face.png b/src/assets/img/emoji/loudly-crying-face.png
new file mode 100644
index 0000000..d72008d
--- /dev/null
+++ b/src/assets/img/emoji/loudly-crying-face.png
Binary files differ
diff --git a/src/assets/img/emoji/money-bag.png b/src/assets/img/emoji/money-bag.png
new file mode 100644
index 0000000..df46b05
--- /dev/null
+++ b/src/assets/img/emoji/money-bag.png
Binary files differ
diff --git a/src/assets/img/emoji/money-mouth-face.png b/src/assets/img/emoji/money-mouth-face.png
new file mode 100644
index 0000000..f7c4cdf
--- /dev/null
+++ b/src/assets/img/emoji/money-mouth-face.png
Binary files differ
diff --git a/src/assets/img/emoji/new-moon-face.png b/src/assets/img/emoji/new-moon-face.png
new file mode 100644
index 0000000..8942b8b
--- /dev/null
+++ b/src/assets/img/emoji/new-moon-face.png
Binary files differ
diff --git a/src/assets/img/emoji/ok-hand-yellow.png b/src/assets/img/emoji/ok-hand-yellow.png
new file mode 100644
index 0000000..4dbd427
--- /dev/null
+++ b/src/assets/img/emoji/ok-hand-yellow.png
Binary files differ
diff --git a/src/assets/img/emoji/pile-of-poo.png b/src/assets/img/emoji/pile-of-poo.png
new file mode 100644
index 0000000..28f149a
--- /dev/null
+++ b/src/assets/img/emoji/pile-of-poo.png
Binary files differ
diff --git a/src/assets/img/emoji/pouting-face.png b/src/assets/img/emoji/pouting-face.png
new file mode 100644
index 0000000..0265aa2
--- /dev/null
+++ b/src/assets/img/emoji/pouting-face.png
Binary files differ
diff --git a/src/assets/img/emoji/rainbow.png b/src/assets/img/emoji/rainbow.png
new file mode 100644
index 0000000..7794ded
--- /dev/null
+++ b/src/assets/img/emoji/rainbow.png
Binary files differ
diff --git a/src/assets/img/emoji/rocket.png b/src/assets/img/emoji/rocket.png
new file mode 100644
index 0000000..04a7619
--- /dev/null
+++ b/src/assets/img/emoji/rocket.png
Binary files differ
diff --git a/src/assets/img/emoji/shamrock.png b/src/assets/img/emoji/shamrock.png
new file mode 100644
index 0000000..8fe0836
--- /dev/null
+++ b/src/assets/img/emoji/shamrock.png
Binary files differ
diff --git a/src/assets/img/emoji/shangchuan.png b/src/assets/img/emoji/shangchuan.png
new file mode 100644
index 0000000..af16fb4
--- /dev/null
+++ b/src/assets/img/emoji/shangchuan.png
Binary files differ
diff --git a/src/assets/img/emoji/slightly-smiling-face.png b/src/assets/img/emoji/slightly-smiling-face.png
new file mode 100644
index 0000000..be7dd9f
--- /dev/null
+++ b/src/assets/img/emoji/slightly-smiling-face.png
Binary files differ
diff --git a/src/assets/img/emoji/smiling-face-with-heart-eyes.png b/src/assets/img/emoji/smiling-face-with-heart-eyes.png
new file mode 100644
index 0000000..c838d4f
--- /dev/null
+++ b/src/assets/img/emoji/smiling-face-with-heart-eyes.png
Binary files differ
diff --git a/src/assets/img/emoji/smiling-face-with-horns.png b/src/assets/img/emoji/smiling-face-with-horns.png
new file mode 100644
index 0000000..b79738c
--- /dev/null
+++ b/src/assets/img/emoji/smiling-face-with-horns.png
Binary files differ
diff --git a/src/assets/img/emoji/smiling-face-with-sunglasses.png b/src/assets/img/emoji/smiling-face-with-sunglasses.png
new file mode 100644
index 0000000..58b8604
--- /dev/null
+++ b/src/assets/img/emoji/smiling-face-with-sunglasses.png
Binary files differ
diff --git a/src/assets/img/emoji/smiling-face.png b/src/assets/img/emoji/smiling-face.png
new file mode 100644
index 0000000..3c2915b
--- /dev/null
+++ b/src/assets/img/emoji/smiling-face.png
Binary files differ
diff --git a/src/assets/img/emoji/sparkles.png b/src/assets/img/emoji/sparkles.png
new file mode 100644
index 0000000..4d11a1b
--- /dev/null
+++ b/src/assets/img/emoji/sparkles.png
Binary files differ
diff --git a/src/assets/img/emoji/star.png b/src/assets/img/emoji/star.png
new file mode 100644
index 0000000..44f80bb
--- /dev/null
+++ b/src/assets/img/emoji/star.png
Binary files differ
diff --git a/src/assets/img/emoji/thinking-face.png b/src/assets/img/emoji/thinking-face.png
new file mode 100644
index 0000000..33d791d
--- /dev/null
+++ b/src/assets/img/emoji/thinking-face.png
Binary files differ
diff --git a/src/assets/img/emoji/thought-balloon.png b/src/assets/img/emoji/thought-balloon.png
new file mode 100644
index 0000000..892eedc
--- /dev/null
+++ b/src/assets/img/emoji/thought-balloon.png
Binary files differ
diff --git a/src/assets/img/emoji/thumbs-up-yellow.png b/src/assets/img/emoji/thumbs-up-yellow.png
new file mode 100644
index 0000000..c30b6ae
--- /dev/null
+++ b/src/assets/img/emoji/thumbs-up-yellow.png
Binary files differ
diff --git a/src/assets/img/emoji/tired-face.png b/src/assets/img/emoji/tired-face.png
new file mode 100644
index 0000000..d1deba8
--- /dev/null
+++ b/src/assets/img/emoji/tired-face.png
Binary files differ
diff --git a/src/assets/img/emoji/two-hearts.png b/src/assets/img/emoji/two-hearts.png
new file mode 100644
index 0000000..4259b46
--- /dev/null
+++ b/src/assets/img/emoji/two-hearts.png
Binary files differ
diff --git a/src/assets/img/emoji/victory-hand-yellow.png b/src/assets/img/emoji/victory-hand-yellow.png
new file mode 100644
index 0000000..fc46ce2
--- /dev/null
+++ b/src/assets/img/emoji/victory-hand-yellow.png
Binary files differ
diff --git "a/src/assets/img/emoji/\345\217\226\346\266\210.png" "b/src/assets/img/emoji/\345\217\226\346\266\210.png"
new file mode 100644
index 0000000..30df0a9
--- /dev/null
+++ "b/src/assets/img/emoji/\345\217\226\346\266\210.png"
Binary files differ
diff --git a/src/assets/img/fileImg/excel.png b/src/assets/img/fileImg/excel.png
new file mode 100644
index 0000000..ae8929c
--- /dev/null
+++ b/src/assets/img/fileImg/excel.png
Binary files differ
diff --git a/src/assets/img/fileImg/pdf.png b/src/assets/img/fileImg/pdf.png
new file mode 100644
index 0000000..3653045
--- /dev/null
+++ b/src/assets/img/fileImg/pdf.png
Binary files differ
diff --git a/src/assets/img/fileImg/ppt.png b/src/assets/img/fileImg/ppt.png
new file mode 100644
index 0000000..2362d61
--- /dev/null
+++ b/src/assets/img/fileImg/ppt.png
Binary files differ
diff --git a/src/assets/img/fileImg/txt.png b/src/assets/img/fileImg/txt.png
new file mode 100644
index 0000000..0ce91dc
--- /dev/null
+++ b/src/assets/img/fileImg/txt.png
Binary files differ
diff --git a/src/assets/img/fileImg/unknowfile.png b/src/assets/img/fileImg/unknowfile.png
new file mode 100644
index 0000000..75e22fb
--- /dev/null
+++ b/src/assets/img/fileImg/unknowfile.png
Binary files differ
diff --git a/src/assets/img/fileImg/word.png b/src/assets/img/fileImg/word.png
new file mode 100644
index 0000000..97e8a69
--- /dev/null
+++ b/src/assets/img/fileImg/word.png
Binary files differ
diff --git a/src/assets/img/fileImg/zpi.png b/src/assets/img/fileImg/zpi.png
new file mode 100644
index 0000000..de3c681
--- /dev/null
+++ b/src/assets/img/fileImg/zpi.png
Binary files differ
diff --git a/src/assets/img/head_portrait.jpg b/src/assets/img/head_portrait.jpg
new file mode 100644
index 0000000..dd345b3
--- /dev/null
+++ b/src/assets/img/head_portrait.jpg
Binary files differ
diff --git a/src/assets/img/head_portrait1.png b/src/assets/img/head_portrait1.png
new file mode 100644
index 0000000..3134bd5
--- /dev/null
+++ b/src/assets/img/head_portrait1.png
Binary files differ
diff --git a/src/assets/img/logo.png b/src/assets/img/logo.png
new file mode 100644
index 0000000..b53ef8a
--- /dev/null
+++ b/src/assets/img/logo.png
Binary files differ
diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss
index 4eae8b2..8c741af 100644
--- a/src/assets/styles/element-ui.scss
+++ b/src/assets/styles/element-ui.scss
@@ -67,7 +67,7 @@
 }
 .el-dialog__body {
   padding: 16px 40px 0 40px;
-  max-height: 90vh;
+  max-height: 74vh;
   overflow-y: auto;
 }
 .el-dialog__footer {
diff --git a/src/components/FileCard.vue b/src/components/FileCard.vue
new file mode 100644
index 0000000..d14ec48
--- /dev/null
+++ b/src/components/FileCard.vue
@@ -0,0 +1,81 @@
+<template>
+  <div class="file-card">
+    <img src="@/assets/img/fileImg/unknowfile.png" alt="" v-if="fileType == 0"/>
+    <img src="@/assets/img/fileImg/word.png" alt="" v-else-if="fileType == 1"/>
+    <img src="@/assets/img/fileImg/excel.png" alt="" v-else-if="fileType == 2"/>
+    <img src="@/assets/img/fileImg/ppt.png" alt="" v-else-if="fileType == 3"/>
+    <img src="@/assets/img/fileImg/pdf.png" alt="" v-else-if="fileType == 4"/>
+    <img src="@/assets/img/fileImg/zpi.png" alt="" v-else-if="fileType == 5"/>
+    <img src="@/assets/img/fileImg/txt.png" alt="" v-else/>
+    <div class="word">
+      <span
+        >{{file.name || '鏈煡'}}</span
+      >
+      <span>154kb</span>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  // props: ["fileType", "file"],
+  props: {
+    fileType: Number,
+    file: File,
+    default() {
+      return {};
+    },
+  },
+  watch: {
+    file() {
+      console.log(this.file);
+    },
+  },  
+  mounted() {
+    console.log(this.file);
+    console.log(this.fileType);
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.file-card {
+  width: 250px;
+  height: 100px;
+  background-color: rgb(45, 48, 63);
+  border-radius: 20px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 10px;
+  box-sizing: border-box;
+  cursor: pointer;
+  &:hover {
+    background-color: rgb(33, 36, 54);
+  }
+  img {
+    width: 60px;
+    height: 60px;
+  }
+  .word {
+    width: 60%;
+    margin-left: 10px;
+    overflow: hidden;
+    span {
+      width: 90%;
+      display: inline-block;
+      color: #fff;
+    }
+    span:first-child {
+      font-size: 14px;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+    }
+    span:last-child {
+      font-size: 12px;
+      color: rgb(180, 180, 180);
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
index 3c69a74..10adf72 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -57,6 +57,7 @@
     component: () => import('@/views/error/401'),
     hidden: true
   },
+
   {
     path: '',
     component: Layout,
@@ -71,6 +72,20 @@
     ]
   },
   {
+    path: '/main/MobileChat',
+    component: Layout,
+    redirect: '',
+    hidden: true,
+    children: [
+      {
+        path: '',
+        component: () => import('@/views/chatHome/chatHomeIndex/MobileChat'),
+        name: 'MobileChat',
+        meta: { title: 'AI瀵硅瘽', icon: 'dashboard', affix: true}
+      }
+    ]
+  },
+  {
     path: '/user',
     component: Layout,
     hidden: true,
diff --git a/src/utils/util.js b/src/utils/util.js
new file mode 100644
index 0000000..78846dc
--- /dev/null
+++ b/src/utils/util.js
@@ -0,0 +1,92 @@
+//闃叉姈
+export  function debounce(fn) {
+    console.log(1)
+    let t = null //鍙細鎵ц涓�娆�
+    debugger
+
+    return function (){
+        if(t){
+            clearTimeout(t)
+        }
+        t = setTimeout(()=>{
+            console.log(temp);  //鍙互鑾峰彇
+            // console.log(arguments[0]) //undefined
+            fn.apply(this,arguments)
+            //鍦ㄨ繖涓洖璋冨嚱鏁伴噷闈㈢殑argument鏄繖涓洖璋冨嚱鏁扮殑鍙傛暟锛屽洜涓烘病鏈夊弬鏁版墍浠ndefined锛屽彲浠ラ�氳繃澶栭潰鐨勫嚱鏁拌祴鍊兼潵杩涜璁块棶
+            //涔熷彲浠ユ敼鍙樻垚绠ご鍑芥暟,绠ご鍑芥暟鐨則his鏄寚鍚戝畾涔夊嚱鏁扮殑閭d竴灞傜殑锛屾墍浠ヨ闂埌鐨刟rguments鏄笂涓�灞傚嚱鏁扮殑arguments
+        },1000)
+
+    }
+}
+//鑺傛祦
+export function throttle(fn, delay = 200) {
+    let timer = null
+    console.log(fn);
+    debugger
+    return function () {
+        if(timer) return
+        timer = setTimeout(() => {
+            debugger
+          fn.apply(this,arguments)
+          timer = null
+        })
+    }
+ }
+//涓嬫媺鍔ㄧ敾
+ export function animation(obj, target, fn1) {
+    // console.log(fn1);
+    // fn鏄竴涓洖璋冨嚱鏁帮紝鍦ㄥ畾鏃跺櫒缁撴潫鐨勬椂鍊欐坊鍔�
+    // 姣忔寮�瀹氭椂鍣ㄤ箣鍓嶅厛娓呴櫎鎺夊畾鏃跺櫒
+    clearInterval(obj.timer);
+    obj.timer = setInterval(function () {
+      // 姝ラ暱璁$畻鍏紡  瓒婃潵瓒婂皬
+      // 姝ラ暱鍙栨暣
+      var step = (target - obj.scrollTop) / 10;
+      step = step > 0 ? Math.ceil(step) : Math.floor(step);
+      if (obj.scrollTop >= target) {
+        clearInterval(obj.timer);
+        // 濡傛灉fn1瀛樺湪锛岃皟鐢╢n
+        if (fn1) {
+          fn1();
+        }
+      } else {
+        // 姣�30姣灏卞皢鏂扮殑鍊肩粰obj.left
+        obj.scrollTop = obj.scrollTop + step;
+      }
+    }, 10);
+  }
+
+  //鍒ゆ柇鏂囦欢绫诲瀷
+  export function judgeFileType(file) {
+    if (file == null||file == ""){  
+         alert("璇烽�夋嫨瑕佷笂浼犵殑鍥剧墖!");  
+         return false;  
+    }  
+    if (file.lastIndexOf('.')==-1){    //濡傛灉涓嶅瓨鍦�"."    
+        alert("璺緞涓嶆纭�!");  
+        return false;  
+    }  
+    var AllImgExt=".jpg|.jpeg|.gif|.bmp|.png|";  
+    var extName = file.substring(file.lastIndexOf(".")).toLowerCase();//锛堟妸璺緞涓殑鎵�鏈夊瓧姣嶅叏閮ㄨ浆鎹负灏忓啓锛�          
+    if(AllImgExt.indexOf(extName+"|")==-1)          
+    {  
+        ErrMsg="璇ユ枃浠剁被鍨嬩笉鍏佽涓婁紶銆傝涓婁紶 "+AllImgExt+" 绫诲瀷鐨勬枃浠讹紝褰撳墠鏂囦欢绫诲瀷涓�"+extName;  
+        alert(ErrMsg);  
+        return false;  
+    }  
+  }
+
+  //鏂囦欢绫诲瀷
+  export function fileType() {
+    return {
+      'application/msword': 'word',
+      'application/pdf': 'pdf',
+      'application/vnd.ms-powerpoint': 'ppt',
+      'application/vnd.ms-excel': 'excel',
+      'aplication/zip': 'zpi',
+    }
+  }
+
+  export function filterArr(arr) {
+      return arr.filter(item => item.flag !== false);
+  }
\ No newline at end of file
diff --git a/src/views/chatHome/chatHomeIndex/MobileChat.vue b/src/views/chatHome/chatHomeIndex/MobileChat.vue
new file mode 100644
index 0000000..f8bc625
--- /dev/null
+++ b/src/views/chatHome/chatHomeIndex/MobileChat.vue
@@ -0,0 +1,461 @@
+<template>
+  <div class="mobile-chat-wrapper" style="height: 91vh;">
+    <div class="chat-history">
+      <div class="chat-content" ref="chatContent">
+        <div class="chat-wrapper" v-for="(item, index) in chatList" :key="index">
+          <div class="chat-friend" v-if="item.uid !== '1001'">
+            <div class="info-time">
+              <img :src="item.headImg" alt="" />
+              <span>{{ item.name }}</span>
+              <span>{{ item.time }}</span>
+            </div>
+            <div class="chat-text" v-if="item.chatType == 0">
+              <template v-if="isSend && index === chatList.length - 1">
+                <span class="flash_cursor"></span>
+              </template>
+              <template v-else>
+                <pre>{{ item.msg }}</pre>
+              </template>
+            </div>
+            <div class="chat-img" v-if="item.chatType == 1">
+              <img :src="item.msg" alt="琛ㄦ儏" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" />
+              <el-image :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image>
+            </div>
+            <div class="chat-img" v-if="item.chatType == 2">
+              <div class="word-file">
+                <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
+              </div>
+            </div>
+          </div>
+          <div class="chat-me" v-else>
+            <div class="info-time">
+              <span>{{ item.name }}</span>
+              <span>{{ item.time }}</span>
+              <img :src="item.headImg" alt="" />
+            </div>
+            <div class="chat-text" v-if="item.chatType == 0">
+              {{ item.msg }}
+            </div>
+            <div class="chat-img" v-if="item.chatType == 1">
+              <img :src="item.msg" alt="琛ㄦ儏" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" />
+              <el-image style="max-width: 300px; border-radius: 10px" :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image>
+            </div>
+            <div class="chat-img" v-if="item.chatType == 2">
+              <div class="word-file">
+                <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="chat-input-wrapper">
+      <div style="display: flex; align-items: center">
+          <input v-model="inputMsg" @change="sendText" :disabled="loading" class="input-text" autofocus placeholder="缁欏皬鏅哄彂閫佹秷鎭�" />
+          <img class="send-icon" src="@/assets/img/emoji/rocket.png" alt="" @click="sendText" />
+
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, nextTick,onActivated } from 'vue'
+import { useRoute } from 'vue-router'
+import { animation } from '@/utils/util'
+import chatGPTHeadImg from '@/assets/img/head_portrait1.png'
+import headPortrait from '@/assets/img/head_portrait.jpg'
+import FileCard from '@/components/FileCard.vue'
+import { ElMessage } from "element-plus"
+import {checking} from './ai-wd.js'
+
+// 瀹氫箟鍝嶅簲寮忔暟鎹�
+const route = useRoute()
+const chatContent = ref(null)
+const ws = ref(null)
+const chatList = ref([
+  {
+    headImg: chatGPTHeadImg,
+    name: '灏忔櫤',
+    time: new Date().toLocaleTimeString(),
+    msg: ' 灏忔櫤涓烘偍鏈嶅姟',
+    chatType: 0,
+    uid: '1002'
+  }
+])
+const inputMsg = ref('')
+const isSend = ref(false)
+const fileList = ref([])
+const isProcessing = ref(false)
+const loading = ref(true)
+const srcImgList = ref([])
+
+// 鍒犻櫎鍥剧墖
+const deleteImg = (index) => {
+  if (index >= 0 && index < fileList.value.length) {
+    fileList.value.splice(index, 1)
+  }
+}
+
+// WebSocket娑堟伅鎺ユ敹
+const websocketonmessage = (e) => {
+  const redata = JSON.parse(e.data)
+  //鏁版嵁鎺ユ敹
+  let chatGPT = {
+    headImg: headPortrait,
+    name: 'DeepSeek',
+    time: new Date().toLocaleTimeString(),
+    msg: redata[0].text,
+    chatType: 0, //淇℃伅绫诲瀷锛�0鏂囧瓧锛�1鍥剧墖
+    uid: '1002' //uid
+  }
+  sendMsg(chatGPT)
+  isSend.value = false
+}
+
+// WebSocket鍙戦�佹秷鎭�
+const websocketsend = (Data) => {
+  console.log("鍗冲皢鍙戦�佹秷鎭�", Data)
+  if (ws.value && ws.value.readyState === WebSocket.OPEN) {
+    console.log("鍙戦�佹秷鎭�", ws.value)
+    console.log("鍙戦�佹秷鎭�", Data)
+    let fileUrls = fileList.value.map(item => item.file.fileUrl)
+    //鏁版嵁鍙戦��
+    ws.value.send(Data + ":" + fileUrls.join(","))
+    fileList.value = []
+    inputMsg.value = ''
+  }
+}
+
+// 鍙戦�佹枃鏈秷鎭�
+const sendText = () => {
+  if (inputMsg.value) {
+    let chatMsg = {
+      headImg: headPortrait,
+      name: '鍗ч緳',
+      time: new Date().toLocaleTimeString(),
+      msg: inputMsg.value,
+      chatType: 0, //淇℃伅绫诲瀷锛�0鏂囧瓧锛�1鍥剧墖
+      uid: '1001' //uid
+    }
+    chatList.value.push(chatMsg)
+    let chatGPT = {
+      headImg: headPortrait,
+      name: '灏忔櫤',
+      time: new Date().toLocaleTimeString(),
+      msg: "",
+      chatType: 0, //淇℃伅绫诲瀷锛�0鏂囧瓧锛�1鍥剧墖
+      uid: '1002' //uid
+    }
+    chatList.value.push(chatGPT) // 灏嗘帴鏀跺埌鐨勬秷鎭瓨鍌ㄥ埌 messages 鏁扮粍
+    simulateStreamingOutput(chatGPT, inputMsg.value)
+    inputMsg.value = ''
+
+  } else {
+    ElMessage({
+      message: '娑堟伅涓嶈兘涓虹┖鍝',
+      type: 'warning'
+    })
+  }
+}
+
+// 鍙戦�佷俊鎭�
+const sendMsg = (msgList) => {
+  chatList.value.push(msgList)
+  scrollBottom()
+}
+
+// 鑾峰彇绐楀彛楂樺害骞舵粴鍔ㄨ嚦鏈�搴曞眰
+const scrollBottom = () => {
+  nextTick(() => {
+    const scrollDom = chatContent.value
+    animation(scrollDom, scrollDom.scrollHeight - scrollDom.offsetHeight)
+  })
+}
+
+// 缁勪欢鎸傝浇鏃舵墽琛�
+onActivated(() => {
+  chatList.value = []
+  chatList.value.push({
+    headImg: chatGPTHeadImg,
+    name: '灏忔櫤',
+    time: new Date().toLocaleTimeString(),
+    msg: '灏忔櫤涓烘偍鏈嶅姟',
+    chatType: 0,
+    uid: '1002'
+  })
+  chatList.value.push({
+    headImg: chatGPTHeadImg,
+    name: '鍗ч緳',
+    time: new Date().toLocaleTimeString(),
+    msg: route.query.keyWord,
+    chatType: 0,
+    uid: '1001'
+  })
+  // 娣诲姞涓�涓┖鐨勫洖澶嶆秷鎭崰浣�
+  const replyMsg = {
+    headImg: chatGPTHeadImg,
+    name: '灏忔櫤',
+    time: new Date().toLocaleTimeString(),
+    msg: '',
+    chatType: 0,
+    uid: '1002'
+  }
+  chatList.value.push(replyMsg)
+  scrollBottom()
+
+  // 濡傛灉鏈夋煡璇㈠叧閿瓧锛屽垯妯℃嫙娴佸紡杈撳嚭
+  if (route.query.keyWord) {
+    simulateStreamingOutput(replyMsg, route.query.keyWord)
+  }
+})
+// 妯℃嫙娴佸紡杈撳嚭
+const simulateStreamingOutput = async (msgObj, keyWord) => {
+  loading.value = true
+  // 鐢熸垚0.8-1.3绉掍箣闂寸殑闅忔満寤惰繜
+  const delay = Math.random() * 500 + 800
+
+  // 妯℃嫙鍥炲鍐呭锛堝疄闄呭簲鐢ㄤ腑搴斾粠API鑾峰彇锛�
+  const responseText = `鍏充簬"${keyWord}"鐨勯棶棰橈紝鎴戞潵涓烘偍瑙g瓟锛歕n` + checking(keyWord)
+
+  isSend.value = true
+
+  let index = 0
+  setTimeout(() => {
+    const interval = setInterval(() => {
+      isSend.value = true
+      if (index < responseText.length) {
+        msgObj.msg += responseText.charAt(index)
+        index++
+        isSend.value = false
+        scrollBottom()
+      } else {
+        clearInterval(interval)
+        isSend.value = false
+        loading.value = false
+      }
+    }, 50) // 姣�50ms杈撳嚭涓�涓瓧绗︼紝妯℃嫙娴佸紡鏁堟灉
+  }, delay)
+
+}
+</script>
+
+<style lang="scss" scoped>
+.mobile-chat-wrapper {
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  height: 91vh;
+  position: relative;
+  background-color: white;
+
+  .chat-history {
+    flex: 1 1 0;
+    overflow-y: auto;
+  }
+
+  .chat-input-wrapper {
+    padding: 8px 16px 8px 8px;
+    position: absolute;
+    left: 0;
+    right: 0;
+    bottom: 0;
+      .file-tt{
+          flex-direction: column;
+          width: 200px;
+          display: flex;
+          padding: 5px;
+          border-radius: 5px;
+          margin-right: 5px;
+          background: #cacaca;
+          .file-item{
+              width: 200px;
+              overflow:hidden;
+              word-wrap: break-word;
+              text-overflow:ellipsis;
+              display:-webkit-box;
+              -webkit-box-orient:vertical;
+              -webkit-line-clamp:2;
+          }
+      }
+
+    .send-icon {
+      height: 40px;
+      margin-left: 16px;
+    }
+      .input-text{
+          font-size: 18px;
+          width: 100%;
+          border-radius: 20px;
+          height: 80px;
+          padding-left: 10px;
+          //padding-top: 10px;
+          border: none;
+          color: black;                 /* 淇敼鏂囨湰棰滆壊涓虹櫧鑹� */
+          background-color: #f5f4f4;   /* 淇敼鑳屾櫙棰滆壊涓烘繁鐏拌壊 */
+      }
+  }
+
+  .chat-content {
+    width: 100%;
+    height: 80%;
+    overflow-y: scroll;
+    padding: 20px;
+    box-sizing: border-box;
+
+    &::-webkit-scrollbar {
+      width: 0;
+      /* Safari,Chrome 闅愯棌婊氬姩鏉� */
+      height: 0;
+      /* Safari,Chrome 闅愯棌婊氬姩鏉� */
+      display: none;
+      /* 绉诲姩绔�乸ad 涓奡afari锛孋hrome锛岄殣钘忔粴鍔ㄦ潯 */
+    }
+
+    .chat-wrapper {
+      position: relative;
+      word-break: break-all;
+
+      .chat-friend {
+        width: 100%;
+        float: left;
+        margin-bottom: 20px;
+        display: flex;
+        flex-direction: column;
+        justify-content: flex-start;
+        align-items: flex-start;
+
+        .chat-text {
+          max-width: 90%;
+          padding: 20px;
+          border-radius: 20px 20px 20px 5px;
+          background-color: rgb(245, 248, 248);
+          color: black;
+
+          &:hover {
+            background-color: rgb(232, 232, 232);
+          }
+
+          pre {
+            white-space: break-spaces;
+          }
+        }
+
+        .chat-img {
+          img {
+            width: 100px;
+            height: 100px;
+          }
+        }
+
+        .info-time {
+          margin: 10px 0;
+          color: black;
+          font-size: 14px;
+
+          img {
+            width: 30px;
+            height: 30px;
+            border-radius: 50%;
+            vertical-align: middle;
+            margin-right: 10px;
+          }
+
+          span:last-child {
+            color: rgb(101, 104, 115);
+            margin-left: 10px;
+            vertical-align: middle;
+          }
+        }
+      }
+
+      .chat-me {
+        width: 100%;
+        float: right;
+        margin-bottom: 20px;
+        position: relative;
+        display: flex;
+        flex-direction: column;
+        justify-content: flex-end;
+        align-items: flex-end;
+
+        .chat-text {
+          float: right;
+          max-width: 90%;
+          padding: 20px;
+          border-radius: 20px 20px 5px 20px;
+          background-color: rgb(29, 144, 245);
+          color: #fff;
+
+          &:hover {
+            background-color: rgb(26, 129, 219);
+          }
+        }
+
+        .chat-img {
+          img {
+            max-width: 300px;
+            max-height: 200px;
+            border-radius: 10px;
+          }
+        }
+
+        .info-time {
+          margin: 10px 0;
+          color: black;
+          font-size: 14px;
+          display: flex;
+          justify-content: flex-end;
+
+          img {
+            width: 30px;
+            height: 30px;
+            border-radius: 50%;
+            vertical-align: middle;
+            margin-left: 10px;
+          }
+
+          span {
+            line-height: 30px;
+          }
+
+          span:first-child {
+            color: rgb(101, 104, 115);
+            margin-right: 10px;
+            vertical-align: middle;
+          }
+        }
+      }
+    }
+  }
+  .flash_cursor {
+    width: 20px;
+    height: 30px;
+    display: inline-block;
+    background: #d6e3f5;
+    opacity: 1;
+    animation: glow 800ms ease-out infinite alternate;
+  }
+  @keyframes glow {
+    0% {
+      opacity: 1;
+    }
+
+    25% {
+      opacity: 0.5;
+    }
+
+    50% {
+      opacity: 0;
+    }
+
+    75% {
+      opacity: 0.5;
+    }
+
+    100% {
+      opacity: 1;
+    }
+  }
+}
+</style>
diff --git a/src/views/chatHome/chatHomeIndex/ai-jz.js b/src/views/chatHome/chatHomeIndex/ai-jz.js
new file mode 100644
index 0000000..02ee6dc
--- /dev/null
+++ b/src/views/chatHome/chatHomeIndex/ai-jz.js
@@ -0,0 +1,3 @@
+export function jam() {
+    return ""
+}
\ No newline at end of file
diff --git a/src/views/chatHome/chatHomeIndex/ai-wd.js b/src/views/chatHome/chatHomeIndex/ai-wd.js
new file mode 100644
index 0000000..c5b83d5
--- /dev/null
+++ b/src/views/chatHome/chatHomeIndex/ai-wd.js
@@ -0,0 +1,393 @@
+export function gasLeaks() {
+  return "1. 璁捐涓庤澶囬�夋嫨\n" +
+      "閫夌敤楂樿川閲忔潗鏂欙細绠¢亾銆侀榾闂ㄣ�佸偍缃愮瓑璁惧搴旈�夌敤鑰愯厫铓�銆佽�愰珮鍘嬬殑鏉愭枡锛屽苟绗﹀悎瀹夊叏鏍囧噯锛堝ASME銆丄PI绛夛級銆俓n" +
+      "\n" +
+      "瀹夊叏璁捐锛歕n" +
+      "\n" +
+      "瀹夎鍐椾綑鐨勫畨鍏ㄨ缃紙濡傚弻閲嶉榾闂ㄣ�佺垎鐮寸墖銆佸畨鍏ㄩ榾绛夛級銆俓n" +
+      "\n" +
+      "璁剧疆姘斾綋娉勬紡妫�娴嬬郴缁燂紙濡傚彲鐕冩皵浣撴姤璀﹀櫒銆佹湁姣掓皵浣撲紶鎰熷櫒锛夈�俓n" +
+      "\n" +
+      "閲囩敤灏侀棴寮忕郴缁熻璁★紝鍑忓皯寮�鏀炬帴鍙c�俓n" +
+      "\n" +
+      "閫氶绯荤粺锛氬湪鍙兘娉勬紡鐨勫尯鍩熷畨瑁呭己鍒堕�氶璁惧锛岄槻姝㈡皵浣撹仛闆嗐�俓n" +
+      "\n" +
+      "2. 瀹夎涓庣淮鎶n" +
+      "瑙勮寖瀹夎锛氱敱涓撲笟浜哄憳杩涜璁惧瀹夎锛岀‘淇濈閬撶剨鎺ャ�佸瘑灏佺瓑鐜妭鏃犵己闄枫�俓n" +
+      "\n" +
+      "瀹氭湡妫�鏌ワ細\n" +
+      "\n" +
+      "瀵圭閬撱�侀榾闂ㄣ�佽繛鎺ュ杩涜娉勬紡妫�娴嬶紙濡傚帇鍔涙祴璇曘�佽秴澹版尝妫�娴嬨�佽偉鐨傛按妫�婕忥級銆俓n" +
+      "\n" +
+      "鏇存崲鑰佸寲鎴栬厫铓�鐨勯儴浠躲�俓n" +
+      "\n" +
+      "棰勯槻鎬х淮鎶わ細鍒跺畾缁存姢璁″垝锛屽畾鏈熸鼎婊戦榾闂ㄣ�佹洿鎹㈠瘑灏佷欢绛夈�俓n" +
+      "\n" +
+      "3. 鎿嶄綔绠$悊\n" +
+      "涓ユ牸鎿嶄綔瑙勭▼锛歕n" +
+      "\n" +
+      "鎿嶄綔浜哄憳闇�鍩硅涓婂矖锛岀啛鎮夋皵浣撶壒鎬у拰搴旀�ユ祦绋嬨�俓n" +
+      "\n" +
+      "閬垮厤瓒呭帇銆佽秴娓╂垨閿欒鎿嶄綔銆俓n" +
+      "\n" +
+      "鐩戞帶绯荤粺锛歕n" +
+      "\n" +
+      "瀹炴椂鐩戞祴鍘嬪姏銆佹俯搴︺�佹祦閲忕瓑鍙傛暟锛岃缃嚜鍔ㄦ姤璀﹀拰鑱旈攣鍋滄満瑁呯疆銆俓n" +
+      "\n" +
+      "浣跨敤姘斾綋妫�娴嬩华锛堝绾㈠銆佺數鍖栧浼犳劅鍣級鐩戞祴鐜娴撳害銆俓n" +
+      "\n" +
+      "鏄庣‘鏍囪瘑锛氬湪鍗遍櫓鍖哄煙鏍囨槑姘斾綋绫诲瀷銆侀闄╃瓑绾у強闃叉姢瑕佹眰銆俓n" +
+      "\n" +
+      "4. 娉勬紡搴旀�ユ帾鏂絓n" +
+      "搴旀�ヨ澶囷細\n" +
+      "\n" +
+      "閰嶅闃叉瘨闈㈠叿銆佸懠鍚稿櫒銆侀槻鎶ゆ湇绛変釜浜洪槻鎶よ澶囷紙PPE锛夈�俓n" +
+      "\n" +
+      "灏辫繎鏀剧疆娉勬紡搴旀�ュ寘锛堝鍫垫紡鑳躲�佸瘑灏佸甫锛夈�俓n" +
+      "\n" +
+      "绱ф�ュ搷搴旓細\n" +
+      "\n" +
+      "绔嬪嵆鍒囨柇姘旀簮锛堝叧闂笂娓搁榾闂ㄦ垨鍚姩绱ф�ュ垏鏂郴缁燂級銆俓n" +
+      "\n" +
+      "鍚姩閫氶璁惧绋�閲婃皵浣撴祿搴︺�俓n" +
+      "\n" +
+      "鐤忔暎浜哄憳骞朵笂鎶ヤ笓涓氶儴闂紙濡傛秷闃层�佺幆淇濓級銆俓n" +
+      "\n" +
+      "搴旀�ラ妗堬細瀹氭湡婕旂粌娉勬紡澶勭疆娴佺▼锛岀‘淇濅汉鍛樼啛鎮夊垎宸ャ�俓n" +
+      "\n" +
+      "5. 鍌ㄥ瓨涓庤繍杈撳畨鍏╘n" +
+      "鍌ㄥ瓨瑕佹眰锛歕n" +
+      "\n" +
+      "鍌ㄧ綈杩滅鐏簮銆侀珮娓╁尯锛屽苟璁剧疆鍥村牥闃叉鎵╂暎銆俓n" +
+      "\n" +
+      "娑插寲姘斾綋鍌ㄧ綈闇�閰嶅娉勫帇瑁呯疆銆俓n" +
+      "\n" +
+      "杩愯緭瀹夊叏锛歕n" +
+      "\n" +
+      "浣跨敤鍚堣鐨勮繍杈撹溅杈嗭紝鍥哄畾姘旂摱闃叉纰版挒銆俓n" +
+      "\n" +
+      "杩愯緭閫斾腑鐩戞帶杞﹁締鐘舵�侊紙濡侴PS銆佹俯搴︿紶鎰熷櫒锛夈�俓n" +
+      "\n" +
+      "6. 浜哄憳鍩硅涓庢枃鍖朶n" +
+      "瀹夊叏鍩硅锛氬畾鏈熷紑灞曟皵浣撳嵄瀹炽�侀槻鎶ゆ帾鏂藉拰搴旀�ュ鐞嗙殑鍩硅銆俓n" +
+      "\n" +
+      "瀹夊叏鏂囧寲锛氶紦鍔卞憳宸ユ姤鍛婃綔鍦ㄩ闄╋紝寤虹珛鈥滈浂娉勬紡鈥濈鐞嗙洰鏍囥�俓n" +
+      "\n" +
+      "7. 娉曡涓庢爣鍑哱n" +
+      "閬靛畧鐩稿叧娉曡锛堝OSHA銆丟B 50493銆婄煶娌瑰寲宸ュ彲鐕冩皵浣撳拰鏈夋瘨姘斾綋妫�娴嬫姤璀﹁璁¤鑼冦�嬶級銆俓n" +
+      "\n" +
+      "瀹氭湡杩涜瀹夊叏瀹¤锛岀‘淇濈鍚堣涓氭爣鍑嗐�俓n" +
+      "\n" +
+      "甯歌鍗遍櫓姘斾綋娉勬紡鐨勯拡瀵规�ф帾鏂絓n" +
+      "鍙噧姘斾綋锛堝鐢茬兎銆佹阿姘旓級锛氶槻鐖嗙數鍣ㄣ�佹秷闄ら潤鐢点�俓n" +
+      "\n" +
+      "鏈夋瘨姘斾綋锛堝姘皵銆佺~鍖栨阿锛夛細閰嶅涓撶敤杩囨护寮忔垨渚涙哀寮忓懠鍚稿櫒銆俓n" +
+      "\n" +
+      "绐掓伅鎬ф皵浣擄紙濡傛爱姘斻�佷簩姘у寲纰筹級锛氱洃娴嬫哀姘旀祿搴︼紝閬垮厤瀵嗛棴绌洪棿浣滀笟銆俓n" +
+      "\n" +
+      "閫氳繃浠ヤ笂鎺柦鐨勭患鍚堝簲鐢紝鍙ぇ骞呴檷浣庢皵浣撴硠婕忛闄╋紝淇濋殰浜哄憳瀹夊叏鍜岀幆澧冨仴搴枫�傝嫢鍙戠敓娉勬紡锛岄渶浼樺厛纭繚浜哄憳鎾ょ锛屽啀鐢变笓涓氫汉鍛樺缃�俓n" +
+      "\n" +
+      "鏈洖绛旂敱 AI 鐢熸垚锛屽唴瀹逛粎渚涘弬鑰冿紝璇蜂粩缁嗙攧鍒��"
+}
+
+export function shipping() {
+    return "涓�銆佺珛鍗冲簲鎬ュ搷搴擻n" +
+        "1. 鍙戠幇娉勬紡鏃剁殑绱ф�ヨ鍔╘n" +
+        "鍋滆溅骞堕殧绂荤幇鍦猴細\n" +
+        "\n" +
+        "杩愯緭杞﹁締绔嬪嵆鍋滈潬鍦ㄧ┖鏃枫�佽繙绂讳汉缇ゅ拰鐏簮鐨勪綅缃�俓n" +
+        "\n" +
+        "璁剧疆璀︽垝绾匡紙鑷冲皯50~100绫冲崐寰勶紝鏍规嵁姘斾綋鎬ц川璋冩暣锛夛紝绂佹鏃犲叧浜哄憳杩涘叆銆俓n" +
+        "\n" +
+        "鍒囨柇娉勬紡婧愶細\n" +
+        "\n" +
+        "鍏抽棴瀹瑰櫒闃�闂ㄦ垨灏佸牭鐮存崯澶勶紙濡備娇鐢ㄥ簲鎬ュ牭婕忓伐鍏凤級銆俓n" +
+        "\n" +
+        "鑻ラ榾闂ㄦ崯鍧忥紝灏濊瘯杞Щ鍓╀綑姘斾綋鑷冲鐢ㄥ鍣紙闇�涓撲笟浜哄憳鎿嶄綔锛夈�俓n" +
+        "\n" +
+        "鎶ヨ涓庝笂鎶ワ細\n" +
+        "\n" +
+        "鎷ㄦ墦搴旀�ョ數璇濓紙濡傛秷闃�119銆佺幆淇濋儴闂級锛岃鏄庢皵浣撶被鍨嬨�佹硠婕忛噺銆佷綅缃瓑淇℃伅銆俓n" +
+        "\n" +
+        "鑱旂郴杩愯緭鍏徃鍙婅揣涓伙紝鑾峰彇鎶�鏈敮鎻达紙濡侻SDS瀹夊叏鏁版嵁琛級銆俓n" +
+        "\n" +
+        "2. 浜哄憳闃叉姢涓庣枏鏁n" +
+        "绌挎埓闃叉姢瑁呭锛歕n" +
+        "\n" +
+        "鍙噧姘斾綋锛氶槻鐖嗗伐鍏�+闃查潤鐢垫湇锛涙湁姣掓皵浣擄細姝e帇寮忓懠鍚稿櫒+闃插寲鏈嶃�俓n" +
+        "\n" +
+        "鏃犻槻鎶よ澶囨椂锛岀珛鍗虫挙绂昏嚦涓婇鏂瑰悜銆俓n" +
+        "\n" +
+        "鐤忔暎鍛ㄨ竟鍖哄煙锛歕n" +
+        "\n" +
+        "鏍规嵁姘斾綋鎵╂暎鑼冨洿锛堝弬鑰冨簲鎬ュ搷搴旀寚鍗桬RG锛夌枏鏁e眳姘戞垨浣滀笟浜哄憳銆俓n" +
+        "\n" +
+        "閬垮厤浣庢醇澶勬粸鐣欙紙鏌愪簺姘斾綋姣旂┖姘旈噸锛屽纭寲姘級銆俓n" +
+        "\n" +
+        "3. 鎺у埗娉勬紡鎵╂暎\n" +
+        "鐗╃悊鏂规硶锛歕n" +
+        "\n" +
+        "瑕嗙洊娉勬紡鍙o紙濡傜敤娴告按妫夎鍑忓皯鎸ュ彂锛屼絾绂佺敤浜庨亣姘村弽搴旀皵浣撳姘皵锛夈�俓n" +
+        "\n" +
+        "绛戝牑鍥村牭娑蹭綋娉勬紡鐗╋紝闃叉娴佸叆涓嬫按閬撴垨娌虫祦銆俓n" +
+        "\n" +
+        "鍖栧鏂规硶锛歕n" +
+        "\n" +
+        "涓拰澶勭悊锛堝姘ㄦ皵娉勬紡鍠锋磼绋�鐩愰吀锛岄渶涓撲笟浜哄憳鎿嶄綔锛夈�俓n" +
+        "\n" +
+        "浣跨敤鍚搁檮鏉愭枡锛堝娲绘�х偔銆佹矙鍦熷惛闄勬湁鏈烘皵浣擄級銆�"
+}
+
+export function operate(){
+    return "涓�銆佹搷浣滀笉褰撳彂鐢熷悗鐨勫簲鎬ュ鐞哱n" +
+        "1. 绔嬪嵆鎺у埗浜嬫晠\n" +
+        "鍋滄鎿嶄綔锛歕n" +
+        "\n" +
+        "鎸変笅绱ф�ュ仠鏈烘寜閽紝鍏抽棴鏈�杩戠殑涓婃父闃�闂ㄣ�俓n" +
+        "\n" +
+        "鍚姩搴旀�ラ妗堬細\n" +
+        "\n" +
+        "灏忓瀷娉勬紡锛氫娇鐢ㄥ簲鎬ュ牭婕忓伐鍏凤紙濡傚瘑灏佽兌銆佸す鍏凤級銆俓n" +
+        "\n" +
+        "澶у瀷娉勬紡锛氱枏鏁d汉鍛橈紝鎶ヨ姹傚姪锛�119/鐜繚閮ㄩ棬锛夈�俓n" +
+        "\n" +
+        "2. 浜哄憳瀹夊叏\n" +
+        "鎾ょ涓庨殧绂伙細\n" +
+        "\n" +
+        "閫嗛鎾ょ鑷充笂椋庡悜瀹夊叏鍖猴紝閬垮厤浣庢醇澶勶紙閲嶆皵浣撶Н鑱氾級銆俓n" +
+        "\n" +
+        "鎬ユ晳鎺柦锛歕n" +
+        "\n" +
+        "鍚稿叆鏈夋瘨姘斾綋锛氱Щ鑷崇┖姘旀柊椴滃锛屽繀瑕佹椂浜哄伐鍛煎惛銆俓n" +
+        "\n" +
+        "鐨偆鎺ヨЕ锛氱珛鍗崇敤娓呮按鍐叉礂15鍒嗛挓锛堣厫铓�鎬ф皵浣擄級銆俓n" +
+        "\n" +
+        "3. 浜嬫晠璋冩煡涓庢暣鏀筡n" +
+        "鏍规湰鍘熷洜鍒嗘瀽锛圧CA锛夛細\n" +
+        "\n" +
+        "鏄搷浣滃け璇�佸煿璁笉瓒筹紝杩樻槸璁惧缂洪櫡锛焅n" +
+        "\n" +
+        "鏀硅繘鎺柦锛歕n" +
+        "\n" +
+        "淇鎿嶄綔瑙勭▼锛屽鍔犺绀烘爣璇嗐�俓n" +
+        "\n" +
+        "瀵硅矗浠讳汉鍐嶅煿璁紝蹇呰鏃惰皟宀椼��"
+}
+
+export function emergency(){
+    return "涓�銆佷紭鍖栧簲鎬ュ搷搴旂殑鍏抽敭鎺柦\n" +
+        "1. 瀹屽杽搴旀�ラ妗圽n" +
+        "閽堝鎬ц璁★細\n" +
+        "\n" +
+        "鍩轰簬HAZOP锛堝嵄闄╀笌鍙搷浣滄�у垎鏋愶級璇嗗埆鎵�鏈夋綔鍦ㄩ闄╁満鏅�俓n" +
+        "\n" +
+        "鍒跺畾鍒嗙骇鍝嶅簲鏈哄埗锛堝皬娉勬紡鐜板満澶勭疆銆佸ぇ娉勬紡鍏ㄥ憳鐤忔暎锛夈�俓n" +
+        "\n" +
+        "鏄庣‘鑱岃矗锛歕n" +
+        "\n" +
+        "璁剧珛搴旀�ユ寚鎸ラ儴锛屾寚瀹氭�绘寚鎸ャ�侀�氳缁勩�佹姠闄╃粍銆佸尰鐤楃粍绛夈�俓n" +
+        "\n" +
+        "纭繚24灏忔椂鍊肩彮鍒跺害锛岃仈绯绘柟寮忓疄鏃舵洿鏂般�俓n" +
+        "\n" +
+        "鑱斿姩澶栭儴璧勬簮锛歕n" +
+        "\n" +
+        "涓庢秷闃层�佺幆淇濄�佸尰闄㈡彁鍓嶇璁㈡晳鎻村崗璁紝鏄庣‘鍗忎綔娴佺▼銆俓n" +
+        "\n" +
+        "2. 寮哄寲搴旀�ヨ祫婧愪繚闅淺n" +
+        "瑁呭涓庣墿璧勶細\n" +
+        "\n" +
+        "閰嶅瓒抽噺涓旀湁鏁堢殑搴旀�ヨ澶囷紝鍖呮嫭锛歕n" +
+        "\n" +
+        "涓汉闃叉姢瑁呭锛圥PE锛夛細闃叉瘨闈㈠叿銆佸寲瀛﹂槻鎶ゆ湇銆俓n" +
+        "\n" +
+        "鍫垫紡宸ュ叿锛氬瘑灏佽兌銆佸す鍏枫�佸揩閫熷皝鍫靛櫒銆俓n" +
+        "\n" +
+        "鍚搁檮/涓拰鏉愭枡锛氭椿鎬х偔銆佹矙鍦熴�佺█纰辨恫锛堢敤浜庨吀鎬ф皵浣擄級銆俓n" +
+        "\n" +
+        "瀹氭湡妫�鏌ャ�佺淮鎶ゅ拰鏇存崲锛堝姘旂摱鍘嬪姏銆佷紶鎰熷櫒鐢垫睜锛夈�俓n" +
+        "\n" +
+        "搴旀�ヨ溅杈嗕笌閫氶亾锛歕n" +
+        "\n" +
+        "纭繚鏁戞彺杞﹁締鍙揩閫熸姷杈炬硠婕忕偣锛堟竻闄よ矾闅滐紝鏍囪瘑搴旀�ヨ矾绾匡級銆俓n" +
+        "\n" +
+        "鍏抽敭鍖哄煙璁剧疆搴旀�ユ礂鐪煎櫒銆佸柗娣嬬郴缁熴�俓n" +
+        "\n" +
+        "3. 鍔犲己浜哄憳鍩硅涓庤兘鍔涘缓璁綷n" +
+        "鍒嗗眰鍩硅锛歕n" +
+        "\n" +
+        "鍩哄眰浜哄憳锛氭帉鎻″熀鏈簲鎬ュ缃紙濡傚叧闂榾闂ㄣ�佷娇鐢ㄧ伃鐏櫒锛夈�俓n" +
+        "\n" +
+        "搴旀�ュ皬缁勶細涓撲笟鍫垫紡銆佷激鍛樻�ユ晳銆佹皵浣撴娴嬫妧鑳姐�俓n" +
+        "\n" +
+        "绠$悊灞傦細鎸囨尌鍐崇瓥銆佸獟浣撴矡閫氥�佹硶寰嬪悎瑙勩�俓n" +
+        "\n" +
+        "瀹炴垬鍖栬�冩牳锛歕n" +
+        "\n" +
+        "閫氳繃妯℃嫙绐佸彂娉勬紡锛堝鐩叉紨锛夋楠屽搷搴旈�熷害銆俓n" +
+        "\n" +
+        "涓嶅悎鏍艰�呴渶閲嶆柊鍩硅銆俓n" +
+        "\n" +
+        "4. 瀹氭湡婕旂粌涓庢寔缁敼杩沑n" +
+        "婕旂粌棰戠巼锛歕n" +
+        "\n" +
+        "姣忓搴﹁嚦灏�1娆℃闈㈡帹婕旓紝姣忓勾2娆$患鍚堝疄鎴樻紨缁冦�俓n" +
+        "\n" +
+        "鍦烘櫙璁捐锛歕n" +
+        "\n" +
+        "妯℃嫙澶嶆潅鎯呭喌锛堝澶滈棿鍋滅數銆佸浜哄彈浼わ級銆俓n" +
+        "\n" +
+        "寮曞叆鈥滅獊鍙戝彉閲忊�濓紙濡傞鍚戠獊鍙樸�佷簩娆℃硠婕忥級銆俓n" +
+        "\n" +
+        "澶嶇洏涓庝紭鍖栵細\n" +
+        "\n" +
+        "璁板綍婕旂粌涓殑闂锛堝閫氳寤惰繜銆佽澶囩己澶憋級銆俓n" +
+        "\n" +
+        "鏇存柊棰勬骞朵笅鍙戝涔犮�俓n" +
+        "\n" +
+        "5. 鎶�鏈崌绾т笌鏅鸿兘鍖栨敮鎸乗n" +
+        "瀹炴椂鐩戞祴涓庨璀︼細\n" +
+        "\n" +
+        "閮ㄧ讲鐗╄仈缃戯紙IoT锛変紶鎰熷櫒锛岀洃娴嬫皵浣撴祿搴︺�佽澶囩姸鎬併�俓n" +
+        "\n" +
+        "璁剧疆鑷姩鑱旈攣鎺у埗锛堝娉勬紡鏃惰仈鍔ㄥ叧闂榾闂ㄥ苟鍚姩閫氶锛夈�俓n" +
+        "\n" +
+        "搴旀�ラ�氳绯荤粺锛歕n" +
+        "\n" +
+        "浣跨敤闃茬垎瀵硅鏈恒�佸崼鏄熺數璇濓紙淇濋殰淇″彿瑕嗙洊锛夈�俓n" +
+        "\n" +
+        "寤虹珛搴旀�ュ箍鎾郴缁燂紙濡傚巶鍖鸿鎶ャ�佺煭淇$兢鍙戯級銆俓n" +
+        "\n" +
+        "鏁板瓧鍖栭妗堬細\n" +
+        "\n" +
+        "灏嗗簲鎬ラ妗堝綍鍏ョЩ鍔ㄧ粓绔紝瀹炵幇涓�閿皟闃呫�佹楠ゆ寚寮曘��"
+}
+
+export function compliance(){
+    return "涓�銆佸父瑙佺殑鍚堣鎬ч棶棰榎n" +
+        "1. 璁稿彲涓庤祫璐ㄧ己澶盶n" +
+        "闂锛歕n" +
+        "\n" +
+        "鏈彇寰楀嵄闄╁寲瀛﹀搧缁忚惀璁稿彲璇佹垨瀹夊叏鐢熶骇璁稿彲璇併�俓n" +
+        "\n" +
+        "鐗圭浣滀笟浜哄憳锛堝鍘嬪姏瀹瑰櫒鎿嶄綔宸ワ級鏃犺瘉涓婂矖銆俓n" +
+        "\n" +
+        "椋庨櫓锛歕n" +
+        "\n" +
+        "鐩戠閮ㄩ棬澶勭綒锛堝缃氭銆佽矗浠ゅ仠浜э級銆俓n" +
+        "\n" +
+        "淇濋櫓鎷掕禂锛堜簨鏁呭彂鐢熸椂锛夈�俓n" +
+        "\n" +
+        "2. 瀹夊叏璁捐涓嶈揪鏍嘰n" +
+        "闂锛歕n" +
+        "\n" +
+        "鍌ㄧ綈銆佺閬撴湭鎸塆B/T 150锛堝帇鍔涘鍣ㄦ爣鍑嗭級璁捐銆俓n" +
+        "\n" +
+        "鏈畨瑁呭彲鐕�/鏈夋瘨姘斾綋鎶ヨ鍣紙杩濆弽GB 50493锛夈�俓n" +
+        "\n" +
+        "椋庨櫓锛歕n" +
+        "\n" +
+        "璁惧澶辨晥瀵艰嚧娉勬紡鎴栫垎鐐搞�俓n" +
+        "\n" +
+        "涓嶇鍚堝簲鎬ョ鐞嗛儴鎴朞SHA妫�鏌ヨ姹傘�俓n" +
+        "\n" +
+        "3. 鎿嶄綔涓庣淮鎶よ繚瑙刓n" +
+        "闂锛歕n" +
+        "\n" +
+        "鏈墽琛屼綔涓氱エ鍒跺害锛堝鍔ㄧ伀浣滀笟鏈鎵癸級銆俓n" +
+        "\n" +
+        "鏈畾鏈熸楠屽帇鍔涘鍣紙杩濆弽TSG 21-2016锛夈�俓n" +
+        "\n" +
+        "椋庨櫓锛歕n" +
+        "\n" +
+        "杩濊鎿嶄綔寮曞彂浜嬫晠锛堝鐒婃帴寮曞彂鍙噧姘斾綋鐖嗙偢锛夈�俓n" +
+        "\n" +
+        "璁惧鑰佸寲瀵艰嚧绐佸彂娉勬紡銆俓n" +
+        "\n" +
+        "4. 搴旀�ョ鐞嗕笉鍚堣\n" +
+        "闂锛歕n" +
+        "\n" +
+        "鏈埗瀹氬簲鎬ラ妗堟垨鏈妗堬紙杩濆弽銆婄敓浜у畨鍏ㄤ簨鏁呭簲鎬ユ潯渚嬨�嬶級銆俓n" +
+        "\n" +
+        "鏈厤澶囧簲鎬ョ墿璧勶紙濡傞槻姣掗潰鍏枫�佸牭婕忓伐鍏凤級銆俓n" +
+        "\n" +
+        "椋庨櫓锛歕n" +
+        "\n" +
+        "浜嬫晠鍙戠敓鏃舵棤娉曟湁鏁堟帶鍒讹紝瀵艰嚧鎹熷け鎵╁ぇ銆俓n" +
+        "\n" +
+        "闈复鐢熸�佺幆澧冮儴杩借矗锛堝鍖栧鍝佹薄鏌撳湡澹�/姘翠綋锛夈�俓n" +
+        "\n" +
+        "5. 璁板綍涓庢姤鍛婄己澶盶n" +
+        "闂锛歕n" +
+        "\n" +
+        "鏈繚瀛樺畨鍏ㄦ鏌ヨ褰曟垨鍩硅妗f銆俓n" +
+        "\n" +
+        "鏈寜瑙勫畾涓婃姤娉勬紡浜嬫晠锛堝鐬掓姤銆佽繜鎶ワ級銆俓n" +
+        "\n" +
+        "椋庨櫓锛歕n" +
+        "\n" +
+        "浜嬫晠璋冩煡鏃舵棤娉曡嚜璇佸悎瑙勶紝鎵挎媴鍏ㄨ矗銆俓n" +
+        "\n" +
+        "琚垪鍏ュ畨鍏ㄧ敓浜ч粦鍚嶅崟锛屽奖鍝嶄紒涓氫俊瑾夈��"
+}
+
+export function monitoring(){
+    return "涓�銆佸浐瀹氬紡鐩戞祴鎶�鏈痋n" +
+        "1. 鍌寲鐕冪儳寮忎紶鎰熷櫒\n" +
+        "鍘熺悊锛氬彲鐕冩皵浣撳湪閾備笣琛ㄩ潰鐕冪儳瀵艰嚧鐢甸樆鍙樺寲\n" +
+        "\n" +
+        "浼樺娍锛氭垚鏈綆锛堬骏500-2000/涓級銆佸搷搴斿揩锛�<10s锛塡n" +
+        "\n" +
+        "灞�闄愶細鏄撲腑姣掞紙纭�/纭寲鍚堢墿锛夈�佸鍛界煭锛�2-3骞达級\n" +
+        "\n" +
+        "閫傜敤锛氱煶鍖栧巶鍙噧姘旂洃娴嬶紙鐢茬兎銆佹阿姘旂瓑锛塡n" +
+        "\n" +
+        "2. 鐢靛寲瀛︿紶鎰熷櫒\n" +
+        "鍘熺悊锛氭皵浣撲笌鐢佃В娑插彂鐢熸哀鍖栬繕鍘熷弽搴斾骇鐢熺數娴乗n" +
+        "\n" +
+        "浼樺娍锛歱pb绾ф娴嬶紙濡侶2S妫�娴嬩笅闄�0.1ppm锛塡n" +
+        "\n" +
+        "灞�闄愶細鍙楁俯婀垮害褰卞搷锛堥渶瀹氭湡鏍″噯锛塡n" +
+        "\n" +
+        "閫傜敤锛氭湁姣掓皵浣擄紙Cl鈧傘�丯H鈧冦�丆O绛夛級\n" +
+        "\n" +
+        "3. 绾㈠鍚告敹寮忥紙NDIR锛塡n" +
+        "鍘熺悊锛氭皵浣撳鐗瑰畾绾㈠娉㈡鐨勫惛鏀剁巼妫�娴媆n" +
+        "\n" +
+        "浼樺娍锛氬厤鏍″噯锛堝鍛�5-10骞达級銆佹姉涓瘨\n" +
+        "\n" +
+        "灞�闄愶細楂樻垚鏈紙锟�5000+/涓級\n" +
+        "\n" +
+        "閫傜敤锛欳O鈧傘�丆H鈧勭瓑娓╁姘斾綋鐩戞祴\n" +
+        "\n" +
+        "4. 婵�鍏夊厜璋憋紙TDLAS锛塡n" +
+        "鍘熺悊锛氬彲璋冭皭婵�鍏変簩鏋佺鎵弿姘斾綋鍚告敹绾縗n" +
+        "\n" +
+        "浼樺娍锛歱pm绾х簿搴︺�佸搷搴攎s绾n" +
+        "\n" +
+        "灞�闄愶細闇�鍏夊瀵瑰噯锛堝畨瑁呭鏉傦級\n" +
+        "\n" +
+        "閫傜敤锛氱閬撳井娉勬紡妫�娴嬶紙澶╃劧姘旈暱杈撶绾匡級"
+}
+
+export function checking(keyWord){
+    if(keyWord.includes("姘斾綋娉勬紡")){
+        return gasLeaks();
+    }
+    if(keyWord.includes("瀹瑰櫒澶辨晥")){
+        return shipping();
+    }
+    if(keyWord.includes("鎿嶄綔涓嶅綋")){
+        return operate();
+    }
+    if(keyWord.includes("鍝嶅簲涓嶈冻")){
+        return emergency();
+    }
+    if(keyWord.includes("鍚堣鎬�")){
+        return compliance();
+    }
+    if(keyWord.includes("鐩戞祴鎶�鏈�")){
+        return monitoring();
+    }
+    return "涓嶅ソ鎰忔�濓紝灏忔櫤杩樺湪鎴愰暱杩囩▼涓紝鎮ㄧ殑闂宸茬粡瓒呰繃灏忔櫤鐨勫鐞嗚寖鍥翠簡銆�";
+
+}
\ No newline at end of file
diff --git a/src/views/chatHome/chatHomeIndex/home.vue b/src/views/chatHome/chatHomeIndex/home.vue
new file mode 100644
index 0000000..7796284
--- /dev/null
+++ b/src/views/chatHome/chatHomeIndex/home.vue
@@ -0,0 +1,175 @@
+<template>
+<div class="home">
+    <div style="background: white;color: black;font-size: 30px;" class="logo">
+        <div class="logo-one" style="font-weight: bold">
+<!--            <img src="/src/assets/img/logo.png" style="width: 50px;height: 50px;margin: 0 10px" />-->
+            <div><i>澶фā鍨婣I灏忔櫤姝e湪涓烘偍鏈嶅姟</i></div>
+        </div>
+        <div class="input">
+            <input type="text" v-model="keyWord" class="input-text" placeholder="缁欏皬鏅哄彂閫佹秷鎭�"  @keyup.enter="sendMsg" />
+            <div style="font-size: 13px;color: #808080;display: flex;justify-content: space-between;padding: 10px;">
+                <div style="display: flex;justify-content: center;align-items: center;">
+<!--                    <div style="display: flex;justify-content: center;align-items: center;">-->
+<!--                        <img src="/src/assets/img/logo.png" style="width: 15px;height: 15px;margin: 0 5px" />-->
+<!--                        <span>娣卞害鎬濊��(R1)</span>-->
+<!--                    </div>-->
+<!--                    <div style="display: flex;justify-content: center;align-items: center;">-->
+<!--                        <img src="/src/assets/img/logo.png" style="width: 15px;height: 15px;margin: 0 5px" />-->
+<!--                        <span>鑱旂綉鎼滅储</span>-->
+<!--                    </div>-->
+                </div>
+                <div style="display: flex;justify-content: center;align-items: center;margin-right: 5px;">
+<!--                    <img src="/src/assets/img/logo.png" style="width: 25px;height: 25px;margin: 0 5px" />-->
+                    <img src="@/assets/img/emoji/rocket.png" style="width: 25px;height: 25px;margin: 0 5px" @click="sendMsg"/>
+                </div>
+            </div>
+        </div>
+        <div style="width: 780px;">
+            <div style="font-weight: bold;margin: 30px 0;">鐑棬鎺ㄨ崘</div>
+            <div class="keywords">
+                <div class="keywordss" @click="sendMsgDefault(keyWordOne)">
+                    <p class="fontSize aaa">{{keyWordOne}}</p>
+                    <p class="fontSize">闃�闂ㄣ�佺閬撴垨瀹瑰櫒瀵嗗皝澶辨晥瀵艰嚧姘斾綋娉勬紡锛堝姘皵銆佹皑姘旓級銆�</p>
+                    <p class="fontSize">鍚庢灉锛氫腑姣掋�佺垎鐐搞�佺幆澧冩薄鏌撱��</p>
+                </div>
+                <div class="keywordss" @click="sendMsgDefault(keyWordTwo)">
+                    <p class="fontSize aaa">{{keyWordTwo}}</p>
+                    <p class="fontSize">閽㈢摱鎴栫綈浣撳洜鏉愭枡鐤插姵銆佽厫铓�鎴栬秴鍘嬬牬瑁�</p>
+                    <p class="fontSize">鍘熷洜锛氭湭瀹氭湡妫�娴嬨�佽繚瑙勫厖瑁呮垨澶栭儴鎾炲嚮銆傘��</p>
+                </div>
+            </div>
+            <div class="keywords">
+                <div class="keywordss" @click="sendMsgDefault(keyWordFive)">
+                    <p class="fontSize aaa">{{keyWordFive}}</p>
+                    <p class="fontSize">瑁呭嵏杩囩▼涓繚瑙勬搷浣滐紙濡傞噹铔惉杩愩�佹贩瑁呯蹇岀墿璐級銆�</p>
+                    <p class="fontSize">杩愯緭閫斾腑鏈浐瀹氬鍣紝瀵艰嚧纰版挒鎴栧�惧�掋��</p>
+                </div>
+                <div class="keywordss" @click="sendMsgDefault(keyWordSix)">
+                    <p class="fontSize aaa">{{keyWordSix}}</p>
+                    <p class="fontSize">缂轰箯娉勬紡搴旀�ラ妗堬紝浜哄憳鍩硅涓嶈冻銆�</p>
+                    <p class="fontSize">鏁戞彺璁惧锛堝闃叉瘨闈㈠叿銆佸牭婕忓伐鍏凤級缂哄け鎴栧け鏁堛��</p>
+                </div>
+            </div>
+            <div class="keywords">
+                <div class="keywordss" @click="sendMsgDefault(keyWordServen)">
+                    <p class="fontSize aaa">{{keyWordServen}}</p>
+                    <p class="fontSize">鏈彇寰楄繍杈撹祫璐紙濡侫DR/RID绛夊浗闄呰鑼冿級銆�</p>
+                    <p class="fontSize">璺嚎瑙勫垝涓嶅悎瑙勶紙濡傜┛瓒婁汉鍙e瘑闆嗗尯锛夈��</p>
+                </div>
+                <div class="keywordss" @click="sendMsgDefault(keyWordEight)">
+                    <p class="fontSize aaa">{{keyWordEight}}</p>
+                    <p class="fontSize">浼犳劅鍣ㄩ儴缃诧紙濡傜孩澶栨皵浣撴帰娴嬪櫒銆佺數鍖栧浼犳劅鍣級銆�</p>
+                    <p class="fontSize">瀹炴椂鏁版嵁浼犺緭鑷崇洃鎺у钩鍙帮紝瑙﹀彂鎶ヨ銆�</p>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div></div>
+</div>
+</template>
+
+<script setup>
+import { ref,onMounted } from "vue";
+import {useRoute,useRouter} from "vue-router"
+const route = useRoute();
+const router = useRouter();
+const keyWord = ref('');
+const keyWordOne = ref('鍗遍櫓姘斾綋娉勬紡鎬庝箞鍔�');
+const keyWordTwo = ref('杩愯緭瀹瑰櫒澶辨晥鎬庝箞鍔�');
+const keyWordFive = ref('鎿嶄綔涓嶅綋鎬庝箞鍔�');
+const keyWordSix = ref('搴旀�ュ搷搴斾笉瓒虫�庝箞鍔�');
+const keyWordServen = ref('鍚堣鎬ч棶棰�');
+const keyWordEight = ref('娉勬紡鐩戞祴鎶�鏈湁鍝簺');
+
+const sendMsg = () => {
+    router.push({ path: '/main/MobileChat',query:{ keyWord: keyWord.value} })
+}
+
+const sendMsgDefault = (value) => {
+    router.push({ path: '/main/MobileChat',query:{ keyWord: value} })
+}
+
+</script>
+
+<style lang="scss" scoped>
+.home {
+  width: 100%;
+  height: 91vh;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+
+  .logo {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    flex-direction: column;
+    z-index: 99;
+    width: 100%;
+    height: 100%;
+    color: #fff;
+    cursor: pointer;
+    overflow: hidden;
+    background-color: #F0F6F9;
+
+    .keywords {
+      display: flex;
+      width: 100%;
+      height: 90px;
+      line-height: 80px;
+      justify-content: space-between;
+      margin: 10px 0;
+
+      .keywordss {
+        box-shadow: 0px 2px 5px #b8b8b8;
+        width: 48%;
+        background: #e0edfc;
+        border-radius: 10px;
+
+        .aaa {
+          font-weight: bold;
+          font-size: 15px !important;
+        }
+
+        .fontSize {
+          font-size: 13px;
+          height: 20px;
+          line-height: 20px;
+          margin: 6px;
+        }
+      }
+    }
+
+    .logo-one {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      margin-bottom: 20px;
+    }
+
+    .input {
+      width: 780px;
+      height: 150px;
+      background: #f5f4f4;
+      border-radius: 20px;
+
+      .input-text {
+        font-size: 18px;
+        width: 568px;
+        border-radius: 20px 20px 0 0;
+        height: 90px;
+        padding-left: 10px;
+        border: none;
+        color: black;
+        background-color: #f5f4f4;
+      }
+
+      .input-text:focus {
+        outline: none;
+        border: none;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index 847f4c4..403cab6 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -102,6 +102,10 @@
               <div v-if="!activity.isShen" class="node-reason">
                 <span>瀹℃壒鎰忚锛�</span>{{ activity.approveNodeReason }}
               </div>
+              <div v-if="!activity.isShen" class="node-reason">
+                <span>绛惧悕锛�</span>
+								<img :src="activity.urlTem" class="signImg" alt="" v-if="activity.urlTem"/>
+              </div>
               <div v-else-if="activity.isShen">
                 <el-form-item
                   :prop="'activities.' + index + '.approveNodeReason'"
@@ -117,16 +121,33 @@
       <template #footer v-if="operationType === 'approval'">
         <div class="dialog-footer">
           <el-button type="primary" @click="submitForm(2)">涓嶉�氳繃</el-button>
-          <el-button type="primary" @click="submitForm(1)">閫氳繃</el-button>
+          <el-button type="primary" @click="openSignatureDialog(1)">閫氳繃</el-button>
           <el-button @click="closeDia">鍙栨秷</el-button>
         </div>
       </template>
+    </el-dialog>
+    <!-- 鐢靛瓙绛惧悕寮圭獥锛坴ue3-signature-pad锛� -->
+    <el-dialog v-model="signatureDialogVisible" title="鐢靛瓙绛惧悕" width="600px" append-to-body>
+			<vueEsign
+				ref="esign"
+				class="mySign"
+				:width="800"
+				:height="300"
+				:isCrop="isCrop"
+				:lineWidth="lineWidth"
+				:lineColor="lineColor"
+			/>
+      <div style="margin-top:10px;">
+        <el-button @click="clearSignature">娓呴櫎</el-button>
+        <el-button type="primary" @click="confirmSignature">纭畾</el-button>
+      </div>
     </el-dialog>
   </div>
 </template>
 
 <script setup>
-import {getCurrentInstance, reactive, ref, toRefs} from "vue";
+import { getCurrentInstance, reactive, ref, toRefs } from "vue";
+import vueEsign from "vue-esign";
 import {
 	approveProcessDetails,
 	getDept,
@@ -135,6 +156,7 @@
 import useUserStore from "@/store/modules/user.js";
 import {userListNoPageByTenantId} from "@/api/system/user.js";
 import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
+import { getToken } from "@/utils/auth";
 const emit = defineEmits(['close'])
 const { proxy } = getCurrentInstance()
 
@@ -156,6 +178,22 @@
 	},
 });
 const { form } = toRefs(data);
+const signatureDialogVisible = ref(false);
+const signatureImg = ref('');
+let submitStatus = null; // 涓存椂瀛樺偍閫氳繃/涓嶉�氳繃鐘舵��
+const isCrop = ref("");
+const esign = ref(null);
+const lineWidth = ref(0);
+const lineColor = ref("#000000");
+
+// 涓婁紶閰嶇疆
+const upload = reactive({
+  // 涓婁紶鐨勫湴鍧�
+  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+  // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+  headers: { Authorization: "Bearer " + getToken() },
+});
+
 // 鑺傜偣鏍囬
 const getNodeTitle = (index, len) => {
   if (index === len - 1) return '缁撴潫';
@@ -190,6 +228,11 @@
     activities.value = res.data
     // 澧炲姞isApproval瀛楁
     activities.value.forEach(item => {
+			if (item.url && item.url.includes('word')) {
+				item.urlTem = item.url.replaceAll('word', 'img')
+			} else {
+				item.urlTem = item.url
+			}
       if (item.approveNodeStatus === 2) {
         item.isApproval = '宸查┏鍥�';
       } else if (item.approveNodeStatus === 1) {
@@ -205,17 +248,84 @@
 		productOptions.value = res.data;
 	});
 };
+// 鎵撳紑绛惧悕寮圭獥
+const openSignatureDialog = (status) => {
+  submitStatus = status;
+  signatureDialogVisible.value = true;
+};
+// 娓呴櫎绛惧悕
+const clearSignature = () => {
+	esign.value.reset();
+};
+// 纭绛惧悕
+const confirmSignature = () => {
+	esign.value.generate().then((res) => {
+		console.log(res);
+		// 灏哹ase64杞崲涓轰簩杩涘埗
+		const base64Data = res.split(',')[1]; // 绉婚櫎data:image/png;base64,鍓嶇紑
+		const binaryString = atob(base64Data);
+		const bytes = new Uint8Array(binaryString.length);
+		for (let i = 0; i < binaryString.length; i++) {
+			bytes[i] = binaryString.charCodeAt(i);
+		}
+		signatureImg.value = bytes;
+		
+		// 鍒涘缓鏂囦欢瀵硅薄鐢ㄤ簬涓婁紶
+		const blob = new Blob([bytes], { type: 'image/png' });
+		const file = new File([blob], 'signature.png', { type: 'image/png' });
+		
+		// 鍒涘缓FormData
+		const formData = new FormData();
+		formData.append('file', file);
+		
+		// 涓婁紶绛惧悕鍥剧墖
+		fetch(upload.url, {
+			method: 'POST',
+			headers: upload.headers,
+			body: formData
+		})
+		.then(response => response.json())
+		.then(data => {
+			if (data.code === 200) {
+				console.log('data---', data)
+				let tempFileIds = [];
+				tempFileIds.push(data.data.tempId);
+				signatureDialogVisible.value = false;
+				clearSignature();
+				// 鍙湁閫氳繃鏃舵墠浼犻�掔鍚嶆枃浠禝D
+				if (submitStatus === 1) {
+					submitForm(submitStatus, tempFileIds);
+				} else {
+					submitForm(submitStatus);
+				}
+			} else {
+				proxy.$modal.msgError("绛惧悕鍥剧墖涓婁紶澶辫触锛�" + data.msg);
+			}
+		})
+		.catch(error => {
+			console.error('涓婁紶澶辫触:', error);
+			proxy.$modal.msgError("绛惧悕鍥剧墖涓婁紶澶辫触");
+		});
+	}).catch((err) => {
+		console.log(err);
+		proxy.$modal.msgWarning("璇峰厛绛惧悕锛�");
+	})
+};
 // 鎻愪氦瀹℃壒
-const submitForm = (status) => {
+const submitForm = (status, tempFileIds) => {
   const filteredActivities = activities.value.filter(activity => activity.isShen);
-  filteredActivities[0].approveNodeStatus = status
+  filteredActivities[0].approveNodeStatus = status;
+  // 鍙湁閫氳繃鏃舵墠闇�瑕佺鍚�
+  if (status === 1 && tempFileIds) {
+    filteredActivities[0].tempFileIds = tempFileIds;
+  }
   // 鍒ゆ柇鏄惁涓烘渶鍚庝竴姝�
   const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1;
   updateApproveNode({ ...filteredActivities[0], isLast }).then(() => {
     proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
     closeDia();
-  })
-}
+  });
+};
 // 鍏抽棴寮规
 const closeDia = () => {
   proxy.resetForm("formRef");
@@ -253,4 +363,9 @@
 	height: 30px;
 	border-radius: 50px;
 }
+.signImg {
+	cursor: pointer;
+	width: 200px;
+	height: 60px;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/energyManagement/waterManagement/components/formDia.vue b/src/views/energyManagement/waterManagement/components/formDia.vue
new file mode 100644
index 0000000..2e58ea0
--- /dev/null
+++ b/src/views/energyManagement/waterManagement/components/formDia.vue
@@ -0,0 +1,221 @@
+<template>
+  <div>
+    <el-dialog
+        v-model="dialogFormVisible"
+        title="鐢ㄦ按璁惧"
+        width="70%"
+        @close="closeDia"
+    >
+			<el-form
+				:model="form"
+				label-width="140px"
+				label-position="top"
+				:rules="rules"
+				ref="formRef"
+			>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="璁惧锛�" prop="deviceModel">
+							<el-select
+								v-model="form.deviceModel"
+								placeholder="璇烽�夋嫨"
+								clearable
+								@change="setName"
+								:disabled="operationType !== 'add'"
+							>
+								<el-option
+									v-for="item in codeList"
+									:key="item.deviceModel"
+									:label="item.deviceName"
+									:value="item.deviceModel"
+								>
+									{{item.deviceName + '--' + item.deviceModel}}
+								</el-option>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="姣忔棩闄愬埗姘撮噺锛�" prop="waterDayLimit">
+							<el-input
+								v-model="form.waterDayLimit"
+								placeholder="璇疯緭鍏�"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="棰濆畾娴侀噺锛�" prop="ratedRate">
+							<el-input
+								v-model="form.ratedRate"
+								placeholder="璇疯緭鍏�"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="瀹為檯娴侀噺锛�" prop="actualTraffic">
+							<el-input
+								v-model="form.actualTraffic"
+								placeholder="璇疯緭鍏�"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="杩愯鏃堕棿锛�" prop="runTime">
+							<el-date-picker
+								style="width: 100%"
+								v-model="form.runTime"
+								value-format="YYYY-MM-DD"
+								format="YYYY-MM-DD"
+								type="date"
+								placeholder="璇烽�夋嫨"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="褰撴棩鐢ㄦ按閲忥細" prop="waterDay">
+							<el-input
+								v-model="form.waterDay"
+								placeholder="璇疯緭鍏�"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="姘磋垂鍗曚环锛�" prop="waterPrice">
+							<el-input
+								v-model="form.waterPrice"
+								placeholder="璇疯緭鍏�"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="鐢ㄦ按绫诲瀷锛�" prop="type">
+							<el-select
+								v-model="form.type"
+								placeholder="璇烽�夋嫨"
+								clearable
+							>
+								<el-option label="宸ヤ笟鐢ㄦ按" value="industrial" />
+								<el-option label="鐢熸椿鐢ㄦ按" value="domestic" />
+								<el-option label="娑堥槻鐢ㄦ按" value="fire" />
+								<el-option label="缁垮寲鐢ㄦ按" value="greening" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+			<template #footer>
+				<div class="dialog-footer">
+					<el-button type="primary" @click="submitForm">纭</el-button>
+					<el-button @click="closeDia">鍙栨秷</el-button>
+				</div>
+			</template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref, reactive, nextTick} from "vue";
+import useUserStore from "@/store/modules/user.js";
+import {waterDeviceList, waterEquipmentAdd, waterEquipmentUpdate} from "@/api/energyManagement/waterManagement.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const userStore = useUserStore();
+
+const data = reactive({
+	form: {
+    deviceName: "",
+    deviceModel: "",
+    waterDayLimit: "",
+    ratedRate: "",
+    actualTraffic: "",
+    runTime: "",
+    waterDay: "",
+		waterPrice: "",
+    type: "",
+	},
+	rules: {
+    deviceModel: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		runTime: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+    waterDayLimit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    ratedRate: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    actualTraffic: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    waterDay: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		waterPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    type: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+	},
+})
+const { form, rules } = toRefs(data);
+const codeList = ref([])
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+  operationType.value = type;
+  dialogFormVisible.value = true;
+	form.value = {}
+	proxy.resetForm("formRef");
+	waterDeviceList({size: -1}).then((res) => {
+		codeList.value = res.data.records;
+	});
+	if (type === "edit") {
+		form.value = {...row}
+	}
+}
+const setName = (code) => {
+	const index = codeList.value.findIndex(item => item.deviceModel === code);
+	if (index > -1) {
+		console.log(codeList)
+		form.value.name = codeList.value[index].deviceName;
+	}
+}
+const submitForm = () => {
+	proxy.$refs["formRef"].validate(valid => {
+		if (valid) {
+			if (operationType.value === "add") {
+				waterEquipmentAdd(form.value).then(response => {
+					proxy.$modal.msgSuccess("鏂板鎴愬姛")
+					closeDia()
+				})
+			} else {
+				waterEquipmentUpdate(form.value).then(response => {
+					proxy.$modal.msgSuccess("淇敼鎴愬姛")
+					closeDia()
+				})
+			}
+		}
+	})
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+	proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+  emit('close')
+};
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+	const today = new Date();
+	const year = today.getFullYear();
+	const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+	const day = String(today.getDate()).padStart(2, "0");
+	return `${year}-${month}-${day}`;
+}
+defineExpose({
+  openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/energyManagement/waterManagement/components/waterBillForm.vue b/src/views/energyManagement/waterManagement/components/waterBillForm.vue
new file mode 100644
index 0000000..a132041
--- /dev/null
+++ b/src/views/energyManagement/waterManagement/components/waterBillForm.vue
@@ -0,0 +1,210 @@
+<template>
+  <div>
+    <el-dialog
+        v-model="dialogFormVisible"
+        title="姘磋垂绠$悊"
+        width="70%"
+        @close="closeDia"
+    >
+			<el-form
+				:model="form"
+				label-width="140px"
+				label-position="top"
+				:rules="rules"
+				ref="formRef"
+			>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="璁惧锛�" prop="code">
+							<el-select
+								v-model="form.code"
+								placeholder="璇烽�夋嫨"
+								clearable
+								@change="setName"
+								:disabled="operationType !== 'add'"
+							>
+								<el-option
+									v-for="item in codeList"
+									:key="item.deviceModel"
+									:label="item.deviceName"
+									:value="item.deviceModel"
+								>
+									{{item.deviceName + '--' + item.deviceModel}}
+								</el-option>
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="鐢ㄦ按閲忥細" prop="waterConsumption">
+							<el-input
+								v-model="form.waterConsumption"
+								placeholder="璇疯緭鍏�"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="姘磋垂鍗曚环锛�" prop="waterPrice">
+							<el-input
+								v-model="form.waterPrice"
+								placeholder="璇疯緭鍏�"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="姘磋垂閲戦锛�" prop="waterBill">
+							<el-input
+								v-model="form.waterBill"
+								placeholder="鑷姩璁$畻"
+								clearable
+								disabled
+							/>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="璁¤垂鏃ユ湡锛�" prop="billDate">
+							<el-date-picker
+								style="width: 100%"
+								v-model="form.billDate"
+								value-format="YYYY-MM-DD"
+								format="YYYY-MM-DD"
+								type="date"
+								placeholder="璇烽�夋嫨"
+								clearable
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="鐢ㄦ按绫诲瀷锛�" prop="waterType">
+							<el-select
+								v-model="form.waterType"
+								placeholder="璇烽�夋嫨"
+								clearable
+							>
+								<el-option label="宸ヤ笟鐢ㄦ按" value="industrial" />
+								<el-option label="鐢熸椿鐢ㄦ按" value="domestic" />
+								<el-option label="娑堥槻鐢ㄦ按" value="fire" />
+								<el-option label="缁垮寲鐢ㄦ按" value="greening" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+			<template #footer>
+				<div class="dialog-footer">
+					<el-button type="primary" @click="submitForm">纭</el-button>
+					<el-button @click="closeDia">鍙栨秷</el-button>
+				</div>
+			</template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref, reactive, nextTick, watch} from "vue";
+import useUserStore from "@/store/modules/user.js";
+import {waterDeviceList, waterBillAdd, waterBillUpdate} from "@/api/energyManagement/waterManagement.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const userStore = useUserStore();
+
+const data = reactive({
+	form: {
+		name: "",
+		code: "",
+		waterConsumption: "",
+		waterPrice: "",
+		waterBill: "",
+		billDate: "",
+		waterType: "",
+	},
+	rules: {
+		code: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		waterConsumption: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		waterPrice: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		billDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		waterType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+	},
+})
+const { form, rules } = toRefs(data);
+const codeList = ref([])
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+  operationType.value = type;
+  dialogFormVisible.value = true;
+	form.value = {}
+	proxy.resetForm("formRef");
+	waterDeviceList().then((res) => {
+		codeList.value = res.data;
+	});
+	if (type === "edit") {
+		form.value = {...row}
+	}
+}
+const setName = (code) => {
+	const index = codeList.value.findIndex(item => item.deviceModel === code);
+	if (index > -1) {
+		console.log(codeList)
+		form.value.name = codeList.value[index].deviceName;
+	}
+}
+
+// 璁$畻姘磋垂閲戦
+const calculateWaterBill = () => {
+	if (form.value.waterConsumption && form.value.waterPrice) {
+		form.value.waterBill = (parseFloat(form.value.waterConsumption) * parseFloat(form.value.waterPrice)).toFixed(2);
+	}
+}
+
+// 鐩戝惉鐢ㄦ按閲忓拰姘磋垂鍗曚环鍙樺寲
+watch([() => form.value.waterConsumption, () => form.value.waterPrice], () => {
+	calculateWaterBill();
+});
+
+const submitForm = () => {
+	proxy.$refs["formRef"].validate(valid => {
+		if (valid) {
+			if (operationType.value === "add") {
+				waterBillAdd(form.value).then(response => {
+					proxy.$modal.msgSuccess("鏂板鎴愬姛")
+					closeDia()
+				})
+			} else {
+				waterBillUpdate(form.value).then(response => {
+					proxy.$modal.msgSuccess("淇敼鎴愬姛")
+					closeDia()
+				})
+			}
+		}
+	})
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+	proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+  emit('close')
+};
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+	const today = new Date();
+	const year = today.getFullYear();
+	const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
+	const day = String(today.getDate()).padStart(2, "0");
+	return `${year}-${month}-${day}`;
+}
+defineExpose({
+  openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/energyManagement/waterManagement/index.vue b/src/views/energyManagement/waterManagement/index.vue
new file mode 100644
index 0000000..181ae88
--- /dev/null
+++ b/src/views/energyManagement/waterManagement/index.vue
@@ -0,0 +1,312 @@
+<template>
+	<div class="app-container">
+		<div class="search_form">
+			<div>
+				<span class="search_title">璁惧鍚嶇О锛�</span>
+				<el-input
+					v-model="searchForm.deviceName"
+					style="width: 240px"
+					placeholder="璇疯緭鍏�"
+					@change="handleQuery"
+					clearable
+					:prefix-icon="Search"
+				/>
+				<el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+				>鎼滅储</el-button
+				>
+			</div>
+			<div>
+				<el-button type="primary" @click="openForm('add')">鏂板</el-button>
+				<el-button type="info" plain icon="Upload" @click="handleImport">瀵煎叆</el-button>
+				<el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+			</div>
+		</div>
+		<div class="table_list">
+			<PIMTable
+				rowKey="id"
+				:column="tableColumn"
+				:tableData="tableData"
+				:page="page"
+				:isSelection="true"
+				@selection-change="handleSelectionChange"
+				:tableLoading="tableLoading"
+				@pagination="pagination"
+			></PIMTable>
+		</div>
+		<form-dia ref="formDia" @close="handleQuery"></form-dia>
+		<el-dialog
+			:title="upload.title"
+			v-model="upload.open"
+			width="400px"
+			append-to-body
+			@close="handleDialogClose"
+		>
+			<el-upload
+				ref="uploadRef"
+				:limit="1"
+				accept=".xlsx, .xls"
+				:headers="upload.headers"
+				:action="upload.url"
+				:disabled="upload.isUploading"
+				:before-upload="upload.beforeUpload"
+				:on-progress="upload.onProgress"
+				:on-success="upload.onSuccess"
+				:on-error="upload.onError"
+				:on-change="upload.onChange"
+				:auto-upload="false"
+				drag
+			>
+				<el-icon class="el-icon--upload"><upload-filled /></el-icon>
+				<div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+				<template #tip>
+					<div class="el-upload__tip text-center">
+						<span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
+						<el-link
+							type="primary"
+							:underline="false"
+							style="font-size: 12px; vertical-align: baseline"
+							@click="importTemplate"
+							>涓嬭浇妯℃澘</el-link
+						>
+					</div>
+				</template>
+			</el-upload>
+			<template #footer>
+				<div class="dialog-footer">
+					<el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
+					<el-button @click="upload.open = false">鍙� 娑�</el-button>
+				</div>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script setup>
+import {Search} from "@element-plus/icons-vue";
+import {onMounted, ref, reactive, nextTick} from "vue";
+import FormDia from "@/views/energyManagement/waterManagement/components/formDia.vue";
+import {ElMessageBox} from "element-plus";
+import {getToken} from "@/utils/auth.js";
+import {waterEquipmentDelete, waterEquipmentListPage} from "@/api/energyManagement/waterManagement.js";
+const { proxy } = getCurrentInstance();
+
+const data = reactive({
+	searchForm: {
+		name: "",
+	},
+});
+const { searchForm } = toRefs(data);
+
+const selectedRows = ref([]);
+const tableColumn = ref([
+	{
+		label: "璁惧鍚嶇О",
+		prop: "deviceName",
+		width: 200,
+	},
+	{
+		label: "瑙勬牸鍨嬪彿",
+		prop: "deviceModel",
+		width: 200,
+	},
+	{
+		label: "棰濆畾娴侀噺",
+		prop: "ratedRate",
+	},
+	{
+		label: "瀹為檯娴侀噺",
+		prop: "actualTraffic",
+	},
+	{
+		label: "杩愯鏃堕棿",
+		prop: "runTime",
+		width:150
+	},
+	{
+		label: "褰撴棩鐢ㄦ按閲�",
+		prop: "waterDay",
+		width: 150,
+	},
+	{
+		label: "姣忔棩闄愬埗姘撮噺",
+		prop: "waterDayLimit",
+		width:220
+	},
+	{
+		label: "姘磋垂鍗曚环",
+		prop: "waterPrice",
+		width: 120,
+	},
+	{
+		dataType: "action",
+		label: "鎿嶄綔",
+		align: "center",
+		fixed: 'right',
+		operation: [
+			{
+				name: "缂栬緫",
+				type: "text",
+				clickFun: (row) => {
+					openForm("edit", row);
+				},
+			},
+		],
+	},
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+	current: 1,
+	size: 100,
+	total: 0,
+});
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+	selectedRows.value = selection;
+};
+const formDia = ref()
+const upload = reactive({
+	// 鏄惁鏄剧ず寮瑰嚭灞傦紙瀹㈡埛瀵煎叆锛�
+	open: false,
+	// 寮瑰嚭灞傛爣棰橈紙瀹㈡埛瀵煎叆锛�
+	title: "",
+	// 鏄惁绂佺敤涓婁紶
+	isUploading: false,
+	// 璁剧疆涓婁紶鐨勮姹傚ご閮�
+	headers: { Authorization: "Bearer " + getToken() },
+	// 涓婁紶鐨勫湴鍧�
+	url: import.meta.env.VITE_APP_BASE_API + "/waterRecord/importData",
+	// 鏂囦欢涓婁紶鍓嶇殑鍥炶皟
+	beforeUpload: (file) => {
+		console.log('鏂囦欢鍗冲皢涓婁紶', file);
+		// 鍙互鍦ㄦ澶勫仛鏂囦欢绫诲瀷鎴栧ぇ灏忔牎楠�
+		const isValid = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
+		if (!isValid) {
+			proxy.$modal.msgError("鍙兘涓婁紶 Excel 鏂囦欢");
+		}
+		return isValid;
+	},
+	// 鏂囦欢鐘舵�佹敼鍙樻椂鐨勫洖璋�
+	onChange: (file, fileList) => {
+		console.log('鏂囦欢鐘舵�佹敼鍙�', file, fileList);
+	},
+	// 鏂囦欢涓婁紶鎴愬姛鏃剁殑鍥炶皟
+	onSuccess: (response, file, fileList) => {
+		console.log('涓婁紶鎴愬姛', response, file, fileList);
+		if(response.code === 200){
+			proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+		}else if(response.code === 500){
+			proxy.$modal.msgError(response.msg);
+		}else{
+			proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+		}
+		upload.open = false;
+		getList();
+	},
+	// 鏂囦欢涓婁紶澶辫触鏃剁殑鍥炶皟
+	onError: (error, file, fileList) => {
+		console.log('涓婁紶澶辫触', error, file, fileList);
+		proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+		upload.open = false;
+	},
+	// 鏂囦欢涓婁紶杩涘害鏀瑰彉鏃剁殑鍥炶皟
+	onProgress: (event, file, fileList) => {
+		console.log('涓婁紶杩涘害', event, file, fileList);
+		upload.isUploading = true;
+	},
+});
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+	page.current = 1;
+	getList();
+};
+const pagination = (obj) => {
+	page.current = obj.page;
+	page.size = obj.limit;
+	getList();
+};
+
+const getList = () => {
+	tableLoading.value = true;
+	waterEquipmentListPage({ ...searchForm.value, ...page }).then((res) => {
+		tableLoading.value = false;
+		tableData.value = res.data.records;
+		page.total = res.data.total;
+	}).catch(() => {
+		tableLoading.value = false;
+	})
+};
+
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+	nextTick(() => {
+		formDia.value?.openDialog(type, row)
+	})
+};
+
+/** 瀵煎叆鎸夐挳鎿嶄綔 */
+function handleImport() {
+	upload.title = "鐢ㄦ按璁惧";
+	upload.open = true;
+	// 娓呯┖涓婃涓婁紶鐨勬枃浠跺垪琛�
+	nextTick(() => {
+		proxy.$refs["uploadRef"]?.clearFiles();
+	});
+}
+function importTemplate() {
+	proxy.download(
+		"/waterRecord/export",
+		{},
+		'鐢ㄦ按璁惧瀵煎叆妯$増.xlsx'
+	);
+}
+/** 鎻愪氦涓婁紶鏂囦欢 */
+function submitFileForm() {
+	proxy.$refs["uploadRef"].submit();
+}
+
+/** 寮规鍏抽棴鏃舵竻绌烘枃浠跺垪琛� */
+function handleDialogClose() {
+	nextTick(() => {
+		proxy.$refs["uploadRef"]?.clearFiles();
+	});
+}
+
+const handleDelete = () => {
+	let ids = [];
+	if (selectedRows.value.length > 0) {
+		ids = selectedRows.value.map((item) => item.id);
+	} else {
+		proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+		return;
+	}
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			tableLoading.value = true;
+			waterEquipmentDelete(ids)
+				.then((res) => {
+					proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+					getList();
+				})
+				.finally(() => {
+					tableLoading.value = false;
+				});
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
+};
+onMounted(() => {
+	getList();
+});
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/energyManagement/waterManagement/waterBill.vue b/src/views/energyManagement/waterManagement/waterBill.vue
new file mode 100644
index 0000000..ea382f0
--- /dev/null
+++ b/src/views/energyManagement/waterManagement/waterBill.vue
@@ -0,0 +1,181 @@
+<template>
+	<div class="app-container">
+		<div class="search_form">
+			<div>
+				<span class="search_title">璁惧鍚嶇О锛�</span>
+				<el-input
+					v-model="searchForm.name"
+					style="width: 240px"
+					placeholder="璇疯緭鍏�"
+					@change="handleQuery"
+					clearable
+					:prefix-icon="Search"
+				/>
+				<el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+				>鎼滅储</el-button
+				>
+			</div>
+			<div>
+				<el-button type="primary" @click="openForm('add')">鏂板</el-button>
+				<el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+			</div>
+		</div>
+		<div class="table_list">
+			<PIMTable
+				rowKey="id"
+				:column="tableColumn"
+				:tableData="tableData"
+				:page="page"
+				:isSelection="true"
+				@selection-change="handleSelectionChange"
+				:tableLoading="tableLoading"
+				@pagination="pagination"
+			></PIMTable>
+		</div>
+		<form-dia ref="formDia" @close="handleQuery"></form-dia>
+	</div>
+</template>
+
+<script setup>
+import {Search} from "@element-plus/icons-vue";
+import {onMounted, ref, reactive, nextTick} from "vue";
+import FormDia from "@/views/energyManagement/waterManagement/components/waterBillForm.vue";
+import {ElMessageBox} from "element-plus";
+import {waterBillDelete, waterBillListPage} from "@/api/energyManagement/waterManagement.js";
+const { proxy } = getCurrentInstance();
+
+const data = reactive({
+	searchForm: {
+		name: "",
+	},
+});
+const { searchForm } = toRefs(data);
+
+const selectedRows = ref([]);
+const tableColumn = ref([
+	{
+		label: "璁惧鍚嶇О",
+		prop: "name",
+		width: 200,
+	},
+	{
+		label: "瑙勬牸鍨嬪彿",
+		prop: "code",
+		width: 200,
+	},
+	{
+		label: "鐢ㄦ按閲�",
+		prop: "waterConsumption",
+	},
+	{
+		label: "姘磋垂鍗曚环",
+		prop: "waterPrice",
+	},
+	{
+		label: "姘磋垂閲戦",
+		prop: "waterBill",
+		width:150
+	},
+	{
+		label: "璁¤垂鏃ユ湡",
+		prop: "billDate",
+		width: 150,
+	},
+	{
+		label: "鐢ㄦ按绫诲瀷",
+		prop: "waterType",
+		width:120
+	},
+	{
+		dataType: "action",
+		label: "鎿嶄綔",
+		align: "center",
+		fixed: 'right',
+		operation: [
+			{
+				name: "缂栬緫",
+				type: "text",
+				clickFun: (row) => {
+					openForm("edit", row);
+				},
+			},
+		],
+	},
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+	current: 1,
+	size: 100,
+	total: 0,
+});
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+	selectedRows.value = selection;
+};
+const formDia = ref()
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+	page.current = 1;
+	getList();
+};
+const pagination = (obj) => {
+	page.current = obj.page;
+	page.size = obj.limit;
+	getList();
+};
+
+const getList = () => {
+	tableLoading.value = true;
+	waterBillListPage({ ...searchForm.value, ...page }).then((res) => {
+		tableLoading.value = false;
+		tableData.value = res.data.records;
+		page.total = res.data.total;
+	});
+};
+
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+	nextTick(() => {
+		formDia.value?.openDialog(type, row)
+	})
+};
+
+const handleDelete = () => {
+	let ids = [];
+	if (selectedRows.value.length > 0) {
+		ids = selectedRows.value.map((item) => item.id);
+	} else {
+		proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+		return;
+	}
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			tableLoading.value = true;
+			waterBillDelete(ids)
+				.then((res) => {
+					proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+					getList();
+				})
+				.finally(() => {
+					tableLoading.value = false;
+				});
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
+};
+onMounted(() => {
+	getList();
+});
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/energyManagement/waterManagement/waterTrends.vue b/src/views/energyManagement/waterManagement/waterTrends.vue
new file mode 100644
index 0000000..12e45fc
--- /dev/null
+++ b/src/views/energyManagement/waterManagement/waterTrends.vue
@@ -0,0 +1,118 @@
+<template>
+	<div class="app-container">
+		<div class="search_form">
+			<div>
+				<span class="search_title">璁惧鍚嶇О锛�</span>
+				<el-input
+					v-model="searchForm.name"
+					style="width: 240px"
+					placeholder="璇疯緭鍏�"
+					@change="handleQuery"
+					clearable
+					:prefix-icon="Search"
+				/>
+				<el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+				>鎼滅储</el-button
+				>
+			</div>
+		</div>
+		<div class="table_list">
+			<PIMTable
+				rowKey="id"
+				:column="tableColumn"
+				:tableData="tableData"
+				:page="page"
+				:isSelection="true"
+				@selection-change="handleSelectionChange"
+				:tableLoading="tableLoading"
+				@pagination="pagination"
+			></PIMTable>
+		</div>
+	</div>
+</template>
+
+<script setup>
+import {Search} from "@element-plus/icons-vue";
+import {onMounted, ref, reactive} from "vue";
+import {listPageByWaterTrend} from "@/api/energyManagement/waterManagement.js";
+
+const data = reactive({
+	searchForm: {
+		name: "",
+	},
+});
+const { searchForm } = toRefs(data);
+
+const selectedRows = ref([]);
+const tableColumn = ref([
+	{
+		label: "璁惧鍚嶇О",
+		prop: "name",
+		width: 220,
+	},
+	{
+		label: "瑙勬牸鍨嬪彿",
+		prop: "code",
+		width: 220,
+	},
+	{
+		label: "杩愯鏃堕棿",
+		prop: "runDate",
+		width: 250,
+	},
+	{
+		label: "鏄ㄦ棩鐢ㄦ按閲�",
+		prop: "toDayNum",
+	},
+	{
+		label: "鏈湀骞冲潎姘撮噺",
+		prop: "avgNum",
+		width:150
+	},
+	{
+		label: "瓒嬪娍",
+		prop: "trend",
+		width: 220,
+	},
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+	current: 1,
+	size: 100,
+	total: 0,
+});
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+	selectedRows.value = selection;
+};
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+	page.current = 1;
+	getList();
+};
+const pagination = (obj) => {
+	page.current = obj.page;
+	page.size = obj.limit;
+	getList();
+};
+
+const getList = () => {
+	tableLoading.value = true;
+	listPageByWaterTrend({ ...searchForm.value, ...page }).then((res) => {
+		tableLoading.value = false;
+		tableData.value = res.data.records;
+		page.total = res.data.total;
+	});
+};
+
+onMounted(() => {
+	getList();
+});
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/equipmentManagement/gasTank/simple.vue b/src/views/equipmentManagement/gasTank/simple.vue
new file mode 100644
index 0000000..92e88df
--- /dev/null
+++ b/src/views/equipmentManagement/gasTank/simple.vue
@@ -0,0 +1,566 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <h2>閲嶅瀷缃愬紡璐ц溅鐩戞帶</h2>
+      <div class="header-actions">
+<!--        <el-button type="primary" @click="addTank">鏂板鍌ㄧ綈</el-button>-->
+<!--        <el-button @click="exportData">瀵煎嚭鏁版嵁</el-button>-->
+      </div>
+    </div>
+
+    <!-- 鍥涗釜涓昏妯″潡 -->
+    <div class="modules-container">
+      <!-- 1. 鍩烘湰淇℃伅妯″潡 -->
+      <el-card class="module-card">
+        <template #header>
+          <div class="card-header">
+            <span>1. 鍩烘湰淇℃伅</span>
+                         <el-button type="text" @click="handleEditBasicInfo">缂栬緫</el-button>
+          </div>
+        </template>
+        <div class="info-grid">
+          <div class="info-item">
+            <label>鍌ㄧ綈缂栧彿锛�</label>
+            <span>{{ basicInfo.tankCode }}</span>
+          </div>
+          <div class="info-item">
+            <label>鍌ㄧ綈鍚嶇О锛�</label>
+            <span>{{ basicInfo.tankName }}</span>
+          </div>
+          <div class="info-item">
+            <label>鍌ㄧ綈绫诲瀷锛�</label>
+            <span>{{ basicInfo.tankType }}</span>
+          </div>
+          <div class="info-item">
+            <label>璁捐鍘嬪姏锛�</label>
+            <span>{{ basicInfo.designPressure }} MPa</span>
+          </div>
+          <div class="info-item">
+            <label>宸ヤ綔鍘嬪姏锛�</label>
+            <span>{{ basicInfo.workingPressure }} MPa</span>
+          </div>
+          <div class="info-item">
+            <label>瀹圭Н锛�</label>
+            <span>{{ basicInfo.volume }} m鲁</span>
+          </div>
+        </div>
+      </el-card>
+
+      <!-- 2. 鐩戞祴鍙傛暟妯″潡 -->
+      <el-card class="module-card">
+        <template #header>
+          <div class="card-header">
+            <span>2. 鐩戞祴鍙傛暟</span>
+            <el-button type="text" @click="refreshMonitoring">鍒锋柊</el-button>
+          </div>
+        </template>
+        <div class="monitoring-grid">
+          <div class="monitor-item">
+            <div class="monitor-label">鍘嬪姏</div>
+            <div class="monitor-value" :class="getStatusClass(monitoringData.pressureStatus)">
+              {{ monitoringData.pressure }} MPa
+            </div>
+            <div class="monitor-status">{{ monitoringData.pressureStatus === 'normal' ? '姝e父' : '寮傚父' }}</div>
+          </div>
+          <div class="monitor-item">
+            <div class="monitor-label">娓╁害</div>
+            <div class="monitor-value" :class="getStatusClass(monitoringData.temperatureStatus)">
+              {{ monitoringData.temperature }} 鈩�
+            </div>
+            <div class="monitor-status">{{ monitoringData.temperatureStatus === 'normal' ? '姝e父' : '寮傚父' }}</div>
+          </div>
+          <div class="monitor-item">
+            <div class="monitor-label">姘斾綋娴撳害</div>
+            <div class="monitor-value" :class="getStatusClass(monitoringData.gasStatus)">
+              {{ monitoringData.gasConcentration }} ppm
+            </div>
+            <div class="monitor-status">{{ monitoringData.gasStatus === 'normal' ? '姝e父' : '寮傚父' }}</div>
+          </div>
+          <div class="monitor-item">
+            <div class="monitor-label">娴侀噺</div>
+            <div class="monitor-value" :class="getStatusClass(monitoringData.flowStatus)">
+              {{ monitoringData.flow }} m鲁/h
+            </div>
+            <div class="monitor-status">{{ monitoringData.flowStatus === 'normal' ? '姝e父' : '寮傚父' }}</div>
+          </div>
+        </div>
+      </el-card>
+
+      <!-- 3. 瀹夊叏瑁呯疆妯″潡 -->
+      <el-card class="module-card">
+        <template #header>
+          <div class="card-header">
+            <span>3. 瀹夊叏瑁呯疆</span>
+            <el-button type="text" @click="checkSafetyDevices">妫�鏌�</el-button>
+          </div>
+        </template>
+        <div class="safety-grid">
+          <div class="safety-item" v-for="device in safetyDevices" :key="device.name">
+            
+            <div class="device-info">
+              <div class="device-name">{{ device.name }}</div>
+              <div class="device-status" :class="device.status">
+                {{ device.status === 'normal' ? '姝e父' : '寮傚父' }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </el-card>
+
+      <!-- 4. 缁存姢璁板綍妯″潡 -->
+      <el-card class="module-card">
+        <template #header>
+          <div class="card-header">
+            <span>4. 缁存姢璁板綍</span>
+            <el-button type="text" @click="addMaintenanceRecord">娣诲姞璁板綍</el-button>
+          </div>
+        </template>
+        <div class="maintenance-list">
+          <div class="maintenance-item" v-for="record in maintenanceRecords" :key="record.id">
+            <div class="record-header">
+              <span class="record-date">{{ record.date }}</span>
+              <el-tag :type="record.type === 'inspection' ? 'primary' : 'success'" size="small">
+                {{ record.type === 'inspection' ? '妫�楠�' : '缁存姢' }}
+              </el-tag>
+            </div>
+            <div class="record-content">
+              <div class="record-title">{{ record.title }}</div>
+              <div class="record-desc">{{ record.description }}</div>
+              <div class="record-operator">鎿嶄綔浜猴細{{ record.operator }}</div>
+            </div>
+          </div>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- 缂栬緫鍩烘湰淇℃伅寮圭獥 -->
+    <el-dialog v-model="basicInfoDialogVisible" title="缂栬緫鍩烘湰淇℃伅" width="600px">
+      <el-form :model="editBasicInfo" label-width="120px">
+        <el-form-item label="鍌ㄧ綈缂栧彿">
+          <el-input v-model="editBasicInfo.tankCode" />
+        </el-form-item>
+        <el-form-item label="鍌ㄧ綈鍚嶇О">
+          <el-input v-model="editBasicInfo.tankName" />
+        </el-form-item>
+        <el-form-item label="鍌ㄧ綈绫诲瀷">
+          <el-select v-model="editBasicInfo.tankType" style="width: 100%">
+            <el-option label="娑插寲姘斾綋鍌ㄧ綈" value="娑插寲姘斾綋鍌ㄧ綈" />
+            <el-option label="鍘嬪姏瀹瑰櫒" value="鍘嬪姏瀹瑰櫒" />
+            <el-option label="甯稿帇鍌ㄧ綈" value="甯稿帇鍌ㄧ綈" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="璁捐鍘嬪姏">
+          <el-input-number v-model="editBasicInfo.designPressure" :precision="2" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="宸ヤ綔鍘嬪姏">
+          <el-input-number v-model="editBasicInfo.workingPressure" :precision="2" style="width: 100%" />
+        </el-form-item>
+        <el-form-item label="瀹圭Н">
+          <el-input-number v-model="editBasicInfo.volume" :precision="2" style="width: 100%" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="basicInfoDialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="saveBasicInfo">淇濆瓨</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 娣诲姞缁存姢璁板綍寮圭獥 -->
+    <el-dialog v-model="maintenanceDialogVisible" title="娣诲姞缁存姢璁板綍" width="600px">
+      <el-form :model="newMaintenanceRecord" label-width="120px">
+        <el-form-item label="璁板綍绫诲瀷">
+          <el-select v-model="newMaintenanceRecord.type" style="width: 100%">
+            <el-option label="妫�楠�" value="inspection" />
+            <el-option label="缁存姢" value="maintenance" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鏍囬">
+          <el-input v-model="newMaintenanceRecord.title" />
+        </el-form-item>
+        <el-form-item label="鎻忚堪">
+          <el-input type="textarea" v-model="newMaintenanceRecord.description" :rows="3" />
+        </el-form-item>
+        <el-form-item label="鎿嶄綔浜�">
+          <el-input v-model="newMaintenanceRecord.operator" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="maintenanceDialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="saveMaintenanceRecord">淇濆瓨</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+
+// 鍩烘湰淇℃伅
+const basicInfo = reactive({
+  tankCode: 'GT001',
+  tankName: '娑插寲姘斿偍缃怉',
+  tankType: '娑插寲姘斾綋鍌ㄧ綈',
+  designPressure: 1.6,
+  workingPressure: 0.8,
+  volume: 100.5
+})
+
+// 鐩戞祴鍙傛暟
+const monitoringData = reactive({
+  pressure: 0.8,
+  pressureStatus: 'normal',
+  temperature: 25.5,
+  temperatureStatus: 'normal',
+  gasConcentration: 0.1,
+  gasStatus: 'normal',
+  flow: 15.2,
+  flowStatus: 'normal'
+})
+
+// 瀹夊叏瑁呯疆
+const safetyDevices = ref([
+  { name: '瀹夊叏闃�', status: 'normal' },
+  { name: '鍘嬪姏浼犳劅鍣�', status: 'normal' },
+  { name: '娓╁害浼犳劅鍣�', status: 'normal' },
+  { name: '姘斾綋妫�娴嬪櫒', status: 'normal' },
+  { name: '鐖嗙牬鐗�', status: 'normal' },
+  { name: '娉勫帇瑁呯疆', status: 'normal' }
+])
+
+// 缁存姢璁板綍
+const maintenanceRecords = ref([
+  {
+    id: 1,
+    date: '2024-01-15',
+    type: 'inspection',
+    title: '骞村害妫�楠�',
+    description: '鎸夌収TSG 21-2016鏍囧噯杩涜骞村害妫�楠岋紝璁惧鐘舵�佽壇濂�',
+    operator: '寮犲伐绋嬪笀'
+  },
+  {
+    id: 2,
+    date: '2024-02-20',
+    type: 'maintenance',
+    title: '瀹夊叏闃�缁存姢',
+    description: '鏇存崲瀹夊叏闃�瀵嗗皝鍦堬紝鏍″噯鍘嬪姏璁惧畾鍊�',
+    operator: '鏉庢妧甯�'
+  },
+  {
+    id: 3,
+    date: '2024-03-10',
+    type: 'inspection',
+    title: '鍘嬪姏娴嬭瘯',
+    description: '杩涜鍘嬪姏瀹瑰櫒姘村帇璇曢獙锛岀鍚堣璁¤姹�',
+    operator: '鐜嬫楠屽憳'
+  }
+])
+
+// 寮圭獥鎺у埗
+const basicInfoDialogVisible = ref(false)
+const maintenanceDialogVisible = ref(false)
+
+// 缂栬緫琛ㄥ崟鏁版嵁
+const editBasicInfo = reactive({ ...basicInfo })
+const newMaintenanceRecord = reactive({
+  type: 'inspection',
+  title: '',
+  description: '',
+  operator: ''
+})
+
+// 鑾峰彇鐘舵�佹牱寮忕被
+const getStatusClass = (status) => {
+  return status === 'normal' ? 'status-normal' : 'status-warning'
+}
+
+// 鏂板鍌ㄧ綈
+const addTank = () => {
+  ElMessage.success('鏂板鍌ㄧ綈鍔熻兘')
+}
+
+// 瀵煎嚭鏁版嵁
+const exportData = () => {
+  ElMessage.success('瀵煎嚭鎴愬姛')
+}
+
+// 缂栬緫鍩烘湰淇℃伅
+const handleEditBasicInfo = () => {
+  Object.assign(editBasicInfo, basicInfo)
+  basicInfoDialogVisible.value = true
+}
+
+// 淇濆瓨鍩烘湰淇℃伅
+const saveBasicInfo = () => {
+  Object.assign(basicInfo, editBasicInfo)
+  basicInfoDialogVisible.value = false
+  ElMessage.success('淇濆瓨鎴愬姛')
+}
+
+// 鍒锋柊鐩戞祴鏁版嵁
+const refreshMonitoring = () => {
+  // 妯℃嫙鏁版嵁鏇存柊
+  monitoringData.pressure = (Math.random() * 0.5 + 0.6).toFixed(2)
+  monitoringData.temperature = (Math.random() * 10 + 20).toFixed(1)
+  monitoringData.gasConcentration = (Math.random() * 0.2).toFixed(2)
+  monitoringData.flow = (Math.random() * 10 + 10).toFixed(1)
+  ElMessage.success('鏁版嵁宸插埛鏂�')
+}
+
+// 妫�鏌ュ畨鍏ㄨ缃�
+const checkSafetyDevices = () => {
+  // 妯℃嫙妫�鏌ヨ繃绋�
+  safetyDevices.value.forEach(device => {
+    device.status = Math.random() > 0.1 ? 'normal' : 'warning'
+  })
+  ElMessage.success('瀹夊叏瑁呯疆妫�鏌ュ畬鎴�')
+}
+
+// 娣诲姞缁存姢璁板綍
+const addMaintenanceRecord = () => {
+  newMaintenanceRecord.type = 'inspection'
+  newMaintenanceRecord.title = ''
+  newMaintenanceRecord.description = ''
+  newMaintenanceRecord.operator = ''
+  maintenanceDialogVisible.value = true
+}
+
+// 淇濆瓨缁存姢璁板綍
+const saveMaintenanceRecord = () => {
+  const record = {
+    id: Date.now(),
+    date: new Date().toISOString().split('T')[0],
+    ...newMaintenanceRecord
+  }
+  maintenanceRecords.value.unshift(record)
+  maintenanceDialogVisible.value = false
+  ElMessage.success('璁板綍娣诲姞鎴愬姛')
+}
+
+// 妯℃嫙瀹炴椂鏁版嵁鏇存柊
+onMounted(() => {
+  setInterval(() => {
+    monitoringData.pressure = (Math.random() * 0.5 + 0.6).toFixed(2)
+    monitoringData.temperature = (Math.random() * 10 + 20).toFixed(1)
+    monitoringData.gasConcentration = (Math.random() * 0.2).toFixed(2)
+    monitoringData.flow = (Math.random() * 10 + 10).toFixed(1)
+  }, 5000)
+})
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  padding: 20px;
+  background: #f5f5f5;
+  min-height: 100vh;
+}
+
+.page-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  padding: 20px;
+  background: white;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+
+  h2 {
+    margin: 0;
+    color: #303133;
+  }
+
+  .header-actions {
+    display: flex;
+    gap: 10px;
+  }
+}
+
+.modules-container {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 20px;
+}
+
+.module-card {
+  .card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    font-weight: bold;
+    color: #303133;
+  }
+}
+
+.info-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 15px;
+
+  .info-item {
+    display: flex;
+    justify-content: space-between;
+    padding: 10px;
+    background: #f8f9fa;
+    border-radius: 4px;
+
+    label {
+      font-weight: bold;
+      color: #606266;
+    }
+
+    span {
+      color: #303133;
+    }
+  }
+}
+
+.monitoring-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 15px;
+
+  .monitor-item {
+    text-align: center;
+    padding: 15px;
+    background: #f8f9fa;
+    border-radius: 8px;
+    border: 2px solid transparent;
+
+    .monitor-label {
+      font-size: 14px;
+      color: #606266;
+      margin-bottom: 8px;
+    }
+
+    .monitor-value {
+      font-size: 20px;
+      font-weight: bold;
+      margin-bottom: 5px;
+
+      &.status-normal {
+        color: #67c23a;
+      }
+
+      &.status-warning {
+        color: #e6a23c;
+      }
+    }
+
+    .monitor-status {
+      font-size: 12px;
+      color: #909399;
+    }
+  }
+}
+
+.safety-grid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 15px;
+
+  .safety-item {
+    display: flex;
+    align-items: center;
+    padding: 15px;
+    background: #f8f9fa;
+    border-radius: 8px;
+    border: 2px solid transparent;
+
+    .device-icon {
+      margin-right: 15px;
+    }
+
+    .device-info {
+      flex: 1;
+
+      .device-name {
+        font-weight: bold;
+        color: #303133;
+        margin-bottom: 5px;
+      }
+
+      .device-status {
+        font-size: 12px;
+        padding: 2px 8px;
+        border-radius: 10px;
+        display: inline-block;
+
+        &.normal {
+          background: #f0f9ff;
+          color: #409eff;
+        }
+
+        &.warning {
+          background: #fef7e0;
+          color: #e6a23c;
+        }
+      }
+    }
+  }
+}
+
+.maintenance-list {
+  max-height: 300px;
+  overflow-y: auto;
+
+  .maintenance-item {
+    padding: 15px;
+    border-bottom: 1px solid #ebeef5;
+    margin-bottom: 10px;
+
+    &:last-child {
+      border-bottom: none;
+      margin-bottom: 0;
+    }
+
+    .record-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 8px;
+
+      .record-date {
+        font-size: 14px;
+        color: #909399;
+      }
+    }
+
+    .record-content {
+      .record-title {
+        font-weight: bold;
+        color: #303133;
+        margin-bottom: 5px;
+      }
+
+      .record-desc {
+        font-size: 14px;
+        color: #606266;
+        margin-bottom: 5px;
+        line-height: 1.4;
+      }
+
+      .record-operator {
+        font-size: 12px;
+        color: #909399;
+      }
+    }
+  }
+}
+
+// 鍝嶅簲寮忚璁�
+@media (max-width: 1200px) {
+  .modules-container {
+    grid-template-columns: 1fr;
+  }
+}
+
+@media (max-width: 768px) {
+  .info-grid,
+  .monitoring-grid,
+  .safety-grid {
+    grid-template-columns: 1fr;
+  }
+}
+</style>
diff --git a/src/views/equipmentManagement/ledger/Form.vue b/src/views/equipmentManagement/ledger/Form.vue
index f7029ee..c1daab7 100644
--- a/src/views/equipmentManagement/ledger/Form.vue
+++ b/src/views/equipmentManagement/ledger/Form.vue
@@ -8,7 +8,7 @@
       </el-col>
       <el-col :span="12">
         <el-form-item label="瑙勬牸鍨嬪彿" prop="deviceModel">
-          <el-input v-model="form.deviceModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+          <el-input v-model="form.deviceModel" :disabled="form.deviceModel != null ? true : false" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
         </el-form-item>
       </el-col>
       <el-col :span="12">
diff --git a/src/views/equipmentManagement/ledger/index.vue b/src/views/equipmentManagement/ledger/index.vue
index ba17f7e..16fbbc6 100644
--- a/src/views/equipmentManagement/ledger/index.vue
+++ b/src/views/equipmentManagement/ledger/index.vue
@@ -79,22 +79,17 @@
         @selection-change="handleSelectionChange"
         @pagination="changePage"
       >
-        <template #operation="{ row }">
-          <el-button type="primary" text @click="edit(row.id)" icon="editPen">
-            缂栬緫
-          </el-button>
-          <el-button
-            type="danger"
-            text
-            icon="delete"
-            @click="deleteRow(row.id)"
-          >
-            鍒犻櫎
-          </el-button>
-        </template>
       </PIMTable>
     </div>
     <Modal ref="modalRef" @success="getTableData"></Modal>
+    <el-dialog v-model="qrDialogVisible" title="浜岀淮鐮�" width="300px">
+      <div style="text-align:center;">
+        <img :src="qrCodeUrl" alt="浜岀淮鐮�" style="width:200px;height:200px;" />
+        <div style="margin:10px 0;">
+          <el-button type="primary" @click="downloadQRCode">涓嬭浇浜岀淮鐮佸浘鐗�</el-button>
+        </div>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -106,6 +101,8 @@
 import Modal from "./Modal.vue";
 import { ElMessageBox, ElMessage } from "element-plus";
 import dayjs from "dayjs";
+import QRCode from "qrcode";
+import { ref } from "vue";
 
 defineOptions({
   name: "璁惧鍙拌处",
@@ -115,6 +112,10 @@
 const multipleList = ref([]);
 const { proxy } = getCurrentInstance();
 const modalRef = ref();
+const qrDialogVisible = ref(false);
+const qrCodeUrl = ref("");
+const qrRowData = ref(null);
+
 const {
   filters,
   columns,
@@ -184,14 +185,29 @@
       align: "center",
       prop: "createTime",
     },
-    {
-      fixed: "right",
-      label: "鎿嶄綔",
-      dataType: "slot",
-      slot: "operation",
-      align: "center",
-      width: "200px",
-    },
+		{
+			dataType: "action",
+			label: "鎿嶄綔",
+			align: "center",
+			fixed: 'right',
+			width: 140,
+			operation: [
+				{
+					name: "缂栬緫",
+					type: "text",
+					clickFun: (row) => {
+						edit(row.id)
+					},
+				},
+				{
+					name: "鐢熸垚浜岀淮鐮�",
+					type: "text",
+					clickFun: (row) => {
+						showQRCode(row)
+					},
+				},
+			],
+		},
   ]
 );
 
@@ -253,6 +269,21 @@
     });
 };
 
+const showQRCode = async (row) => {
+  // 浣犲彲浠ヨ嚜瀹氫箟浜岀淮鐮佸唴瀹癸紝姣斿 row.id 鎴� row.deviceName
+  const qrContent = JSON.stringify(row); // 鎴� `${row.id}`
+  qrCodeUrl.value = await QRCode.toDataURL(qrContent);
+  qrRowData.value = row;
+  qrDialogVisible.value = true;
+};
+
+const downloadQRCode = () => {
+  const a = document.createElement("a");
+  a.href = qrCodeUrl.value;
+  a.download = `${qrRowData.value.deviceName || "浜岀淮鐮�"}.png`;
+  a.click();
+};
+
 onMounted(() => {
   filters.entryDate = [
     dayjs().format("YYYY-MM-DD"),
diff --git a/src/views/inventoryManagement/stockWarning/index.vue b/src/views/inventoryManagement/stockWarning/index.vue
new file mode 100644
index 0000000..3694265
--- /dev/null
+++ b/src/views/inventoryManagement/stockWarning/index.vue
@@ -0,0 +1,1137 @@
+<template>
+  <div class="app-container">
+    <!-- 鎼滅储琛ㄥ崟 -->
+    <div class="search_form">
+      <el-form :model="searchForm" :inline="true">
+        <el-form-item label="鍌ㄦ皵缃愬悕绉帮細">
+          <el-input v-model="searchForm.tankName" placeholder="璇疯緭鍏ュ偍姘旂綈鍚嶇О" clearable style="width: 200px" />
+        </el-form-item>
+        <el-form-item label="鍌ㄦ皵缃愮被鍨嬶細">
+          <el-select v-model="searchForm.tankType" placeholder="璇烽�夋嫨鍌ㄦ皵缃愮被鍨�" clearable style="width: 200px">
+            <el-option label="娑插寲姘斿偍缃�" value="娑插寲姘斿偍缃�" />
+            <el-option label="鍘嬬缉姘斿偍缃�" value="鍘嬬缉姘斿偍缃�" />
+            <el-option label="澶╃劧姘斿偍缃�" value="澶╃劧姘斿偍缃�" />
+            <el-option label="姘ф皵鍌ㄧ綈" value="姘ф皵鍌ㄧ綈" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="棰勮绫诲瀷锛�">
+          <el-select v-model="searchForm.warningType" placeholder="璇烽�夋嫨棰勮绫诲瀷" clearable style="width: 200px">
+            <el-option label="姘斾綋涓嶈冻" value="姘斾綋涓嶈冻" />
+            <el-option label="鍘嬪姏寮傚父" value="鍘嬪姏寮傚父" />
+            <el-option label="娓╁害寮傚父" value="娓╁害寮傚父" />
+            <el-option label="娉勬紡棰勮" value="娉勬紡棰勮" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="棰勮绾у埆锛�">
+          <el-select v-model="searchForm.warningLevel" placeholder="璇烽�夋嫨棰勮绾у埆" clearable style="width: 200px">
+            <el-option label="绱ф��" value="绱ф��" />
+            <el-option label="閲嶈" value="閲嶈" />
+            <el-option label="涓�鑸�" value="涓�鑸�" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="handleQuery">鎼滅储</el-button>
+          <el-button @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 鏁版嵁琛ㄦ牸 -->
+    <div class="table_list">
+      <!-- 鎿嶄綔鎸夐挳 -->
+      <div class="table-operations">
+        <el-button type="primary" @click="handleAdd">鏂板棰勮瑙勫垯</el-button>
+        <el-button type="success" @click="handleBatchProcess">鎵归噺澶勭悊</el-button>
+        <el-button @click="handleExport">瀵煎嚭</el-button>
+      </div>
+      <el-table 
+        :data="tableData" 
+        border 
+        v-loading="tableLoading" 
+        @selection-change="handleSelectionChange"
+        style="width: 100%"
+        height="calc(100vh - 280px)"
+      >
+        <el-table-column align="center" type="selection" width="55" />
+        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+        
+        <!-- 鍩虹淇℃伅瀛楁 -->
+        <el-table-column label="鍌ㄦ皵缃愮紪鐮�" prop="tankCode" width="120" show-overflow-tooltip />
+        <el-table-column label="鍌ㄦ皵缃愬悕绉�" prop="tankName" width="200" show-overflow-tooltip />
+        <el-table-column label="鍌ㄦ皵缃愮被鍨�" prop="tankType" width="120" show-overflow-tooltip />
+        <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="150" show-overflow-tooltip />
+        <el-table-column label="瀹圭Н(m鲁)" prop="volume" width="100" show-overflow-tooltip />
+        
+        <!-- 搴撳瓨鐩稿叧瀛楁 -->
+        <el-table-column label="褰撳墠姘斾綋閲�" prop="currentGasLevel" width="120" show-overflow-tooltip>
+          <template #default="scope">
+            <span :class="getGasLevelClass(scope.row)">{{ scope.row.currentGasLevel }}%</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="瀹夊叏姘斾綋閲�" prop="safetyGasLevel" width="120" show-overflow-tooltip />
+        <el-table-column label="鏈�浣庢皵浣撻噺" prop="minGasLevel" width="120" show-overflow-tooltip />
+        <el-table-column label="鏈�楂樻皵浣撻噺" prop="maxGasLevel" width="120" show-overflow-tooltip />
+        <el-table-column label="褰撳墠鍘嬪姏(MPa)" prop="currentPressure" width="140" show-overflow-tooltip />
+        
+        <!-- 棰勮瑙勫垯瀛楁 -->
+        <el-table-column label="棰勮绫诲瀷" prop="warningType" width="100" show-overflow-tooltip>
+          <template #default="scope">
+            <el-tag :type="getWarningTypeTag(scope.row.warningType)">
+              {{ scope.row.warningType }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="棰勮绾у埆" prop="warningLevel" width="100" show-overflow-tooltip>
+          <template #default="scope">
+            <el-tag :type="getWarningLevelTag(scope.row.warningLevel)">
+              {{ scope.row.warningLevel }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="棰勮闃堝��" prop="warningThreshold" width="100" show-overflow-tooltip />
+        <el-table-column label="鏄惁鍚敤" prop="isEnabled" width="100" show-overflow-tooltip>
+          <template #default="scope">
+            <el-switch v-model="scope.row.isEnabled" @change="handleEnableChange(scope.row)" />
+          </template>
+        </el-table-column>
+        
+        <!-- 鏃堕棿鐩稿叧瀛楁 -->
+        <el-table-column label="棰勮鏃堕棿" prop="warningTime" width="150" show-overflow-tooltip />
+        <el-table-column label="棰勮鎸佺画澶╂暟" prop="warningDuration" width="120" show-overflow-tooltip />
+        <el-table-column label="鏈�鍚庢洿鏂版椂闂�" prop="lastUpdateTime" width="150" show-overflow-tooltip />
+        <el-table-column label="棰勮鍏呰鏃堕棿" prop="expectedRefillTime" width="150" show-overflow-tooltip />
+        <el-table-column label="棰勮缂烘皵鏃堕棿" prop="expectedShortageTime" width="150" show-overflow-tooltip>
+          <template #default="scope">
+            <div v-if="scope.row.expectedShortageTime">
+              <div v-if="getCountdown(scope.row.expectedShortageTime).isExpired" class="countdown-expired">
+                <el-tag type="danger">宸茬己姘�</el-tag>
+              </div>
+              <div v-else class="countdown-timer">
+                <span :class="getCountdownClass(scope.row.expectedShortageTime)">
+                  {{ getCountdown(scope.row.expectedShortageTime).text }}
+                </span>
+              </div>
+            </div>
+            <span v-else>-</span>
+          </template>
+        </el-table-column>
+        
+        <!-- 鎿嶄綔鍒� -->
+        <el-table-column fixed="right" label="鎿嶄綔" width="200" align="center">
+          <template #default="scope">
+            <el-button link type="primary" size="small" @click="handleEdit(scope.row)">缂栬緫</el-button>
+            <el-button link type="success" size="small" @click="handleProcess(scope.row)">澶勭悊</el-button>
+            <el-button link type="danger" size="small" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      
+      <!-- 鍒嗛〉 -->
+      <pagination 
+        v-show="total > 0" 
+        :total="total" 
+        layout="total, sizes, prev, pager, next, jumper"
+        :page="page.current" 
+        :limit="page.size" 
+        @pagination="paginationChange" 
+      />
+    </div>
+
+    <!-- 鏂板/缂栬緫棰勮瑙勫垯寮圭獥 -->
+    <el-dialog 
+      v-model="dialogFormVisible" 
+      :title="operationType === 'add' ? '鏂板棰勮瑙勫垯' : '缂栬緫棰勮瑙勫垯'" 
+      width="50%"
+      @close="closeDialog"
+    >
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="140px">
+        <el-row :gutter="20">
+          <!-- 鍩虹淇℃伅 -->
+          <el-col :span="12">
+            <el-form-item label="鍌ㄦ皵缃愮紪鐮侊細" prop="tankCode">
+              <el-input v-model="form.tankCode" placeholder="璇疯緭鍏ュ偍姘旂綈缂栫爜" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍌ㄦ皵缃愬悕绉帮細" prop="tankName">
+              <el-input v-model="form.tankName" placeholder="璇疯緭鍏ュ偍姘旂綈鍚嶇О" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍌ㄦ皵缃愮被鍨嬶細" prop="tankType">
+              <el-select v-model="form.tankType" placeholder="璇烽�夋嫨鍌ㄦ皵缃愮被鍨�" style="width: 100%">
+                <el-option label="娑插寲姘斿偍缃�" value="娑插寲姘斿偍缃�" />
+                <el-option label="鍘嬬缉姘斿偍缃�" value="鍘嬬缉姘斿偍缃�" />
+                <el-option label="澶╃劧姘斿偍缃�" value="澶╃劧姘斿偍缃�" />
+                <el-option label="姘ф皵鍌ㄧ綈" value="姘ф皵鍌ㄧ綈" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="specificationModel">
+              <el-input v-model="form.specificationModel" placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="瀹圭Н(m鲁)锛�" prop="volume">
+              <el-input-number v-model="form.volume" :min="0" :precision="2" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="褰撳墠姘斾綋閲�(%)锛�" prop="currentGasLevel">
+              <el-input-number v-model="form.currentGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <!-- 搴撳瓨鐩稿叧 -->
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="瀹夊叏姘斾綋閲�(%)锛�" prop="safetyGasLevel">
+              <el-input-number v-model="form.safetyGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏈�浣庢皵浣撻噺(%)锛�" prop="minGasLevel">
+              <el-input-number v-model="form.minGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鏈�楂樻皵浣撻噺(%)锛�" prop="maxGasLevel">
+              <el-input-number v-model="form.maxGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="褰撳墠鍘嬪姏(MPa)锛�" prop="currentPressure">
+              <el-input-number v-model="form.currentPressure" :min="0" :precision="2" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <!-- 棰勮瑙勫垯 -->
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="棰勮绫诲瀷锛�" prop="warningType">
+              <el-select v-model="form.warningType" placeholder="璇烽�夋嫨棰勮绫诲瀷" style="width: 100%">
+                <el-option label="姘斾綋涓嶈冻" value="姘斾綋涓嶈冻" />
+                <el-option label="鍘嬪姏寮傚父" value="鍘嬪姏寮傚父" />
+                <el-option label="娓╁害寮傚父" value="娓╁害寮傚父" />
+                <el-option label="娉勬紡棰勮" value="娉勬紡棰勮" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="棰勮绾у埆锛�" prop="warningLevel">
+              <el-select v-model="form.warningLevel" placeholder="璇烽�夋嫨棰勮绾у埆" style="width: 100%">
+                <el-option label="绱ф��" value="绱ф��" />
+                <el-option label="閲嶈" value="閲嶈" />
+                <el-option label="涓�鑸�" value="涓�鑸�" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="棰勮闃堝�硷細" prop="warningThreshold">
+              <el-input-number v-model="form.warningThreshold" :min="0" :precision="2" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏄惁鍚敤锛�" prop="isEnabled">
+              <el-switch v-model="form.isEnabled" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <!-- 鏃堕棿鐩稿叧 -->
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="棰勮鏃堕棿锛�" prop="warningTime">
+              <el-date-picker 
+                v-model="form.warningTime" 
+                type="datetime" 
+                placeholder="璇烽�夋嫨棰勮鏃堕棿" 
+                style="width: 100%"
+                value-format="YYYY-MM-DD HH:mm:ss"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="棰勮鍏呰鏃堕棿锛�" prop="expectedRefillTime">
+              <el-date-picker 
+                v-model="form.expectedRefillTime" 
+                type="datetime" 
+                placeholder="璇烽�夋嫨棰勮鍏呰鏃堕棿" 
+                style="width: 100%"
+                value-format="YYYY-MM-DD HH:mm:ss"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="棰勮缂烘皵鏃堕棿锛�" prop="expectedShortageTime">
+              <el-date-picker 
+                v-model="form.expectedShortageTime" 
+                type="datetime" 
+                placeholder="璇烽�夋嫨棰勮缂烘皵鏃堕棿" 
+                style="width: 100%"
+                value-format="YYYY-MM-DD HH:mm:ss"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="棰勮瑙勫垯鎻忚堪锛�" prop="warningRule">
+              <el-input 
+                v-model="form.warningRule" 
+                type="textarea" 
+                :rows="3" 
+                placeholder="璇疯緭鍏ラ璀﹁鍒欐弿杩�"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="closeDialog">鍙栨秷</el-button>
+          <el-button type="primary" @click="submitForm">纭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 缂烘皵棰勮寮规 -->
+    <el-dialog
+      v-model="shortageWarningVisible"
+      title="鈿狅笍 缂烘皵棰勮"
+      width="400px"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      :show-close="false"
+    >
+      <div class="shortage-warning-content">
+        <div class="warning-icon">
+          <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon>
+        </div>
+        <div class="warning-message">
+          <h3>{{ currentWarningTank.tankName }}</h3>
+          <p>鍌ㄦ皵缃愬凡缂烘皵锛岃鍙婃椂澶勭悊锛�</p>
+          <p class="warning-details">
+            鍌ㄦ皵缃愮紪鐮侊細{{ currentWarningTank.tankCode }}<br>
+            鍌ㄦ皵缃愮被鍨嬶細{{ currentWarningTank.tankType }}<br>
+            褰撳墠姘斾綋閲忥細{{ currentWarningTank.currentGasLevel }}%
+          </p>
+        </div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="handleShortageWarning">绔嬪嵆澶勭悊</el-button>
+          <el-button @click="closeShortageWarning">绋嶅悗澶勭悊</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 缂烘皵棰勮寮规 -->
+    <el-dialog
+      v-model="shortageWarningVisible"
+      title="鈿狅笍 缂烘皵棰勮"
+      width="400px"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      :show-close="false"
+    >
+      <div class="shortage-warning-content">
+        <div class="warning-icon">
+          <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon>
+        </div>
+        <div class="warning-message">
+          <h3>{{ currentWarningTank.tankName }}</h3>
+          <p>鍌ㄦ皵缃愬凡缂烘皵锛岃鍙婃椂澶勭悊锛�</p>
+          <p class="warning-details">
+            鍌ㄦ皵缃愮紪鐮侊細{{ currentWarningTank.tankCode }}<br>
+            鍌ㄦ皵缃愮被鍨嬶細{{ currentWarningTank.tankType }}<br>
+            褰撳墠姘斾綋閲忥細{{ currentWarningTank.currentGasLevel }}%
+          </p>
+        </div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="handleShortageWarning">绔嬪嵆澶勭悊</el-button>
+          <el-button @click="closeShortageWarning">绋嶅悗澶勭悊</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, onUnmounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { WarningFilled } from '@element-plus/icons-vue'
+import pagination from '@/components/PIMTable/Pagination.vue'
+// 娉ㄩ噴鎺堿PI瀵煎叆锛屼娇鐢ㄥ亣鏁版嵁
+// import {
+//   getStockWarningPage,
+//   addStockWarning,
+//   updateStockWarning,
+//   deleteStockWarning,
+//   batchProcessStockWarning,
+//   exportStockWarning,
+//   toggleStockWarningStatus
+// } from '@/api/inventoryManagement/stockWarning.js'
+
+const { proxy } = getCurrentInstance()
+
+// 鍝嶅簲寮忔暟鎹�
+const tableData = ref([])
+const tableLoading = ref(false)
+const selectedRows = ref([])
+const dialogFormVisible = ref(false)
+const operationType = ref('add')
+const total = ref(0)
+
+// 缂烘皵棰勮鐩稿叧
+const shortageWarningVisible = ref(false)
+const currentWarningTank = ref({})
+const countdownTimer = ref(null)
+
+// 鍒嗛〉鍙傛暟
+const page = reactive({
+  current: 1,
+  size: 10
+})
+
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  tankName: '',
+  tankType: '',
+  warningType: '',
+  warningLevel: ''
+})
+
+// 琛ㄥ崟鏁版嵁
+const form = reactive({
+  id: null,
+  tankCode: '',
+  tankName: '',
+  tankType: '',
+  specificationModel: '',
+  volume: 0,
+  currentGasLevel: 0,
+  safetyGasLevel: 0,
+  minGasLevel: 0,
+  maxGasLevel: 0,
+  currentPressure: 0,
+  warningType: '',
+  warningLevel: '',
+  warningThreshold: 0,
+  isEnabled: true,
+  warningTime: '',
+  warningDuration: 0,
+  lastUpdateTime: '',
+  expectedRefillTime: '',
+  expectedShortageTime: '',
+  warningRule: ''
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = {
+  tankCode: [{ required: true, message: '璇疯緭鍏ュ偍姘旂綈缂栫爜', trigger: 'blur' }],
+  tankName: [{ required: true, message: '璇疯緭鍏ュ偍姘旂綈鍚嶇О', trigger: 'blur' }],
+  tankType: [{ required: true, message: '璇烽�夋嫨鍌ㄦ皵缃愮被鍨�', trigger: 'change' }],
+  warningType: [{ required: true, message: '璇烽�夋嫨棰勮绫诲瀷', trigger: 'change' }],
+  warningLevel: [{ required: true, message: '璇烽�夋嫨棰勮绾у埆', trigger: 'change' }],
+  warningThreshold: [{ required: true, message: '璇疯緭鍏ラ璀﹂槇鍊�', trigger: 'blur' }]
+}
+
+// 鑾峰彇鍊掕鏃朵俊鎭�
+const getCountdown = (expectedTime) => {
+  if (!expectedTime) return { text: '-', isExpired: false }
+  
+  const now = new Date().getTime()
+  const expected = new Date(expectedTime).getTime()
+  const diff = expected - now
+  
+  if (diff <= 0) {
+    return { text: '宸茬己姘�', isExpired: true }
+  }
+  
+  const days = Math.floor(diff / (1000 * 60 * 60 * 24))
+  const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
+  const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
+  
+  if (days > 0) {
+    return { text: `${days}澶�${hours}灏忔椂`, isExpired: false }
+  } else if (hours > 0) {
+    return { text: `${hours}灏忔椂${minutes}鍒嗛挓`, isExpired: false }
+  } else {
+    return { text: `${minutes}鍒嗛挓`, isExpired: false }
+  }
+}
+
+// 鑾峰彇鍊掕鏃舵牱寮忕被
+const getCountdownClass = (expectedTime) => {
+  if (!expectedTime) return ''
+  
+  const now = new Date().getTime()
+  const expected = new Date(expectedTime).getTime()
+  const diff = expected - now
+  
+  if (diff <= 0) {
+    return 'countdown-expired'
+  } else if (diff <= 24 * 60 * 60 * 1000) { // 24灏忔椂鍐�
+    return 'countdown-urgent'
+  } else if (diff <= 7 * 24 * 60 * 60 * 1000) { // 7澶╁唴
+    return 'countdown-warning'
+  } else {
+    return 'countdown-normal'
+  }
+}
+
+// 妫�鏌ョ己姘旈璀�
+const checkShortageWarnings = () => {
+  tableData.value.forEach(tank => {
+    if (tank.expectedShortageTime) {
+      const countdown = getCountdown(tank.expectedShortageTime)
+      if (countdown.isExpired && !tank.warningShown) {
+        // 鏍囪宸叉樉绀洪璀︼紝閬垮厤閲嶅寮规
+        tank.warningShown = true
+        showShortageWarning(tank)
+      }
+    }
+  })
+}
+
+// 鏄剧ず缂烘皵棰勮寮规
+const showShortageWarning = (tank) => {
+  currentWarningTank.value = tank
+  shortageWarningVisible.value = true
+  
+  // 鎾斁鎻愮ず闊筹紙鍙�夛級
+  // const audio = new Audio('/path/to/warning-sound.mp3')
+  // audio.play()
+}
+
+// 澶勭悊缂烘皵棰勮
+const handleShortageWarning = () => {
+  ElMessage.success(`姝e湪澶勭悊鍌ㄦ皵缃� ${currentWarningTank.value.tankName} 鐨勭己姘旈棶棰榒)
+  shortageWarningVisible.value = false
+  // 杩欓噷鍙互璋冪敤澶勭悊API
+}
+// 澶勭悊缂烘皵棰勮
+const closeShortageWarning = () => {
+  // ElMessage.success(`姝e湪澶勭悊鍌ㄦ皵缃� ${currentWarningTank.value.tankName} 鐨勭己姘旈棶棰榒)
+  shortageWarningVisible.value = false
+  // 杩欓噷鍙互璋冪敤澶勭悊API
+}
+
+
+
+// 鐢熸垚鍋囨暟鎹�
+const generateMockData = () => {
+  const mockData = [
+    {
+      id: 1,
+      tankCode: 'TANK001',
+      tankName: '娑插寲姘斿偍缃怉',
+      tankType: '娑插寲姘斿偍缃�',
+      specificationModel: 'LPG-5000L',
+      volume: 5000,
+      currentGasLevel: 15,
+      safetyGasLevel: 30,
+      minGasLevel: 10,
+      maxGasLevel: 95,
+      currentPressure: 2.5,
+      warningType: '姘斾綋涓嶈冻',
+      warningLevel: '绱ф��',
+      warningThreshold: 20,
+      isEnabled: true,
+      warningTime: '2024-01-15 08:30:00',
+      warningDuration: 3,
+      lastUpdateTime: '2024-01-15 10:00:00',
+      expectedRefillTime: '2024-01-16 14:00:00',
+      expectedShortageTime: '2024-01-15 18:30:00', // 浠婂ぉ涓嬪崍6:30缂烘皵
+      warningRule: '褰撴皵浣撻噺浣庝簬20%鏃惰Е鍙戦璀�'
+    },
+    {
+      id: 2,
+      tankCode: 'TANK002',
+      tankName: '鍘嬬缉姘斿偍缃怋',
+      tankType: '鍘嬬缉姘斿偍缃�',
+      specificationModel: 'COMP-3000L',
+      volume: 3000,
+      currentGasLevel: 45,
+      safetyGasLevel: 25,
+      minGasLevel: 15,
+      maxGasLevel: 90,
+      currentPressure: 8.2,
+      warningType: '鍘嬪姏寮傚父',
+      warningLevel: '閲嶈',
+      warningThreshold: 10,
+      isEnabled: true,
+      warningTime: '2024-01-14 16:20:00',
+      warningDuration: 2,
+      lastUpdateTime: '2024-01-15 09:15:00',
+      expectedRefillTime: '2024-01-17 09:00:00',
+      expectedShortageTime: '2024-01-18 12:00:00', // 3澶╁悗缂烘皵
+      warningRule: '褰撳帇鍔涜秴杩�8MPa鏃惰Е鍙戦璀�'
+    },
+    {
+      id: 3,
+      tankCode: 'TANK003',
+      tankName: '澶╃劧姘斿偍缃怌',
+      tankType: '澶╃劧姘斿偍缃�',
+      specificationModel: 'NG-8000L',
+      volume: 8000,
+      currentGasLevel: 75,
+      safetyGasLevel: 20,
+      minGasLevel: 10,
+      maxGasLevel: 95,
+      currentPressure: 4.8,
+      warningType: '娓╁害寮傚父',
+      warningLevel: '涓�鑸�',
+      warningThreshold: 5,
+      isEnabled: true,
+      warningTime: '2024-01-13 11:45:00',
+      warningDuration: 1,
+      lastUpdateTime: '2024-01-15 08:45:00',
+      expectedRefillTime: '2024-01-20 10:00:00',
+      expectedShortageTime: '2024-01-22 15:30:00', // 7澶╁悗缂烘皵
+      warningRule: '褰撴俯搴﹁秴杩�60掳C鏃惰Е鍙戦璀�'
+    },
+    {
+      id: 4,
+      tankCode: 'TANK004',
+      tankName: '姘ф皵鍌ㄧ綈D',
+      tankType: '姘ф皵鍌ㄧ綈',
+      specificationModel: 'O2-2000L',
+      volume: 2000,
+      currentGasLevel: 8,
+      safetyGasLevel: 25,
+      minGasLevel: 5,
+      maxGasLevel: 90,
+      currentPressure: 6.5,
+      warningType: '娉勬紡棰勮',
+      warningLevel: '绱ф��',
+      warningThreshold: 15,
+      isEnabled: true,
+      warningTime: '2024-01-15 07:15:00',
+      warningDuration: 4,
+      lastUpdateTime: '2024-01-15 11:30:00',
+      expectedRefillTime: '2024-01-15 16:00:00',
+      expectedShortageTime: '2024-01-15 14:00:00', // 浠婂ぉ涓嬪崍2鐐圭己姘�
+      warningRule: '褰撴娴嬪埌姘斾綋娉勬紡鏃惰Е鍙戦璀�'
+    },
+    {
+      id: 5,
+      tankCode: 'TANK005',
+      tankName: '娑插寲姘斿偍缃怑',
+      tankType: '娑插寲姘斿偍缃�',
+      specificationModel: 'LPG-6000L',
+      volume: 6000,
+      currentGasLevel: 35,
+      safetyGasLevel: 30,
+      minGasLevel: 15,
+      maxGasLevel: 95,
+      currentPressure: 3.2,
+      warningType: '姘斾綋涓嶈冻',
+      warningLevel: '閲嶈',
+      warningThreshold: 20,
+      isEnabled: false,
+      warningTime: '2024-01-14 14:30:00',
+      warningDuration: 2,
+      lastUpdateTime: '2024-01-15 09:00:00',
+      expectedRefillTime: '2024-01-19 08:00:00',
+      expectedShortageTime: '2024-01-21 10:00:00', // 6澶╁悗缂烘皵
+      warningRule: '褰撴皵浣撻噺浣庝簬20%鏃惰Е鍙戦璀�'
+    },
+    {
+      id: 6,
+      tankCode: 'TANK006',
+      tankName: '鍘嬬缉姘斿偍缃怓',
+      tankType: '鍘嬬缉姘斿偍缃�',
+      specificationModel: 'COMP-4000L',
+      volume: 4000,
+      currentGasLevel: 85,
+      safetyGasLevel: 20,
+      minGasLevel: 10,
+      maxGasLevel: 90,
+      currentPressure: 7.8,
+      warningType: '鍘嬪姏寮傚父',
+      warningLevel: '涓�鑸�',
+      warningThreshold: 8,
+      isEnabled: true,
+      warningTime: '2024-01-12 09:20:00',
+      warningDuration: 1,
+      lastUpdateTime: '2024-01-15 08:30:00',
+      expectedRefillTime: '2024-01-25 14:00:00',
+      expectedShortageTime: '2024-01-28 16:00:00', // 13澶╁悗缂烘皵
+      warningRule: '褰撳帇鍔涜秴杩�8MPa鏃惰Е鍙戦璀�'
+    },
+    {
+      id: 7,
+      tankCode: 'TANK007',
+      tankName: '澶╃劧姘斿偍缃怗',
+      tankType: '澶╃劧姘斿偍缃�',
+      specificationModel: 'NG-10000L',
+      volume: 10000,
+      currentGasLevel: 92,
+      safetyGasLevel: 15,
+      minGasLevel: 8,
+      maxGasLevel: 95,
+      currentPressure: 5.2,
+      warningType: '娓╁害寮傚父',
+      warningLevel: '閲嶈',
+      warningThreshold: 6,
+      isEnabled: true,
+      warningTime: '2024-01-11 16:45:00',
+      warningDuration: 1,
+      lastUpdateTime: '2024-01-15 07:45:00',
+      expectedRefillTime: '2024-01-30 09:00:00',
+      expectedShortageTime: '2024-02-05 12:00:00', // 21澶╁悗缂烘皵
+      warningRule: '褰撴俯搴﹁秴杩�60掳C鏃惰Е鍙戦璀�'
+    },
+    {
+      id: 8,
+      tankCode: 'TANK008',
+      tankName: '姘ф皵鍌ㄧ綈H',
+      tankType: '姘ф皵鍌ㄧ綈',
+      specificationModel: 'O2-1500L',
+      volume: 1500,
+      currentGasLevel: 12,
+      safetyGasLevel: 30,
+      minGasLevel: 8,
+      maxGasLevel: 90,
+      currentPressure: 4.5,
+      warningType: '娉勬紡棰勮',
+      warningLevel: '绱ф��',
+      warningThreshold: 12,
+      isEnabled: true,
+      warningTime: '2024-01-15 06:30:00',
+      warningDuration: 5,
+      lastUpdateTime: '2024-01-15 12:15:00',
+      expectedRefillTime: '2024-01-15 20:00:00',
+      expectedShortageTime: '2024-01-15 17:30:00', // 浠婂ぉ涓嬪崍5:30缂烘皵
+      warningRule: '褰撴娴嬪埌姘斾綋娉勬紡鏃惰Е鍙戦璀�'
+    }
+  ]
+  
+  // 鏍规嵁鎼滅储鏉′欢杩囨护鏁版嵁
+  let filteredData = mockData.filter(item => {
+    if (searchForm.tankName && !item.tankName.includes(searchForm.tankName)) return false
+    if (searchForm.tankType && item.tankType !== searchForm.tankType) return false
+    if (searchForm.warningType && item.warningType !== searchForm.warningType) return false
+    if (searchForm.warningLevel && item.warningLevel !== searchForm.warningLevel) return false
+    return true
+  })
+  
+  // 鍒嗛〉澶勭悊
+  const start = (page.current - 1) * page.size
+  const end = start + page.size
+  const paginatedData = filteredData.slice(start, end)
+  
+  return {
+    records: paginatedData,
+    total: filteredData.length
+  }
+}
+
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = async () => {
+  tableLoading.value = true
+  try {
+    // 妯℃嫙缃戠粶寤惰繜
+    await new Promise(resolve => setTimeout(resolve, 500))
+    
+    const result = generateMockData()
+    tableData.value = result.records
+    total.value = result.total
+    
+    // 妫�鏌ョ己姘旈璀�
+    checkShortageWarnings()
+  } catch (error) {
+    console.error('鑾峰彇鍒楄〃澶辫触:', error)
+    ElMessage.error('鑾峰彇鍒楄〃澶辫触')
+  } finally {
+    tableLoading.value = false
+  }
+}
+
+// 鎼滅储
+const handleQuery = () => {
+  page.current = 1
+  getList()
+}
+
+// 閲嶇疆鎼滅储
+const resetQuery = () => {
+  Object.keys(searchForm).forEach(key => {
+    searchForm[key] = ''
+  })
+  handleQuery()
+}
+
+// 鍒嗛〉鍙樺寲
+const paginationChange = (obj) => {
+  page.current = obj.page
+  page.size = obj.limit
+  getList()
+}
+
+// 琛ㄦ牸閫夋嫨鍙樺寲
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection
+}
+
+// 鏂板
+const handleAdd = () => {
+  operationType.value = 'add'
+  resetForm()
+  dialogFormVisible.value = true
+}
+
+// 缂栬緫
+const handleEdit = (row) => {
+  operationType.value = 'edit'
+  Object.assign(form, row)
+  dialogFormVisible.value = true
+}
+
+// 澶勭悊棰勮
+const handleProcess = async (row) => {
+  try {
+    // 妯℃嫙API璋冪敤寤惰繜
+    await new Promise(resolve => setTimeout(resolve, 300))
+    ElMessage.success(`姝e湪澶勭悊棰勮锛�${row.tankName}`)
+    getList()
+  } catch (error) {
+    ElMessage.error('澶勭悊棰勮澶辫触')
+  }
+}
+
+// 鍒犻櫎
+const handleDelete = async (row) => {
+  try {
+    await ElMessageBox.confirm(`纭畾瑕佸垹闄ら璀﹁鍒欙細${row.tankName}鍚楋紵`, '鎻愮ず', {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: 'warning'
+    })
+    
+    // 妯℃嫙API璋冪敤寤惰繜
+    await new Promise(resolve => setTimeout(resolve, 300))
+    ElMessage.success('鍒犻櫎鎴愬姛')
+    getList()
+  } catch (error) {
+    if (error !== 'cancel') {
+      ElMessage.error('鍒犻櫎澶辫触')
+    }
+  }
+}
+
+// 鎵归噺澶勭悊
+const handleBatchProcess = async () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning('璇烽�夋嫨瑕佸鐞嗙殑棰勮')
+    return
+  }
+  
+  try {
+    // 妯℃嫙API璋冪敤寤惰繜
+    await new Promise(resolve => setTimeout(resolve, 500))
+    ElMessage.success(`鎵归噺澶勭悊浜� ${selectedRows.value.length} 鏉¢璀)
+    getList()
+  } catch (error) {
+    ElMessage.error('鎵归噺澶勭悊澶辫触')
+  }
+}
+
+// 瀵煎嚭
+const handleExport = async () => {
+  try {
+    // 妯℃嫙API璋冪敤寤惰繜
+    await new Promise(resolve => setTimeout(resolve, 800))
+    
+    // 鐢熸垚瀵煎嚭鏁版嵁
+    const exportData = generateMockData().records
+    const csvContent = generateCSV(exportData)
+    
+    // 鍒涘缓涓嬭浇閾炬帴
+    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
+    const url = window.URL.createObjectURL(blob)
+    const link = document.createElement('a')
+    link.href = url
+    link.download = `鍌ㄦ皵缃愰璀︽暟鎹甠${new Date().getTime()}.csv`
+    link.click()
+    window.URL.revokeObjectURL(url)
+    
+    ElMessage.success('瀵煎嚭鎴愬姛')
+  } catch (error) {
+    ElMessage.error('瀵煎嚭澶辫触')
+  }
+}
+
+// 鐢熸垚CSV鍐呭
+const generateCSV = (data) => {
+  const headers = [
+    '鍌ㄦ皵缃愮紪鐮�', '鍌ㄦ皵缃愬悕绉�', '鍌ㄦ皵缃愮被鍨�', '瑙勬牸鍨嬪彿', '瀹圭Н(m鲁)', 
+    '褰撳墠姘斾綋閲�(%)', '瀹夊叏姘斾綋閲�(%)', '鏈�浣庢皵浣撻噺(%)', '鏈�楂樻皵浣撻噺(%)', 
+    '褰撳墠鍘嬪姏(MPa)', '棰勮绫诲瀷', '棰勮绾у埆', '棰勮闃堝��', '鏄惁鍚敤',
+    '棰勮鏃堕棿', '棰勮鎸佺画澶╂暟', '鏈�鍚庢洿鏂版椂闂�', '棰勮鍏呰鏃堕棿', '棰勮缂烘皵鏃堕棿', '棰勮瑙勫垯鎻忚堪'
+  ]
+  
+  const csvRows = [headers.join(',')]
+  
+  data.forEach(item => {
+    const row = [
+      item.tankCode,
+      item.tankName,
+      item.tankType,
+      item.specificationModel,
+      item.volume,
+      item.currentGasLevel,
+      item.safetyGasLevel,
+      item.minGasLevel,
+      item.maxGasLevel,
+      item.currentPressure,
+      item.warningType,
+      item.warningLevel,
+      item.warningThreshold,
+      item.isEnabled ? '鏄�' : '鍚�',
+      item.warningTime,
+      item.warningDuration,
+      item.lastUpdateTime,
+      item.expectedRefillTime,
+      item.expectedShortageTime,
+      item.warningRule
+    ]
+    csvRows.push(row.join(','))
+  })
+  
+  return csvRows.join('\n')
+}
+
+// 鍚敤鐘舵�佸彉鍖�
+const handleEnableChange = async (row) => {
+  try {
+    // 妯℃嫙API璋冪敤寤惰繜
+    await new Promise(resolve => setTimeout(resolve, 200))
+    ElMessage.success(`${row.tankName} 鐨勫惎鐢ㄧ姸鎬佸凡鏇存柊`)
+  } catch (error) {
+    ElMessage.error('鐘舵�佹洿鏂板け璐�')
+    // 鎭㈠鍘熺姸鎬�
+    row.isEnabled = !row.isEnabled
+  }
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+  try {
+    await proxy.$refs.formRef.validate()
+    
+    // 妯℃嫙API璋冪敤寤惰繜
+    await new Promise(resolve => setTimeout(resolve, 500))
+    
+    if (operationType.value === 'add') {
+      ElMessage.success('鏂板鎴愬姛')
+    } else {
+      ElMessage.success('缂栬緫鎴愬姛')
+    }
+    
+    closeDialog()
+    getList()
+  } catch (error) {
+    if (!error.errors) {
+      ElMessage.error(operationType.value === 'add' ? '鏂板澶辫触' : '缂栬緫澶辫触')
+    }
+  }
+}
+
+// 鍏抽棴寮圭獥
+const closeDialog = () => {
+  dialogFormVisible.value = false
+  resetForm()
+}
+
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+  Object.keys(form).forEach(key => {
+    if (key === 'isEnabled') {
+      form[key] = true
+    } else if (typeof form[key] === 'number') {
+      form[key] = 0
+    } else {
+      form[key] = ''
+    }
+  })
+  proxy.$refs.formRef?.resetFields()
+}
+
+// 鑾峰彇姘斾綋閲忔牱寮忕被
+const getGasLevelClass = (row) => {
+  if (row.currentGasLevel < row.minGasLevel) {
+    return 'text-danger'
+  } else if (row.currentGasLevel > row.maxGasLevel) {
+    return 'text-warning'
+  }
+  return 'text-success'
+}
+
+// 鑾峰彇棰勮绫诲瀷鏍囩鏍峰紡
+const getWarningTypeTag = (type) => {
+  const typeMap = {
+    '姘斾綋涓嶈冻': 'danger',
+    '鍘嬪姏寮傚父': 'warning',
+    '娓╁害寮傚父': 'info',
+    '娉勬紡棰勮': 'danger'
+  }
+  return typeMap[type] || 'info'
+}
+
+// 鑾峰彇棰勮绾у埆鏍囩鏍峰紡
+const getWarningLevelTag = (level) => {
+  const levelMap = {
+    '绱ф��': 'danger',
+    '閲嶈': 'warning',
+    '涓�鑸�': 'info'
+  }
+  return levelMap[level] || 'info'
+}
+
+// 鍚姩鍊掕鏃跺畾鏃跺櫒
+const startCountdownTimer = () => {
+  countdownTimer.value = setInterval(() => {
+    checkShortageWarnings()
+  }, 60000) // 姣忓垎閽熸鏌ヤ竴娆�
+}
+
+// 鍋滄鍊掕鏃跺畾鏃跺櫒
+const stopCountdownTimer = () => {
+  if (countdownTimer.value) {
+    clearInterval(countdownTimer.value)
+    countdownTimer.value = null
+  }
+}
+
+// 椤甸潰鍔犺浇
+onMounted(() => {
+  getList()
+  startCountdownTimer()
+})
+
+// 椤甸潰鍗歌浇
+onUnmounted(() => {
+  stopCountdownTimer()
+})
+</script>
+
+<style scoped lang="scss">
+.app-container {
+  padding: 20px;
+  
+  .table-operations {
+    text-align: right;
+    margin-bottom: 20px;
+    
+    .el-button {
+      margin-right: 10px;
+    }
+  }
+  
+  .table_list {
+    background: #fff;
+    border-radius: 4px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  }
+  
+  .text-danger {
+    color: #f56c6c;
+    font-weight: bold;
+  }
+  
+  .text-warning {
+    color: #e6a23c;
+    font-weight: bold;
+  }
+  
+  .text-success {
+    color: #67c23a;
+    font-weight: bold;
+  }
+  
+  .dialog-footer {
+    text-align: right;
+  }
+  
+  // 鍊掕鏃舵牱寮�
+  .countdown-timer {
+    font-weight: bold;
+  }
+  
+  .countdown-normal {
+    color: #67c23a;
+  }
+  
+  .countdown-warning {
+    color: #e6a23c;
+  }
+  
+  .countdown-urgent {
+    color: #f56c6c;
+    animation: blink 1s infinite;
+  }
+  
+  .countdown-expired {
+    color: #f56c6c;
+    font-weight: bold;
+  }
+  
+  @keyframes blink {
+    0%, 50% { opacity: 1; }
+    51%, 100% { opacity: 0.5; }
+  }
+  
+  // 缂烘皵棰勮寮规鏍峰紡
+  .shortage-warning-content {
+    text-align: center;
+    padding: 20px 0;
+    
+    .warning-icon {
+      margin-bottom: 20px;
+    }
+    
+    .warning-message {
+      h3 {
+        color: #f56c6c;
+        margin-bottom: 10px;
+      }
+      
+      p {
+        margin-bottom: 10px;
+        color: #606266;
+      }
+      
+      .warning-details {
+        background: #f5f7fa;
+        padding: 15px;
+        border-radius: 4px;
+        text-align: left;
+        font-size: 14px;
+        line-height: 1.6;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/personnelManagement/payrollManagement/components/formDia.vue b/src/views/personnelManagement/payrollManagement/components/formDia.vue
new file mode 100644
index 0000000..6dbc326
--- /dev/null
+++ b/src/views/personnelManagement/payrollManagement/components/formDia.vue
@@ -0,0 +1,315 @@
+<template>
+  <div>
+    <el-dialog
+        v-model="dialogFormVisible"
+        :title="operationType === 'add' ? '鏂板鍏ヨ亴' : '缂栬緫浜哄憳'"
+        width="50%"
+        @close="closeDia"
+    >
+      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鏈堜唤锛�" prop="payDate">
+							<el-date-picker
+								v-model="form.payDate"
+								type="month"
+								value-format="YYYY-MM-DD"
+								format="YYYY-MM"
+								placeholder="璇烽�夋嫨鏈堜唤"
+								clearable
+								:disabled="operationType === 'edit'"
+								style="width: 100%"
+							/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="濮撳悕锛�" prop="staffId">
+							<el-select v-model="form.staffId" placeholder="璇烽�夋嫨浜哄憳" style="width: 100%" @change="handleSelect" :disabled="operationType === 'edit'">
+								<el-option
+									v-for="item in personList"
+									:key="item.id"
+									:label="item.staffName"
+									:value="item.id"
+								/>
+							</el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="搴斿嚭鍕ゅぉ鏁帮細" prop="shouldAttendedNum">
+							<el-input v-model="form.shouldAttendedNum" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="瀹為檯鍑哄嫟澶╂暟锛�" prop="actualAttendedNum">
+              <el-input v-model="form.actualAttendedNum" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鍩烘湰宸ヨ祫锛�" prop="basicSalary">
+              <el-input v-model="form.basicSalary" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="宀椾綅宸ヨ祫锛�" prop="postSalary">
+              <el-input v-model="form.postSalary" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鍏ョ鑱岀己鍕ゆ墸娆撅細" prop="deductionAbsenteeism">
+              <el-input v-model="form.deductionAbsenteeism" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鐥呭亣鎵f锛�" prop="sickLeaveDeductions">
+              <el-input v-model="form.sickLeaveDeductions" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="浜嬪亣鎵f锛�" prop="deductionPersonalLeave">
+              <el-input v-model="form.deductionPersonalLeave" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="蹇樿鎵撳崱鎵f锛�" prop="forgetClockDeduct">
+              <el-input v-model="form.forgetClockDeduct" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="缁╂晥寰楀垎锛�" prop="performanceScore">
+              <el-input v-model="form.performanceScore" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="缁╂晥宸ヨ祫锛�" prop="performancePay">
+              <el-input v-model="form.performancePay" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="搴斿彂鍚堣锛�" prop="payableWages">
+              <el-input v-model="form.payableWages" placeholder="璇疯緭鍏�" clearable type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="绀句繚涓汉锛�" prop="socialSecurityIndividuals">
+              <el-input v-model="form.socialSecurityIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="绀句繚鍏徃锛�" prop="socialSecurityCompanies">
+							<el-input v-model="form.socialSecurityCompanies" :precision="0" :step="1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="绀句繚鍚堣锛�" prop="socialSecurityTotal">
+							<el-input v-model="form.socialSecurityTotal" :precision="0" :step="1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鍏Н閲戜釜浜猴細" prop="providentFundIndividuals">
+							<el-input v-model="form.providentFundIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍏Н閲戝叕鍙革細" prop="providentFundCompany">
+							<el-input v-model="form.providentFundCompany" :precision="0" :step="1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="鍏Н閲戝悎璁★細" prop="providentFundTotal">
+							<el-input v-model="form.providentFundTotal" :precision="0" :step="1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="搴旂◣宸ヨ祫锛�" prop="taxableWaget">
+							<el-input v-model="form.taxableWaget" :precision="0" :step="1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="涓汉鎵�寰楃◣锛�" prop="personalIncomeTax">
+							<el-input v-model="form.personalIncomeTax" :step="0.1" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="瀹炲彂宸ヨ祫锛�" prop="actualWages">
+							<el-input v-model="form.actualWages" style="width: 100%" type="number"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭</el-button>
+          <el-button @click="closeDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import {getStaffJoinInfo, getStaffOnJob, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
+import {compensationAdd, compensationUpdate} from "@/api/personnelManagement/payrollManagement.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const data = reactive({
+  form: {
+		payDate: "",
+    staffId: "",
+		name: "",
+		shouldAttendedNum: "",
+		actualAttendedNum: "",
+		basicSalary: "",
+		postSalary: "",
+		deductionAbsenteeism: "",
+		sickLeaveDeductions: "",
+		deductionPersonalLeave: "",
+		forgetClockDeduct: "",
+		performanceScore: "",
+		performancePay: "",
+		payableWages: "",
+		socialSecurityIndividuals: "",
+		socialSecurityCompanies: "",
+		socialSecurityTotal: "",
+		providentFundIndividuals: "",
+		providentFundCompany: "",
+		providentFundTotal: "",
+		taxableWaget: "",
+		personalIncomeTax: "",
+		actualWages: "",
+  },
+  rules: {
+		payDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" },],
+		staffId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" },],
+    staffName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		shouldAttendedNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		actualAttendedNum: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		basicSalary: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		postSalary: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		deductionAbsenteeism: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		sickLeaveDeductions: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		deductionPersonalLeave: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		forgetClockDeduct: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		performanceScore: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		performancePay: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		payableWages: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		socialSecurityIndividuals: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		socialSecurityCompanies: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		socialSecurityTotal: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		providentFundIndividuals: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		providentFundCompany: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		providentFundTotal: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		taxableWaget: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		personalIncomeTax: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		actualWages: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+  },
+});
+const { form, rules } = toRefs(data);
+const personList = ref([]);
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+  operationType.value = type;
+  dialogFormVisible.value = true;
+	getStaffOnJob().then(res => {
+		personList.value = res.data
+	})
+	form.value = {}
+  if (operationType.value === 'edit') {
+    getStaffJoinInfo(row.id).then(res => {
+			form.value = {...row}
+			form.value.payDate = form.value.payDate + '-01'
+    })
+  }
+}
+const handleSelect = (value) => {
+	console.log('value', value)
+	const index = personList.value.findIndex(row => row.id === value)
+	if (index > -1) {
+		form.value.name = personList.value[index].staffName
+	}
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitForm = () => {
+  proxy.$refs.formRef.validate(valid => {
+    if (valid) {
+      form.value.staffState = 1
+      if (operationType.value === "add") {
+				compensationAdd(form.value).then(res => {
+          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+          closeDia();
+        })
+      } else {
+				compensationUpdate(form.value).then(res => {
+          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+          closeDia();
+        })
+      }
+    }
+  })
+}
+// 璁$畻鍚堝悓骞撮檺
+const calculateContractTerm = () => {
+  if (form.value.contractStartTime && form.value.contractEndTime) {
+    const startDate = new Date(form.value.contractStartTime);
+    const endDate = new Date(form.value.contractEndTime);
+    
+    if (endDate > startDate) {
+      // 璁$畻骞翠唤宸�
+      const yearDiff = endDate.getFullYear() - startDate.getFullYear();
+      const monthDiff = endDate.getMonth() - startDate.getMonth();
+      const dayDiff = endDate.getDate() - startDate.getDate();
+      
+      let years = yearDiff;
+      
+      // 濡傛灉缁撴潫鏃ユ湡鐨勬湀鏃ュ皬浜庡紑濮嬫棩鏈熺殑鏈堟棩锛屽垯鍑忓幓1骞�
+      if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
+        years = yearDiff - 1;
+      }
+      
+      form.value.contractTerm = Math.max(0, years);
+    } else {
+      form.value.contractTerm = 0;
+    }
+  } else {
+    form.value.contractTerm = 0;
+  }
+};
+
+// 鍏抽棴寮规
+const closeDia = () => {
+  proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+  emit('close')
+};
+defineExpose({
+  openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/payrollManagement/index.vue b/src/views/personnelManagement/payrollManagement/index.vue
new file mode 100644
index 0000000..1de23e4
--- /dev/null
+++ b/src/views/personnelManagement/payrollManagement/index.vue
@@ -0,0 +1,291 @@
+<template>
+	<div class="app-container">
+		<div class="search_form">
+			<div>
+				<span class="search_title">濮撳悕锛�</span>
+				<el-input
+					v-model="searchForm.name"
+					style="width: 240px"
+					placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
+					@change="handleQuery"
+					clearable
+					:prefix-icon="Search"
+				/>
+				<span class="search_title ml10">鏈堜唤锛�</span>
+				<el-date-picker
+					v-model="searchForm.payDateStr"
+					type="month"
+					@change="handleQuery"
+					value-format="YYYY-MM"
+					format="YYYY-MM"
+					placeholder="璇烽�夋嫨鏈堜唤"
+					style="width: 240px"
+					clearable
+				/>
+				<el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+				>鎼滅储</el-button
+				>
+			</div>
+			<div>
+				<el-button type="primary" @click="openForm('add')">鏂板钖祫</el-button>
+<!--				<el-button @click="handleOut">瀵煎嚭</el-button>-->
+				<el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+			</div>
+		</div>
+		<div class="table_list">
+			<PIMTable
+				rowKey="id"
+				:column="tableColumn"
+				:tableData="tableData"
+				:page="page"
+				:isSelection="true"
+				@selection-change="handleSelectionChange"
+				:tableLoading="tableLoading"
+				@pagination="pagination"
+				:total="page.total"
+			></PIMTable>
+		</div>
+		<form-dia ref="formDia" @close="handleQuery"></form-dia>
+	</div>
+</template>
+
+<script setup>
+import { Search } from "@element-plus/icons-vue";
+import {onMounted, ref} from "vue";
+import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue";
+import {staffJoinDel} from "@/api/personnelManagement/onboarding.js";
+import {ElMessageBox} from "element-plus";
+import dayjs from "dayjs";
+import {compensationDelete, compensationListPage} from "@/api/personnelManagement/payrollManagement.js";
+
+const data = reactive({
+	searchForm: {
+		name: "",
+		payDateStr: "",
+	},
+});
+const { searchForm } = toRefs(data);
+const tableColumn = ref([
+	{
+		label: "钖祫鏈堜唤",
+		prop: "payDate",
+	},
+	{
+		label: "濮撳悕",
+		prop: "name",
+	},
+	{
+		label: "搴斿嚭鍕ゅぉ鏁�",
+		prop: "shouldAttendedNum",
+		width:100
+	},
+	{
+		label: "瀹為檯鍑哄嫟澶╂暟",
+		prop: "actualAttendedNum",
+		width:110
+	},
+	{
+		label: "鍩烘湰宸ヨ祫",
+		prop: "basicSalary",
+	},
+	{
+		label: "宀椾綅宸ヨ祫",
+		prop: "postSalary",
+		width:100
+	},
+	{
+		label: "鍏ョ鑱岀己鍕ゆ墸娆�",
+		prop: "deductionAbsenteeism",
+		width:130
+	},
+	{
+		label: "鐥呭亣鎵f",
+		prop: "sickLeaveDeductions",
+		width:100
+	},
+	{
+		label: "浜嬪亣鎵f",
+		prop: "deductionPersonalLeave",
+		width:100
+	},
+	{
+		label: "蹇樿鎵撳崱鎵f",
+		prop: "forgetClockDeduct",
+		width:110
+	},
+	{
+		label: "缁╂晥寰楀垎",
+		prop: "performanceScore",
+		width:150
+	},
+	{
+		label: "缁╂晥宸ヨ祫",
+		prop: "performancePay",
+		width: 120
+	},
+	{
+		label: "搴斿彂鍚堣",
+		prop: "payableWages",
+		width:150
+	},
+	{
+		label: "绀句繚涓汉",
+		prop: "socialSecurityIndividuals",
+	},
+	{
+		label: "绀句繚鍏徃",
+		prop: "socialSecurityCompanies",
+		width: 120
+	},
+	{
+		label: "绀句繚鍚堣",
+		prop: "socialSecurityTotal",
+		width: 120
+	},
+	{
+		label: "鍏Н閲戜釜浜�",
+		prop: "providentFundIndividuals",
+		width: 120
+	},
+	{
+		label: "鍏Н閲戝叕鍙�",
+		prop: "providentFundCompany",
+		width: 120
+	},
+	{
+		label: "鍏Н閲戝悎璁�",
+		prop: "providentFundTotal",
+		width: 120
+	},
+	{
+		label: "搴旂◣宸ヨ祫",
+		prop: "taxableWaget",
+	},
+	{
+		label: "涓汉鎵�寰楃◣",
+		prop: "personalIncomeTax",
+		width: 120
+	},
+	{
+		label: "瀹炲彂宸ヨ祫",
+		prop: "actualWages",
+		width: 120
+	},
+	{
+		dataType: "action",
+		label: "鎿嶄綔",
+		align: "center",
+		fixed: 'right',
+		operation: [
+			{
+				name: "缂栬緫",
+				type: "text",
+				clickFun: (row) => {
+					openForm("edit", row);
+				},
+			},
+		],
+	},
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+	current: 1,
+	size: 100,
+	total: 0,
+});
+const formDia = ref()
+const { proxy } = getCurrentInstance()
+
+const handleDateChange = (value,type) => {
+	searchForm.value.entryDateEnd = null
+	searchForm.value.entryDateStart = null
+	if(type === 1){
+		if (value) {
+			searchForm.value.entryDateStart = dayjs(value).format("YYYY-MM-DD");
+		}
+	}else{
+		if (value) {
+			searchForm.value.entryDateEnd = dayjs(value).format("YYYY-MM-DD");
+		}
+	}
+	getList();
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+	page.current = 1;
+	getList();
+};
+const pagination = (obj) => {
+	page.current = obj.page;
+	page.size = obj.limit;
+	getList();
+};
+const getList = () => {
+	tableLoading.value = true;
+	compensationListPage({...page, ...searchForm.value, staffState: 1}).then(res => {
+		tableLoading.value = false;
+		tableData.value = res.data.records
+		page.total = res.data.total;
+	}).catch(err => {
+		tableLoading.value = false;
+	})
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+	selectedRows.value = selection;
+};
+
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+	nextTick(() => {
+		formDia.value?.openDialog(type, row)
+	})
+};
+
+// 鍒犻櫎
+const handleDelete = () => {
+	let ids = [];
+	if (selectedRows.value.length > 0) {
+		ids = selectedRows.value.map((item) => item.id);
+	} else {
+		proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+		return;
+	}
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			compensationDelete(ids).then((res) => {
+				proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+				getList();
+			});
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
+};
+// 瀵煎嚭
+const handleOut = () => {
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			proxy.download("/staff/staffJoinLeaveRecord/export", {staffState: 1}, "浜哄憳鍏ヨ亴.xlsx");
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
+};
+onMounted(() => {
+	getList();
+});
+</script>
+
+<style scoped></style>
diff --git a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
index be15275..b61f84a 100644
--- a/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -54,7 +54,8 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="鏁伴噺锛�" prop="quantity">
-              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="璇疯緭鍏�" clearable :precision="2"/>
+              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.quantity" placeholder="璇疯緭鍏�"
+                               clearable :precision="2"/>
             </el-form-item>
           </el-col>
         </el-row>
@@ -67,8 +68,8 @@
           <el-col :span="12">
             <el-form-item label="妫�娴嬬粨鏋滐細" prop="checkResult">
               <el-select v-model="form.checkResult">
-                <el-option label="鍚堟牸" value="鍚堟牸" />
-                <el-option label="涓嶅悎鏍�" value="涓嶅悎鏍�" />
+                <el-option label="鍚堟牸" value="鍚堟牸"/>
+                <el-option label="涓嶅悎鏍�" value="涓嶅悎鏍�"/>
               </el-select>
             </el-form-item>
           </el-col>
@@ -77,7 +78,7 @@
           <el-col :span="12">
             <el-form-item label="妫�楠屽憳锛�" prop="checkName">
               <el-input v-model="form.checkName" placeholder="璇疯緭鍏�" clearable/>
-            
+
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -95,6 +96,22 @@
           </el-col>
         </el-row>
       </el-form>
+      <div style="margin-bottom: 10px;text-align: right">
+        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+      </div>
+      <PIMTable
+          rowKey="id"
+          :column="tableColumn"
+          :tableData="tableData"
+          :tableLoading="tableLoading"
+          :isSelection="true"
+          @selection-change="handleSelectionChange"
+          height="400"
+      >
+        <template #slot="{ row }">
+          <el-input v-model="row.testValue" clearable/>
+        </template>
+      </PIMTable>
       <template #footer>
         <div class="dialog-footer">
           <el-button type="primary" @click="submitForm">纭</el-button>
@@ -110,7 +127,11 @@
 import {getOptions} from "@/api/procurementManagement/procurementLedger.js";
 import {productTreeList} from "@/api/basicData/product.js";
 import {qualityInspectAdd, qualityInspectUpdate} from "@/api/qualityManagement/rawMaterialInspection.js";
-const { proxy } = getCurrentInstance()
+import {ElMessageBox} from "element-plus";
+import {qualityInspectParamDel, qualityInspectParamInfo} from "@/api/qualityManagement/qualityInspectParam.js";
+import {qualityInspectDetailByProductId} from "@/api/qualityManagement/metricMaintenance.js";
+
+const {proxy} = getCurrentInstance()
 const emit = defineEmits(['close'])
 
 const dialogFormVisible = ref(false);
@@ -129,20 +150,48 @@
     checkResult: "",
   },
   rules: {
-    checkTime: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" },],
-    supplier: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    checkName: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
-    productId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    model: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
-    unit: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
-    quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    checkCompany: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
-    checkResult: [{ required: true, message: "璇烽�夋嫨妫�娴嬬粨鏋�", trigger: "change" }],
+    checkTime: [{required: false, message: "璇疯緭鍏�", trigger: "blur"},],
+    supplier: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+    checkName: [{required: false, message: "璇疯緭鍏�", trigger: "blur"}],
+    productId: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+    model: [{required: false, message: "璇疯緭鍏�", trigger: "blur"}],
+    unit: [{required: false, message: "璇疯緭鍏�", trigger: "blur"}],
+    quantity: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
+    checkCompany: [{required: false, message: "璇疯緭鍏�", trigger: "blur"}],
+    checkResult: [{required: true, message: "璇烽�夋嫨妫�娴嬬粨鏋�", trigger: "change"}],
   },
 });
-const { form, rules } = toRefs(data);
+const tableColumn = ref([
+  {
+    label: "鎸囨爣",
+    prop: "parameterItem",
+  },
+  {
+    label: "鍗曚綅",
+    prop: "unit",
+  },
+  {
+    label: "鏍囧噯鍊�",
+    prop: "standardValue",
+  },
+  {
+    label: "鍐呮帶鍊�",
+    prop: "controlValue",
+  },
+  {
+    label: "妫�楠屽��",
+    prop: "testValue",
+    dataType: 'slot',
+    slot: 'slot',
+  },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+
+const {form, rules} = toRefs(data);
 const supplierList = ref([]);
 const productOptions = ref([]);
+const currentProductId = ref(0);
 
 // 鎵撳紑寮规
 const openDialog = (type, row) => {
@@ -154,6 +203,8 @@
   getProductOptions();
   if (operationType.value === 'edit') {
     form.value = {...row}
+    currentProductId.value = row.productId || 0
+    getQualityInspectParamList(row.id)
   }
 }
 const getProductOptions = () => {
@@ -162,7 +213,11 @@
   });
 };
 const getModels = (value) => {
+  currentProductId.value = value
   form.value.productName = findNodeById(productOptions.value, value);
+  if (currentProductId) {
+    getList();
+  }
 };
 const findNodeById = (nodes, productId) => {
   for (let i = 0; i < nodes.length; i++) {
@@ -178,9 +233,10 @@
   }
   return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
 };
+
 function convertIdToValue(data) {
   return data.map((item) => {
-    const { id, children, ...rest } = item;
+    const {id, children, ...rest} = item;
     const newItem = {
       ...rest,
       value: id, // 灏� id 鏀逛负 value
@@ -188,22 +244,24 @@
     if (children && children.length > 0) {
       newItem.children = convertIdToValue(children);
     }
-    
+
     return newItem;
   });
 }
+
 // 鎻愪氦浜у搧琛ㄥ崟
 const submitForm = () => {
   proxy.$refs.formRef.validate(valid => {
     if (valid) {
       form.value.inspectType = 0
+      const data = {...form.value, qualityInspectParams: tableData.value}
       if (operationType.value === "add") {
-        qualityInspectAdd(form.value).then(res => {
+        qualityInspectAdd(data).then(res => {
           proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
           closeDia();
         })
       } else {
-        qualityInspectUpdate(form.value).then(res => {
+        qualityInspectUpdate(data).then(res => {
           proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
           closeDia();
         })
@@ -211,9 +269,50 @@
     }
   })
 }
+
+const handleSelectionChange = (selection) => {
+  selectedRows.value = selection;
+};
+
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+    ids = selectedRows.value.map((item) => item.id);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+      .then(() => {
+        qualityInspectParamDel(ids).then((res) => {
+          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+          getList();
+        });
+      })
+      .catch(() => {
+        proxy.$modal.msg("宸插彇娑�");
+      });
+};
+
+const getList = () => {
+  qualityInspectDetailByProductId(currentProductId.value).then(res => {
+    tableData.value = res.data;
+  })
+}
+
+const getQualityInspectParamList = (id) => {
+  qualityInspectParamInfo(id).then(res => {
+    tableData.value = res.data;
+  })
+}
 // 鍏抽棴寮规
 const closeDia = () => {
   proxy.resetForm("formRef");
+  tableData.value = []
   dialogFormVisible.value = false;
   emit('close')
 };
diff --git a/src/views/qualityManagement/rawMaterialInspection/index.vue b/src/views/qualityManagement/rawMaterialInspection/index.vue
index bbee1bc..16db3eb 100644
--- a/src/views/qualityManagement/rawMaterialInspection/index.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -11,11 +11,12 @@
             clearable
             :prefix-icon="Search"
         />
-        <span  style="margin-left: 10px" class="search_title">妫�娴嬫棩鏈燂細</span>
-        <el-date-picker  v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
-                        placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
+        <span style="margin-left: 10px" class="search_title">妫�娴嬫棩鏈燂細</span>
+        <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+                        placeholder="璇烽�夋嫨" clearable @change="changeDaterange"/>
         <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
-        >鎼滅储</el-button
+        >鎼滅储
+        </el-button
         >
       </div>
       <div>
@@ -40,18 +41,42 @@
     <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
     <FormDia ref="formDia" @close="handleQuery"></FormDia>
     <files-dia ref="filesDia" @close="handleQuery"></files-dia>
+    <el-dialog v-model="dialogFormVisible" title="缂栬緫妫�楠屽憳" width="70%"
+               @close="closeDia">
+      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+        <el-form-item label="妫�楠屽憳锛�" prop="checkName">
+          <el-select v-model="form.checkName" placeholder="璇烽�夋嫨" clearable>
+            <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
+                       :value="item.nickName"/>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭</el-button>
+          <el-button @click="closeDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
   </div>
 </template>
 
 <script setup>
-import { Search } from "@element-plus/icons-vue";
+import {Search} from "@element-plus/icons-vue";
 import {onMounted, ref} from "vue";
 import InspectionFormDia from "@/views/qualityManagement/rawMaterialInspection/components/inspectionFormDia.vue";
 import FormDia from "@/views/qualityManagement/rawMaterialInspection/components/formDia.vue";
 import {ElMessageBox} from "element-plus";
-import {qualityInspectDel, qualityInspectListPage} from "@/api/qualityManagement/rawMaterialInspection.js";
+import {
+  downloadQualityInspect,
+  qualityInspectDel,
+  qualityInspectListPage, qualityInspectUpdate,
+  submitQualityInspect
+} from "@/api/qualityManagement/rawMaterialInspection.js";
 import FilesDia from "@/views/qualityManagement/rawMaterialInspection/components/filesDia.vue";
 import dayjs from "dayjs";
+import {userListNoPage} from "@/api/system/user.js";
 
 const data = reactive({
   searchForm: {
@@ -63,8 +88,11 @@
     entryDateStart: dayjs().format("YYYY-MM-DD"),
     entryDateEnd: dayjs().add(1, "day").format("YYYY-MM-DD"),
   },
+  rules: {
+    checkName: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
+  },
 });
-const { searchForm } = toRefs(data);
+const {searchForm, rules} = toRefs(data);
 const tableColumn = ref([
   {
     label: "妫�娴嬫棩鏈�",
@@ -107,12 +135,23 @@
     prop: "checkResult",
     dataType: "tag",
     formatType: (params) => {
-      if (params == '涓嶅悎鏍�') {
+      if (params === '涓嶅悎鏍�') {
         return "danger";
-      } else if (params == '鍚堟牸') {
+      } else if (params === '鍚堟牸') {
         return "success";
       } else {
         return null;
+      }
+    },
+  },
+  {
+    label: "鎻愪氦鐘舵��",
+    prop: "inspectState",
+    formatData: (params) => {
+      if (params) {
+        return "宸叉彁浜�";
+      } else {
+        return "鏈彁浜�";
       }
     },
   },
@@ -121,7 +160,7 @@
     label: "鎿嶄綔",
     align: "center",
     fixed: "right",
-    width: 190,
+    width: 250,
     operation: [
       {
         name: "缂栬緫",
@@ -131,17 +170,35 @@
         },
       },
       {
-        name: "鏂板妫�楠岃褰�",
-        type: "text",
-        clickFun: (row) => {
-          openInspectionForm("edit", row);
-        },
-      },
-      {
         name: "闄勪欢",
         type: "text",
         clickFun: (row) => {
           openFilesFormDia(row);
+        },
+      },
+      {
+        name: "鎻愪氦",
+        type: "text",
+        clickFun: (row) => {
+          submit(row.id);
+        },
+      },
+      {
+        name: "鍒嗛厤妫�楠屽憳",
+        type: "text",
+        clickFun: (row) => {
+          if (!row.checkName) {
+            open(row)
+          } else {
+            proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
+          }
+        },
+      },
+      {
+        name: "涓嬭浇",
+        type: "text",
+        clickFun: (row) => {
+          downLoadFile(row);
         },
       },
     ],
@@ -150,15 +207,21 @@
 const tableData = ref([]);
 const selectedRows = ref([]);
 const tableLoading = ref(false);
+const userList = ref([]);
+const dialogFormVisible = ref(false);
+const form = ref({
+  checkName: ""
+});
 const page = reactive({
   current: 1,
   size: 100,
   total: 0
 });
+const currentRow = ref(null)
 const formDia = ref()
 const filesDia = ref()
 const inspectionFormDia = ref()
-const { proxy } = getCurrentInstance()
+const {proxy} = getCurrentInstance()
 const changeDaterange = (value) => {
   searchForm.value.entryDateStart = undefined;
   searchForm.value.entryDateEnd = undefined;
@@ -181,7 +244,7 @@
 };
 const getList = () => {
   tableLoading.value = true;
-  const params = { ...searchForm.value, ...page };
+  const params = {...searchForm.value, ...page};
   params.entryDate = undefined
   qualityInspectListPage({...params, inspectType: 0}).then(res => {
     tableLoading.value = false;
@@ -253,6 +316,62 @@
         proxy.$modal.msg("宸插彇娑�");
       });
 };
+
+// 鎻愪环
+const submit = async (id) => {
+  const res = await submitQualityInspect({id: id})
+  if (res.code === 200) {
+    proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+    getList();
+  }
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+  proxy.resetForm("formRef");
+  dialogFormVisible.value = false;
+};
+
+const submitForm = () => {
+  if (currentRow.value) {
+    const data = {
+      ...form.value,
+      id: currentRow.value.id
+    }
+    qualityInspectUpdate(data).then(res => {
+      proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+      closeDia();
+      getList();
+    })
+  }
+};
+
+const open = async (row) => {
+  let userLists = await userListNoPage();
+  userList.value = userLists.data;
+  currentRow.value = row
+  dialogFormVisible.value = true
+}
+
+const downLoadFile = (row) => {
+  downloadQualityInspect({id: row.id}).then(res => {
+    // 鍒涘缓 blob 瀵硅薄
+    const blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'})
+    const downloadUrl = window.URL.createObjectURL(blob)
+
+    // 鍒涘缓涓存椂 <a> 鏍囩杩涜涓嬭浇
+    const link = document.createElement('a')
+    link.href = downloadUrl
+    link.download = '妫�楠屾姤鍛�.docx' // 杩欓噷鍜屽悗绔竴鑷�
+    document.body.appendChild(link)
+    link.click()
+
+    // 娓呯悊
+    document.body.removeChild(link)
+    window.URL.revokeObjectURL(downloadUrl)
+  })
+};
+
 onMounted(() => {
   getList();
 });

--
Gitblit v1.9.3