From 19f2e3bdbe04e7ea79c6a0bdc8c7318d4837b189 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 28 五月 2026 17:36:45 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_pro_山西_晋和园
---
src/views/officeProcessAutomation/ApproveManage/approve-template/components/FormConfigEditor.vue | 857 +
src/api/basicData/enum.js | 8
src/layout/index.vue | 23
src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceFormConfigTable.js | 116
src/views/qualityManagement/rawMaterialInspection/index.vue | 797
src/assets/system/cangchuwuliu.svg | 1
src/views/qualityManagement/finalInspection/index.vue | 840
src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue | 260
src/views/qualityManagement/processInspection/index.vue | 829
src/views/productionManagement/workOrderManagement/index.vue | 2
src/views/officeProcessAutomation/HrManage/staff-contract/index.vue | 296
src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/useCostReimburse.js | 634 +
src/views/personnelManagement/contractManagement/components/formDia.vue | 151
src/views/officeProcessAutomation/HrManage/staff-archive/components/Show.vue | 69
src/views/productionManagement/productionTraceability/index.vue | 2
src/views/officeProcessAutomation/EnterpriseNews/news-manage/index.vue | 566
src/views/officeProcessAutomation/HrManage/staff-contract/components/formDia.vue | 93
multiple/assets/favicon/HQJCfavicon.ico | 0
src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/components/DetailPanel.vue | 74
src/views/safeProduction/safetyTrainingAssessment/index.vue | 25
src/views/officeProcessAutomation/HrManage/staff-archive/components/NewOrEditFormDia.vue | 304
src/assets/system/fahuotaizhang.svg | 1
src/assets/system/组 210683.svg | 1
src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalTemplateBindingUtils.js | 91
src/assets/system/shengchanpaichan.svg | 1
src/views/officeProcessAutomation/HrManage/resign-apply/index.vue | 220
multiple/assets/favicon/BWSMfavicon.ico | 0
multiple/assets/logo/BWSMLogo.png | 0
src/assets/system/chanpinweihu.svg | 1
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsUtils.js | 207
multiple/assets/logo/HQJCLogo.png | 0
src/views/financialManagement/receivable/receipt.vue | 26
src/views/officeProcessAutomation/SysMonitor/server-monitor/index.vue | 191
src/views/financialManagement/assets/fixedAssets.vue | 21
src/components/AIChatSidebar/assistants/financeAssistant.js | 6
src/api/officeProcessAutomation/approvalTemplate.js | 58
src/assets/system/yonghuguanli.svg | 1
src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js | 628 +
src/views/officeProcessAutomation/AttendManage/leave-apply/index.vue | 325
src/assets/system/caigoutuihuo.svg | 1
src/views/officeProcessAutomation/ApproveManage/approve-template/useSelectOptionSources.js | 45
src/views/customerService/feedbackRegistration/index.vue | 27
src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceListSearch.js | 158
src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/ApprovalFlowProgress.vue | 49
src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js | 609 +
src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userAvatar.vue | 168
src/views/officeProcessAutomation/SysAdmin/user-manage/authRole.vue | 123
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateFormSection.vue | 122
src/assets/system/gongyingshangdangan.svg | 1
src/assets/system/baogong.svg | 1
src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js | 189
src/assets/system/chukuguanli.svg | 1
src/views/salesManagement/receiptPaymentLedger/index.vue | 6
src/views/salesManagement/salesLedger/index.vue | 4765 ++++----
src/views/officeProcessAutomation/ApproveManage/approve-template/selectOptionSource.js | 140
src/views/officeProcessAutomation/HrManage/regular-apply/index.vue | 174
src/assets/system/shengchandingdan.svg | 1
src/views/financialManagement/assets/intangibleAssets.vue | 21
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsMappers.js | 221
src/assets/system/caigoupeizhi.svg | 1
src/views/inventoryManagement/stockManagement/Record.vue | 640
src/assets/system/xiaoshoutaizhang.svg | 1
src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/DetailPanel.vue | 82
src/assets/system/xiaoshoupeizhi.svg | 1
src/api/officeProcessAutomation/finReimbursement.js | 71
src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue | 613 +
src/assets/styles/sidebar.scss | 37
src/api/officeProcessAutomation/enterpriseNews.js | 38
src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/index.vue | 614 +
src/views/equipmentManagement/inspectionManagement/index.vue | 2
src/views/officeProcessAutomation/ContractManage/sale-contract/index.vue | 12
src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js | 355
src/views/qualityManagement/nearExpiryReturn/index.vue | 628
src/views/officeProcessAutomation/HrManage/post-manage/index.vue | 292
src/views/officeProcessAutomation/EnterpriseNews/news-manage/components/NewsDetailPanel.vue | 169
src/views/officeProcessAutomation/SysMonitor/data-monitor/index.vue | 14
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplatePicker.vue | 85
src/views/officeProcessAutomation/ReimburseManage/shared/components/FinReimburseApprovePanel.vue | 70
src/assets/system/xiaoshoubaojia.svg | 1
src/assets/system/zhushengchanjihua.svg | 1
src/views/safeProduction/dangerInvestigation/index.vue | 2
src/views/financialManagement/receivable/salesOut.vue | 257
src/views/officeProcessAutomation/HrManage/staff-archive/components/JobInfoSection.vue | 176
src/views/officeProcessAutomation/HrManage/resign-apply/components/formDia.vue | 347
src/api/procurementManagement/procurementLedger.js | 73
src/views/basicData/parameterMaintenance/index.vue | 22
src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementMappers.js | 904 +
src/views/officeProcessAutomation/ReimburseManage/shared/reimburseApproveBridge.js | 124
src/views/officeProcessAutomation/ApproveManage/approve-list/components/ApproveDetailPanel.vue | 167
src/views/officeProcessAutomation/NoticeAnnouncement/notice-manage/index.vue | 12
src/views/personnelManagement/contractManagement/index.vue | 2
src/assets/system/shenpiguanli.svg | 1
src/views/officeProcessAutomation/SysMonitor/cache-monitor/index.vue | 134
src/views/collaborativeApproval/purchaseApproval/index.vue | 23
src/views/officeProcessAutomation/ContractManage/purchase-contract/index.vue | 12
src/assets/system/gongxu.svg | 1
src/views/officeProcessAutomation/SysAdmin/log-manage/index.vue | 315
src/views/procurementManagement/procurementPlan/index.vue | 1194 +
multiple/assets/logo/CKGMLogo.png | 0
src/assets/system/rukuguanli.svg | 1
src/assets/system/zhibiaotongji.svg | 1
src/views/inventoryManagement/receiptManagement/Record.vue | 595
src/views/officeProcessAutomation/HrManage/staff-archive/index.vue | 360
src/assets/system/jichupeizhi.svg | 1
src/assets/system/xiaoshoutuihuo.svg | 1
src/assets/system/kucunguanli.svg | 1
src/components/AIChatSidebar/assistants/productionAssistant.js | 19
src/views/equipmentManagement/repair/Modal/RepairModal.vue | 4
src/views/officeProcessAutomation/SysAdmin/user-manage/profile/resetPwd.vue | 59
src/views/officeProcessAutomation/EnterpriseNews/news-manage/useEnterpriseNewsList.js | 55
src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js | 160
src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js | 301
src/assets/system/baogongtaizhang.svg | 1
src/views/officeProcessAutomation/AttendManage/overtime-apply/components/ApprovalFlowEditor.vue | 360
src/views/financialManagement/payable/paymentApply.vue | 48
src/views/procurementManagement/procurementLedger/index.vue | 1021 +
src/views/financialManagement/payable/purchaseIn.vue | 2
multiple/assets/favicon/CKGMfavicon.ico | 0
src/views/officeProcessAutomation/ApproveManage/approve-list/components/InstanceFlowDisplay.vue | 147
src/assets/system/shengchanheduan.svg | 1
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue | 123
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue | 112
src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userInfo.vue | 67
src/views/officeProcessAutomation/ApproveManage/approve-template/components/TemplateFlowEditor.vue | 399
src/views/officeProcessAutomation/SysAdmin/dept-manage/index.vue | 291
src/assets/system/BOM.svg | 1
src/assets/system/gongyingshangwanglai.svg | 1
src/assets/logo/XDRJ.png | 0
src/views/officeProcessAutomation/HrManage/staff-archive/components/RenewContract.vue | 141
src/views/procurementManagement/qualityInspection/index.vue | 42
multiple/config.json | 164
src/components/AIChatSidebar/assistants/purchaseAssistant.js | 15
src/views/productionManagement/workOrder/index.vue | 2
src/views/procurementManagement/purchaseOrder/index.vue | 27
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsApprovalBridge.js | 11
src/views/officeProcessAutomation/HrManage/work-handover/index.vue | 249
src/views/productManagement/productIdentifier/index.vue | 21
src/views/inventoryManagement/dispatchLog/Record.vue | 1427 +-
src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalModuleRegistry.js | 152
src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue | 347
src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/index.vue | 550
src/views/officeProcessAutomation/HrManage/staff-archive/components/EmergencyAndAttachmentSection.vue | 115
src/layout/components/Sidebar/SidebarItem.vue | 107
src/views/officeProcessAutomation/HrManage/staff-archive/components/EducationWorkSection.vue | 263
src/views/officeProcessAutomation/HrManage/staff-archive/components/BasicInfoSection.vue | 181
src/views/officeProcessAutomation/ApproveManage/approve-list/components/FormPayloadFields.vue | 152
src/assets/system/caigoutaizhang.svg | 1
src/views/officeProcessAutomation/HrManage/staff-contract/filesDia.vue | 197
src/assets/system/caigoubaobiao.svg | 1
src/views/officeProcessAutomation/SysAdmin/user-manage/profile/index.vue | 87
src/views/financialManagement/receivable/invoiceApply.vue | 30
src/views/officeProcessAutomation/ApproveManage/approve-shared/useFlowUserOptions.js | 35
src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js | 334
src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalInstanceModule.js | 408
multiple/assets/logo/XDRJ.png | 0
src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/useTravelReimburse.js | 696 +
src/assets/system/shengchanpeizhi.svg | 1
src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/costReimburseUtils.js | 313
src/views/systemArchitecture/index.vue | 226
src/views/productionPlan/productionPlan/index.vue | 51
src/views/officeProcessAutomation/SysAdmin/user-manage/index.vue | 550
src/api/officeProcessAutomation/approvalInstance.js | 47
src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalTemplateBinding.js | 259
src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue | 176
src/assets/system/ai.svg | 1
src/assets/system/kehudangan.svg | 1
src/assets/system/kehuwanglai.svg | 1
src/views/officeProcessAutomation/ApproveManage/approve-template/index.vue | 819 +
168 files changed, 27,977 insertions(+), 6,395 deletions(-)
diff --git a/multiple/assets/favicon/BWSMfavicon.ico b/multiple/assets/favicon/BWSMfavicon.ico
new file mode 100644
index 0000000..12c7cd0
--- /dev/null
+++ b/multiple/assets/favicon/BWSMfavicon.ico
Binary files differ
diff --git a/multiple/assets/favicon/CKGMfavicon.ico b/multiple/assets/favicon/CKGMfavicon.ico
new file mode 100644
index 0000000..7668e42
--- /dev/null
+++ b/multiple/assets/favicon/CKGMfavicon.ico
Binary files differ
diff --git a/multiple/assets/favicon/HQJCfavicon.ico b/multiple/assets/favicon/HQJCfavicon.ico
new file mode 100644
index 0000000..65e6942
--- /dev/null
+++ b/multiple/assets/favicon/HQJCfavicon.ico
Binary files differ
diff --git a/multiple/assets/logo/BWSMLogo.png b/multiple/assets/logo/BWSMLogo.png
new file mode 100644
index 0000000..044d31c
--- /dev/null
+++ b/multiple/assets/logo/BWSMLogo.png
Binary files differ
diff --git a/multiple/assets/logo/CKGMLogo.png b/multiple/assets/logo/CKGMLogo.png
new file mode 100644
index 0000000..cfa60b2
--- /dev/null
+++ b/multiple/assets/logo/CKGMLogo.png
Binary files differ
diff --git a/multiple/assets/logo/HQJCLogo.png b/multiple/assets/logo/HQJCLogo.png
new file mode 100644
index 0000000..5e21e9c
--- /dev/null
+++ b/multiple/assets/logo/HQJCLogo.png
Binary files differ
diff --git "a/src/assets/logo/\350\212\257\345\257\274\350\275\257\344\273\266\357\274\210\346\261\237\350\213\217\357\274\211\346\234\211\351\231\220\345\205\254\345\217\270.png" b/multiple/assets/logo/XDRJ.png
similarity index 100%
copy from "src/assets/logo/\350\212\257\345\257\274\350\275\257\344\273\266\357\274\210\346\261\237\350\213\217\357\274\211\346\234\211\351\231\220\345\205\254\345\217\270.png"
copy to multiple/assets/logo/XDRJ.png
Binary files differ
diff --git a/multiple/config.json b/multiple/config.json
index 0458f35..fac0511 100644
--- a/multiple/config.json
+++ b/multiple/config.json
@@ -12,9 +12,171 @@
"VITE_BASE_API": "http://223.15.233.27:9001",
"VITE_JAVA_API": "http://223.15.233.27:9002"
},
- "logo": "logo/Logo.png",
+ "logo": "logo/XDRJ.png",
"favicon": "favicon/favicon.ico"
},
+ "BTYX": {
+ "env": {
+ "VITE_APP_TITLE": "娌冲崡甯お浼橀�夐鍝佹湁闄愬叕鍙�",
+ "VITE_BASE_API": "http://1.15.17.182:9056",
+ "VITE_JAVA_API": "http://1.15.17.182:9057"
+ },
+ "logo": "logo/BTYXLogo.png",
+ "favicon": "favicon/BTYXfavicon.ico"
+ },
+ "ZXZN": {
+ "env": {
+ "VITE_APP_TITLE": "娌冲崡鏅鸿姱鏅鸿兘鏈哄櫒浜烘湁闄愬叕鍙�",
+ "VITE_BASE_API": "http://127.0.0.1:9001",
+ "VITE_JAVA_API": "http://127.0.0.1:9000"
+ },
+ "logo": "logo/ZXZNLogo.png",
+ "favicon": "favicon/ZXZNfavicon.ico"
+ },
+ "SDTX": {
+ "env": {
+ "VITE_APP_TITLE": "娌冲崡鍠勯紟閫氫俊绉戞妧鏈夐檺鍏徃",
+ "VITE_BASE_API": "http://36.213.156.184:9001",
+ "VITE_JAVA_API": "http://36.213.156.184:9000"
+ },
+ "logo": "logo/SDTXLogo.png",
+ "favicon": "favicon/SDTXfavicon.ico"
+ },
+ "QXY": {
+ "env": {
+ "VITE_APP_TITLE": "寮轰俊瀹囩數鍣ㄧ鐞嗙郴缁�",
+ "VITE_BASE_API": "http://36.134.154.10:9001",
+ "VITE_JAVA_API": "http://36.134.154.10:9000"
+ },
+ "logo": "logo/QXYLogo.png",
+ "favicon": "favicon/QXYfavicon.ico"
+ },
+ "HQJC": {
+ "env": {
+ "VITE_APP_TITLE": "鍗庡己寤烘潗绠$悊绯荤粺",
+ "VITE_BASE_API": "http://36.134.77.64:9001",
+ "VITE_JAVA_API": "http://36.134.77.64:9000"
+ },
+ "logo": "logo/HQJCLogo.png",
+ "favicon": "favicon/HQJCfavicon.ico"
+ },
+ "XCDQ": {
+ "env": {
+ "VITE_APP_TITLE": "鏃櫒鐢靛櫒绠$悊绯荤粺",
+ "VITE_BASE_API": "http://36.133.45.183:9001",
+ "VITE_JAVA_API": "http://36.133.45.183:9002"
+ },
+ "logo": "logo/XCDQLogo.png",
+ "favicon": "favicon/XCDQfavicon.ico"
+ },
+ "BWSM": {
+ "env": {
+ "VITE_APP_TITLE": "鍏淮鍟嗚锤绠$悊绯荤粺",
+ "VITE_BASE_API": "http://1.15.17.182:9070",
+ "VITE_JAVA_API": "http://1.15.17.182:9069"
+ },
+ "logo": "logo/BWSMLogo.png",
+ "favicon": "favicon/BWSMfavicon.ico"
+ },
+ "CKGM": {
+ "env": {
+ "VITE_APP_TITLE": "瀹稿悍宸ヨ锤绠$悊绯荤粺",
+ "VITE_BASE_API": "http://1.15.17.182:9072",
+ "VITE_JAVA_API": "http://1.15.17.182:9071"
+ },
+ "logo": "logo/CKGMLogo.png",
+ "favicon": "favicon/CKGMfavicon.ico"
+ },
+ "ZQSY": {
+ "env": {
+ "VITE_APP_TITLE": "娉芥穱瀹炰笟",
+ "VITE_BASE_API": "http://36.213.128.159:9000",
+ "VITE_JAVA_API": "http://36.213.128.159:9001"
+ },
+ "logo": "logo/ZQSYLogo.png",
+ "favicon": "favicon/ZQSYfavicon.ico"
+ },
+ "JXJH": {
+ "env": {
+ "VITE_APP_TITLE": "娴氬幙姹熸捣姘存偿鍒跺搧鏈夐檺鍏徃",
+ "VITE_BASE_API": "http://36.139.201.20:9000",
+ "VITE_JAVA_API": "http://36.139.201.20:9001"
+ },
+ "logo": "logo/JXJHLogo.png",
+ "favicon": "favicon/JXJHfavicon.ico"
+ },
+ "YTJZ": {
+ "env": {
+ "VITE_APP_TITLE": "璞嘲寤虹瓚鏉愭枡鏈夐檺鍏徃",
+ "VITE_BASE_API": "http://36.139.201.181:9000",
+ "VITE_JAVA_API": "http://36.139.201.181:9001"
+ },
+ "logo": "logo/YTJZLogo.png",
+ "favicon": "favicon/YTJZfavicon.ico"
+ },
+ "HYLQ": {
+ "env": {
+ "VITE_APP_TITLE": "鑸�歌矾妗ュ伐绋嬫湁闄愬叕鍙�",
+ "VITE_BASE_API": "http://36.139.202.111:9000",
+ "VITE_JAVA_API": "http://36.139.202.111:9001"
+ },
+ "logo": "logo/HYLQLogo.png",
+ "favicon": "favicon/HYLQfavicon.ico"
+ },
+ "QXY": {
+ "env": {
+ "VITE_APP_TITLE": "寮轰俊瀹囩數鍣ㄤ簯涓绘満",
+ "VITE_BASE_API": "http://36.134.154.10:9000",
+ "VITE_JAVA_API": "http://36.134.154.10:9001"
+ },
+ "logo": "logo/QXYLogo.png",
+ "favicon": "favicon/QXYfavicon.ico"
+ },
+ "HYJC": {
+ "env": {
+ "VITE_APP_TITLE": "鎭掓磱寤烘潗",
+ "VITE_BASE_API": "http://36.138.94.178:9000",
+ "VITE_JAVA_API": "http://36.138.94.178:9001"
+ },
+ "logo": "logo/HYJCLogo.png",
+ "favicon": "favicon/HYJCfavicon.ico"
+ },
+ "JHY": {
+ "env": {
+ "VITE_APP_TITLE": "灞辫タ鐪佹绀惧幙鏅嬪拰鍥鍝佹湁闄愬叕鍙�",
+ "VITE_BASE_API": "http://223.15.233.27:9001",
+ "VITE_JAVA_API": "http://223.15.233.27:9002"
+ },
+ "logo": "logo/JHYLogo.png",
+ "favicon": "favicon/JHYfavicon.ico"
+ },
+ "XCDQ": {
+ "env": {
+ "VITE_APP_TITLE": "鏃櫒鐢靛櫒绠$悊绯荤粺",
+ "VITE_BASE_API": "http://36.133.45.183:9001",
+ "VITE_JAVA_API": "http://36.133.45.183:9002"
+ },
+ "logo": "logo/XCDQLogo.png",
+ "favicon": "favicon/XCDQfavicon.ico"
+ },
+ "KYHG": {
+ "env": {
+ "VITE_APP_TITLE": "灞辫タ鍧ゆ簮鍖栧伐鏈夐檺鍏徃",
+ "VITE_BASE_API": "http://36.137.13.29:9001",
+ "VITE_JAVA_API": "http://36.137.13.29:9002"
+ },
+ "logo": "logo/KYHGLogo.png",
+ "favicon": "favicon/KYHGfavicon.ico"
+ },
+ "JXSM": {
+ "env": {
+ "VITE_APP_TITLE": "瑗勫灒鍘挎磥閼晢璐告湁闄愬叕鍙�",
+ "VITE_BASE_API": "http://36.134.76.148:9001",
+ "VITE_JAVA_API": "http://36.134.76.148:9002"
+ },
+ "logo": "logo/JXSMLogo.png",
+ "favicon": "favicon/JXSMico.ico"
+ },
"logo": "/src/assets/logo/logo.png",
"favicon": "/public/favicon.ico"
}
\ No newline at end of file
diff --git a/src/api/basicData/enum.js b/src/api/basicData/enum.js
index 350df17..9e8b503 100644
--- a/src/api/basicData/enum.js
+++ b/src/api/basicData/enum.js
@@ -1,5 +1,13 @@
import request from "@/utils/request.js";
+/** 瀹℃壒妯℃澘绫诲瀷绛夐�氱敤鏋氫妇锛圱ypeEnums锛� */
+export function getTypeEnums() {
+ return request({
+ url: '/basic/enum/TypeEnums',
+ method: 'get'
+ })
+}
+
export function findAllStockRecordTypeOptions() {
return request({
url: '/basic/enum/stockRecordType',
diff --git a/src/api/officeProcessAutomation/approvalInstance.js b/src/api/officeProcessAutomation/approvalInstance.js
new file mode 100644
index 0000000..054861c
--- /dev/null
+++ b/src/api/officeProcessAutomation/approvalInstance.js
@@ -0,0 +1,47 @@
+import request from "@/utils/request";
+
+/** 鍒嗛〉鏌ヨ瀹℃壒瀹炰緥 */
+export function listApprovalInstancePage(params) {
+ return request({
+ url: "/approvalInstance/listPage",
+ method: "get",
+ params,
+ });
+}
+
+/** 鎻愪氦/淇濆瓨瀹℃壒瀹炰緥 */
+export function saveApprovalInstance(approvalInstanceDto) {
+ return request({
+ url: "/approvalInstance/save",
+ method: "post",
+ data: approvalInstanceDto,
+ });
+}
+
+/** 鏇存柊瀹℃壒瀹炰緥 */
+export function updateApprovalInstance(approvalInstanceDto) {
+ return request({
+ url: "/approvalInstance/update",
+ method: "put",
+ data: approvalInstanceDto,
+ });
+}
+
+/** 瀹℃壒锛堥�氳繃/椹冲洖锛� */
+export function approveApprovalInstance(approvalInstanceDto) {
+ return request({
+ url: "/approvalInstance/approve",
+ method: "post",
+ data: approvalInstanceDto,
+ });
+}
+
+/** 鍒犻櫎瀹℃壒瀹炰緥锛坆ody 涓� ID 鏁扮粍锛� */
+export function deleteApprovalInstance(ids) {
+ const idList = (Array.isArray(ids) ? ids : [ids]).filter((id) => id != null && id !== "");
+ return request({
+ url: "/approvalInstance/delete",
+ method: "delete",
+ data: idList,
+ });
+}
diff --git a/src/api/officeProcessAutomation/approvalTemplate.js b/src/api/officeProcessAutomation/approvalTemplate.js
new file mode 100644
index 0000000..3ade018
--- /dev/null
+++ b/src/api/officeProcessAutomation/approvalTemplate.js
@@ -0,0 +1,58 @@
+import request from "@/utils/request";
+
+/** 妯℃澘绫诲瀷锛�0 绯荤粺鍐呯疆锛�1 鑷畾涔夛紙涓庡悗绔� templateType 涓�鑷达級 */
+export const TEMPLATE_TYPE_BUILTIN = 0;
+export const TEMPLATE_TYPE_CUSTOM = 1;
+
+/** 鏌ヨ鎵�鏈夊鎵规ā鏉� */
+export function listApprovalTemplate(type) {
+ return request({
+ url: `/approvalTemplate/list/${type}`,
+ method: "get",
+ });
+}
+
+/** 鍒嗛〉鏌ヨ瀹℃壒妯℃澘 */
+export function listApprovalTemplatePage(params) {
+ return request({
+ url: "/approvalTemplate/listPage",
+ method: "get",
+ params,
+ });
+}
+
+/** 鏌ヨ瀹℃壒妯℃澘璇︽儏 */
+export function getApprovalTemplateDetail(id) {
+ return request({
+ url: `/approvalTemplate/detail/${id}`,
+ method: "get",
+ });
+}
+
+/** 鏂板瀹℃壒妯℃澘锛坆ody 涓� ApprovalTemplateDto锛� */
+export function addApprovalTemplate(approvalTemplateDto) {
+ return request({
+ url: "/approvalTemplate/add",
+ method: "post",
+ data: approvalTemplateDto,
+ });
+}
+
+/** 淇敼瀹℃壒妯℃澘锛坆ody 涓� ApprovalTemplateDto锛� */
+export function updateApprovalTemplate(approvalTemplateDto) {
+ return request({
+ url: "/approvalTemplate/update",
+ method: "put",
+ data: approvalTemplateDto,
+ });
+}
+
+/** 鍒犻櫎瀹℃壒妯℃澘锛坆ody 涓烘ā鏉� ID 鏁扮粍锛� */
+export function deleteApprovalTemplate(ids) {
+ const idList = (Array.isArray(ids) ? ids : [ids]).filter((id) => id != null && id !== "");
+ return request({
+ url: "/approvalTemplate/delete",
+ method: "post",
+ data: idList,
+ });
+}
diff --git a/src/api/officeProcessAutomation/enterpriseNews.js b/src/api/officeProcessAutomation/enterpriseNews.js
new file mode 100644
index 0000000..52f345d
--- /dev/null
+++ b/src/api/officeProcessAutomation/enterpriseNews.js
@@ -0,0 +1,38 @@
+import request from "@/utils/request";
+
+/** 鍒嗛〉鏌ヨ浼佷笟鏂伴椈 */
+export function listEnterpriseNewsPage(params) {
+ return request({
+ url: "/enterpriseNews/listPage",
+ method: "get",
+ params,
+ });
+}
+
+/** 鏂板浼佷笟鏂伴椈 */
+export function saveEnterpriseNews(enterpriseNewsDto) {
+ return request({
+ url: "/enterpriseNews/save",
+ method: "post",
+ data: enterpriseNewsDto,
+ });
+}
+
+/** 淇敼浼佷笟鏂伴椈 */
+export function updateEnterpriseNews(enterpriseNewsDto) {
+ return request({
+ url: "/enterpriseNews/update",
+ method: "put",
+ data: enterpriseNewsDto,
+ });
+}
+
+/** 鍒犻櫎浼佷笟鏂伴椈锛坆ody 涓� ID 鏁扮粍锛� */
+export function deleteEnterpriseNews(ids) {
+ const idList = (Array.isArray(ids) ? ids : [ids]).filter((id) => id != null && id !== "");
+ return request({
+ url: "/enterpriseNews/delete",
+ method: "delete",
+ data: idList,
+ });
+}
diff --git a/src/api/officeProcessAutomation/finReimbursement.js b/src/api/officeProcessAutomation/finReimbursement.js
new file mode 100644
index 0000000..84c3560
--- /dev/null
+++ b/src/api/officeProcessAutomation/finReimbursement.js
@@ -0,0 +1,71 @@
+import request from "@/utils/request";
+
+/** 鍒嗛〉鏌ヨ璐㈠姟鎶ラ攢 GET /finReimbursement/listPage */
+export function listFinReimbursementPage(params) {
+ return request({
+ url: "/finReimbursement/listPage",
+ method: "get",
+ params,
+ });
+}
+
+/** 璇︽儏 query锛歋pring 缁戝畾 finReimbursementDto.id锛屽嬁鐢� finReimbursementDto[id] */
+function buildFinReimbursementDetailParams(idOrDto) {
+ const raw =
+ typeof idOrDto === "object" && idOrDto !== null
+ ? idOrDto.id ?? idOrDto.reimbursementId
+ : idOrDto;
+ return {
+ "finReimbursementDto.id": raw,
+ id: raw,
+ };
+}
+
+/** 鏌ヨ璐㈠姟鎶ラ攢璇︽儏 GET /finReimbursement/detail */
+export function getFinReimbursementDetail(idOrDto) {
+ return request({
+ url: "/finReimbursement/detail",
+ method: "get",
+ params: buildFinReimbursementDetailParams(idOrDto),
+ });
+}
+
+/** 鏂板璐㈠姟鎶ラ攢 POST /finReimbursement/save */
+export function saveFinReimbursement(finReimbursementDto) {
+ return request({
+ url: "/finReimbursement/save",
+ method: "post",
+ data: finReimbursementDto,
+ });
+}
+
+/** 淇敼璐㈠姟鎶ラ攢 POST /finReimbursement/update */
+export function updateFinReimbursement(finReimbursementDto) {
+ return request({
+ url: "/finReimbursement/update",
+ method: "post",
+ data: finReimbursementDto,
+ });
+}
+
+/** 鍒犻櫎璐㈠姟鎶ラ攢 DELETE /finReimbursement/delete锛坆ody 涓� ID 鏁扮粍锛� */
+export function deleteFinReimbursement(ids) {
+ const idList = (Array.isArray(ids) ? ids : [ids]).filter(
+ (id) => id != null && id !== ""
+ );
+ return request({
+ url: "/finReimbursement/delete",
+ method: "delete",
+ data: idList,
+ });
+}
+
+/** 鏂板璧� save锛屼慨鏀硅蛋 update锛堜笌鎺ュ彛鏂囨。涓�鑷达級 */
+export function persistFinReimbursement(finReimbursementDto, isEdit = false) {
+ if (isEdit) {
+ return updateFinReimbursement(finReimbursementDto);
+ }
+ const payload = { ...finReimbursementDto };
+ delete payload.id;
+ return saveFinReimbursement(payload);
+}
diff --git a/src/api/procurementManagement/procurementLedger.js b/src/api/procurementManagement/procurementLedger.js
index 5f9df05..88f4ce0 100644
--- a/src/api/procurementManagement/procurementLedger.js
+++ b/src/api/procurementManagement/procurementLedger.js
@@ -66,60 +66,69 @@
});
}
-export function createPurchaseNo() {
+export function createPurchaseNo(entryDate) {
return request({
url: "/purchase/ledger/createPurchaseNo",
method: "get",
+ params: { entryDate },
});
}
export function updateApprovalStatus(query) {
- return request({
- url: "/purchase/ledger/updateApprovalStatus",
- method: "post",
- data: query,
- });
+ return request({
+ url: "/purchase/ledger/updateApprovalStatus",
+ method: "post",
+ data: query,
+ });
}
// 淇濆瓨閲囪喘妯℃澘
export function addPurchaseTemplate(data) {
- return request({
- url: "/purchaseLedgerTemplate/add",
- method: "post",
- data: data,
- });
+ return request({
+ url: "/purchaseLedgerTemplate/add",
+ method: "post",
+ data: data,
+ });
}
// 淇敼閲囪喘妯℃澘
export function updatePurchaseTemplate(data) {
- return request({
- url: "/purchaseLedgerTemplate/update",
- method: "post",
- data: data,
- });
+ return request({
+ url: "/purchaseLedgerTemplate/update",
+ method: "post",
+ data: data,
+ });
}
// 鏌ヨ閲囪喘妯℃澘
export function getPurchaseTemplateList(query) {
- return request({
- url: "/purchase/ledger/getPurchaseTemplateList",
- method: "get",
- params: query,
- });
+ return request({
+ url: "/purchase/ledger/getPurchaseTemplateList",
+ method: "get",
+ params: query,
+ });
}
// 鍒犻櫎閲囪喘妯℃澘
export function delPurchaseTemplate(id) {
- return request({
- url: "/purchaseLedgerTemplate/delete",
- method: "delete",
- data: id,
- });
+ return request({
+ url: "/purchaseLedgerTemplate/delete",
+ method: "delete",
+ data: id,
+ });
}
// 鏌ヨ閲囪喘璇︽儏
export function getPurchaseByCode(id) {
- return request({
- url: "/purchase/ledger/getPurchaseByCode",
- method: "get",
- params: id,
- });
-}
\ No newline at end of file
+ return request({
+ url: "/purchase/ledger/getPurchaseByCode",
+ method: "get",
+ params: id,
+ });
+}
+
+export function batchGeneratePurchaseInboundSteps(query) {
+ return request({
+ url: "/purchase/ledger/batchInsertPurchaseSteps",
+ method: "post",
+ data: query,
+ });
+}
diff --git "a/src/assets/logo/\350\212\257\345\257\274\350\275\257\344\273\266\357\274\210\346\261\237\350\213\217\357\274\211\346\234\211\351\231\220\345\205\254\345\217\270.png" b/src/assets/logo/XDRJ.png
similarity index 100%
rename from "src/assets/logo/\350\212\257\345\257\274\350\275\257\344\273\266\357\274\210\346\261\237\350\213\217\357\274\211\346\234\211\351\231\220\345\205\254\345\217\270.png"
rename to src/assets/logo/XDRJ.png
Binary files differ
diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss
index 685a0eb..5da0e59 100644
--- a/src/assets/styles/sidebar.scss
+++ b/src/assets/styles/sidebar.scss
@@ -216,33 +216,38 @@
& .nest-menu .el-sub-menu > .el-sub-menu__title,
& .el-sub-menu .el-menu-item {
min-width: 0 !important;
- width: calc(100% - 24px) !important;
- margin: 0 12px 8px !important;
- height: 46px;
- line-height: 46px;
- padding-left: 14px !important;
- padding-right: 14px !important;
- border-radius: 12px;
+ width: calc(100% - 32px) !important;
+ margin: 0 16px 6px !important;
+ height: 40px;
+ line-height: 40px;
+ padding-left: 12px !important;
+ padding-right: 12px !important;
+ border-radius: 8px;
transition: all 0.24s ease;
color: var(--sidebar-text);
- border: 1px solid rgba(255, 255, 255, 0.06) !important;
- background: linear-gradient(128deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
+ border: none !important;
+ background: transparent;
+ font-size: 13px;
&:hover {
- background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.07)) !important;
- border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3) !important;
- transform: translateX(2px);
+ background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.12) !important;
+ transform: translateX(4px);
}
&.is-active {
- background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important;
- background-size: 180% 180%;
+ background: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.85) !important;
color: #fff !important;
font-weight: 500;
- box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
- animation: sidebarActiveFlow 4.6s ease infinite;
+ box-shadow: 0 4px 12px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.25);
}
}
+
+ // 瀛愯彍鍗曞鍣ㄦ牱寮� - 澧炲姞缂╄繘鍜岃瑙夊眰娆�
+ & .el-sub-menu .el-menu {
+ padding: 4px 0 8px;
+ margin-left: 8px;
+ border-left: 2px solid rgba(255, 255, 255, 0.08);
+ }
}
.hideSidebar {
diff --git a/src/assets/system/BOM.svg b/src/assets/system/BOM.svg
new file mode 100644
index 0000000..9c7f434
--- /dev/null
+++ b/src/assets/system/BOM.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="62.90625" viewBox="0 0 59.5 62.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35778"><rect x="14" y="0" width="32" height="32" rx="0"/></clipPath></defs><path d="M1.204819142818451,26.096379L28.69276814281845,42.307213000000004L58.29516614281845,26.096379L28.69276814281845,12L1.204819142818451,26.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,26.065809L28.43877614281845,42.737896L28.68361514281845,42.882288L59.39288714281845,26.065309L28.684561142818453,11.44229615L0.16870074281845082,26.065809ZM28.70192014281845,41.732138L2.240937742818451,26.12695L28.70097614281845,12.55770427L57.19744514281845,26.127449L28.70192014281845,41.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,26.80120277404785L0.5,45.83131777404785L28.692764,62.042150774047855L28.692764,43.01204077404785L0.5,26.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,62.906411774047854L29.192764,42.722777774047856L28.941999,42.578587774047854L-5.999999996841865e-8,25.93693918404785L0,46.12058077404785L29.192764,62.906411774047854ZM28.192764,43.30130377404785L28.192764,61.17788877404785L1,45.542054774047855L1,27.66546636404785L28.192764,43.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,26.80120277404785L59,45.12649377404785L88.5,62.00042177404785L88.5,42.26604677404785L59,26.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,62.86243677404785L89,41.96362277404785L88.732151,41.82320777404785L58.50000003,25.97454732404785L58.50000003,45.41651177404785L89,62.86243677404785ZM88,42.568469774047855L88,61.13840677404785L59.5,44.836475774047855L59.5,27.627858224047852L88,42.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35778)"><path d="M16.87011742591858,20.681764625C16.9285550115,21.747077625,17.8163673875,22.577077625,18.8835551875,22.563638625L29.2344931875,22.563638625L29.2344931875,25.430513625L25.2735547875,25.430513625C24.8566794875,25.430513625,24.5185546875,25.768640625,24.5185546875,26.185512625C24.5185546875,26.602386625,24.8566794875,26.940511625,25.2735547875,26.940511625L34.7276171875,26.940511625C35.144493187500004,26.940511625,35.4826161875,26.602386625,35.4826161875,26.185512625C35.4826161875,25.768640625,35.1444911875,25.430513625,34.7276171875,25.430513625L30.7663681875,25.430513625L30.7663681875,22.563638625L41.117616187500005,22.563638625C42.1844921875,22.577075625,43.072304187499995,21.747075625,43.1310541875,20.681764625L43.1310541875,18.953014625L16.87011742591858,18.953014625L16.87011742591858,20.681764625ZM41.1173041875,5.05676746367L18.883554687500002,5.05676746367C17.7919921875,5.044579985,16.8941795825,5.913329955,16.8701171875,7.004579925L16.8701171875,17.268015625L43.1307411875,17.268015625L43.1307411875,7.004579925C43.106680187500004,5.913017635,42.2088661875,5.044579985,41.1173041875,5.05676746367Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/ai.svg b/src/assets/system/ai.svg
new file mode 100644
index 0000000..5f45ee2
--- /dev/null
+++ b/src/assets/system/ai.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="380.89990234375" height="372.80078125" viewBox="0 0 380.89990234375 372.80078125"><defs><pattern x="13.89990234375" y="167.900390625" width="367" height="166" patternUnits="userSpaceOnUse" id="master_svg0_143_34844"><image x="0" y="-0.17693836978131117" width="367" height="166.35387673956262" xlink:href="data:image/png;base64,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"/></pattern><pattern x="79.32733154296875" y="74.900390625" width="206.67991638183594" height="206.78233337402344" patternUnits="userSpaceOnUse" id="master_svg1_143_34837"><image x="-0.05120849609375" y="0" width="206.78233337402344" height="206.78233337402344" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAMgCAYAAADbcAZoAAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAACAASURBVHic7N17nN1ldS/+z2c9371nkpAwyVxygWpQERWrVdSD1nNUilYuggZjJdTaXyNQ5CZarWJfnrHnVw6tRe4WIrRVC1gwKAjGFk6hN6UKre0RBbVCAXOZS+7JzOz9fdY6fzzfPbMnJJm990wyk8x6v155JZnZ+7uf/d179jzr+zxrLcA555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzzjnnnHPOOeecc84555xzE+B0D8A559zM0H3xc1URyWr/t5j+Jglw/K8LM9v7QWT/v1ZIpuMBUNXnfQ0AiDDu+GYGkjAzWN3xzQxUg4ik/+/xvfq/SULNlg1c071h4jPhnHPuQPIAxDnnHLo+0T9fdo9sh9QFA1r3K6IWANRN6PdqggCkFiygLgDBnkGIyWjQQRKqmgIQ4fMDi7oApDbcWrCCuuCldmzStmx8prMbdzE2d4acc85NFQ9AnHPuENB9/n8eSwlXAjhZVUHwQUA/2X/zi386VY+x8Pf/88jS7iOWI68YQ8lopgCw8calj0/VY0yHro/0Lw0ivwDAWmCiJl8ZuGbRb0332JxzbjbyAMQ552a4rgt+fhyVj1DYgWLlgCSi6VYRnjjwZy96crrHeCjo/tjAB6n4S9StoIhkZ276/MJ7p3tszjk3m3gA4pybFTpW/+BrGXEaRKAKTRt2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"/></pattern></defs><rect x="13.89990234375" y="167.900390625" width="367" height="166" rx="0" fill="url(#master_svg0_143_34844)" fill-opacity="1"/><rect x="79.32733154296875" y="74.900390625" width="206.67991638183594" height="206.78233337402344" rx="0" fill="url(#master_svg1_143_34837)" fill-opacity="1"/><g><path d="M139.18790233375,186.900390625L165.68390234375,122.868392625L181.33190134375,122.868392625L207.82790334375,186.900390625L191.89190334375002,186.900390625L185.65190134375,172.116393625L161.36390334375,172.116393625L155.12390334375,186.900390625L139.18790233375,186.900390625ZM173.55590434375,138.324390625L164.43590134375,160.692390625L182.67590334375,160.692390625L173.55590434375,138.324390625ZM214.73990634375,186.900390625L214.73990634375,122.868392625L228.37190234374998,122.868392625L228.37190234374998,186.900390625L214.73990634375,186.900390625Z" fill="#FFFFFF" fill-opacity="1"/><path d="M185.65190134375,172.116393625L191.89190334375002,186.900390625L207.82790334375,186.900390625L207.41410834375,185.900390625L181.33190134375,122.868392625L165.68390434375,122.868392625L139.60169547375,185.900390625L139.18790233375,186.900390625L155.12390534375,186.900390625L161.36390334375,172.116393625L185.65190134375,172.116393625ZM154.46055834375,185.900390625L160.70055434375,171.116393625L186.31525434374998,171.116393625L192.55524834375,185.900390625L206.33187834375002,185.900390625L180.66346734375,123.868392625L166.35234034375,123.868392625L140.68392804375,185.900390625L154.46055834375,185.900390625ZM214.73991434375,185.900390625L214.73991434375,186.900390625L228.37191034375002,186.900390625L228.37191034375002,122.868392625L214.73991434375,122.868392625L214.73991434375,185.900390625ZM215.73991434375,185.900390625L227.37191034375002,185.900390625L227.37191034375002,123.868392625L215.73991434375,123.868392625L215.73991434375,185.900390625ZM174.48189534375,137.946845625L172.62991334375,137.946845625L162.94825334375,161.692394625L184.16355534375,161.692394625L174.48189534375,137.946845625ZM173.01594134375,139.648723625L173.55590434375,138.324394625L174.09586734375,139.648723625L182.26818134375,159.692394625L182.67590334375,160.692394625L164.43590334375,160.692394625L164.84362834375,159.692394625L173.01594134375,139.648723625Z" fill-rule="evenodd" fill="#E2E6F7" fill-opacity="1"/></g><path d="M181.03737234375,51.027744395Q182.03354234375,50.984443635,183.03024234375,50.955862269L183.05888234375,51.955462325Q182.06956234375,51.983808525,181.08081234375,52.026801425L181.03737234375,51.027744395ZM172.04366234375,51.720317005Q174.02491234375,51.500955875,176.01177234375,51.340186175L176.09243234375,52.336925725Q174.12028234375,52.496511825,172.15371234375,52.714242925L172.04366234375,51.720317005ZM167.09549234374998,52.360937525Q168.08639234375,52.213984525,169.07935234375,52.081752025L169.21139234375,53.072996125Q168.22574234375,53.204284225,167.24216234375,53.350121525L167.09549234374998,52.360937525ZM158.23325234375,53.979113625Q160.17093234375,53.558054225,162.12014234375,53.194085825L162.30369234375001,54.177096325Q160.36891234375,54.538365325,158.44559234374998,54.956299325L158.23325234375,53.979113625ZM153.36297234375002,55.132375225Q154.33571234375,54.882904325,155.31206234375,54.647931825L155.54604234375,55.620178225000004Q154.57692234375,55.853413625,153.61136234375,56.101017025L153.36297234375002,55.132375225ZM144.72354134375001,57.657829325Q146.61345634375,57.036274425,148.52086634375001,56.470681625L148.80514534374998,57.429419525Q146.91186534374998,57.990807025,145.03596534374998,58.607769925L144.72354134375001,57.657829325ZM139.99185134375,59.311944025Q140.93434934375,58.962696125,141.88194234374998,58.627520525L142.21542334375,59.570271525Q141.27481834374998,59.902988425000004,140.33931734375,60.249637625L139.99185134375,59.311944025ZM131.66394834375,62.717643625Q133.48324634375,61.901856625,135.32585134375,61.140151625L135.70787834375,62.064305625Q133.87901334375,62.820330625,132.07310534375,63.630112625L131.66394834375,62.717643625ZM127.12737234375,64.853932625Q128.02841234375,64.409004625,128.93596634375,63.977537625L129.36532634374998,64.880674625Q128.46451534375,65.308926625,127.57015234375,65.750575625L127.12737234375,64.853932625ZM119.19712834375,69.10426662500001Q120.92459834375,68.10291062499999,122.68093134375,67.153081625L123.15663134375,68.03269362500001Q121.41317734375,68.975562625,119.69862334375,69.969421625L119.19712834375,69.10426662500001ZM114.90772234375001,71.698261625Q115.75703434375001,71.162862625,116.61421234375,70.640155625L117.13485734375,71.493924625Q116.28401934375,72.01277962500001,115.44097934375,72.54420462499999L114.90772234375001,71.698261625ZM107.45834334375,76.748943625Q109.07444034375,75.57273062499999,110.72465134375,74.444879625L111.28891034374999,75.270475625Q109.65093634375,76.389959625,108.04680234375,77.557472625L107.45834334375,76.748943625ZM103.46362734375,79.771280625Q104.25187634375,79.151578625,105.04924034375,78.543651625L105.65554034375,79.338893625Q104.86407134375,79.942317625,104.08168034375001,80.557422625L103.46362734375,79.771280625ZM96.57452734374999,85.569305625Q98.06130934375,84.23079662500001,99.58710134374999,82.93692762500001L100.23386734375,83.699607625Q98.71938334375,84.983920625,97.24359134375,86.312503625L96.57452734374999,85.569305625ZM92.91767834375,88.986293625Q93.63644434375,88.289275625,94.36546734375,87.602996625L95.05091834375,88.331107625Q94.32731634375,89.01231362499999,93.61383034375001,89.704189625L92.91767834375,88.986293625ZM86.66326934375,95.470214625Q88.00439434375,93.983653625,89.38901134375,92.53751762499999L90.11130934375001,93.229106625Q88.73696134375001,94.66448162500001,87.40576934375,96.14006062499999L86.66326934375,95.470214625ZM83.38322434375,99.244186625Q84.02494034375,98.477615625,84.67793634374999,97.720634625L85.43513534375,98.373809625Q84.78699534375,99.125167625,84.15001334375,99.88608562499999L83.38322434375,99.244186625ZM77.83154634375,106.34478762500001Q79.01226634375,104.72605862500001,80.24050334374999,103.14307762499999L81.03057434375,103.75609162500001Q79.81140534375,105.327400625,78.63946334375,106.934093625L77.83154634375,106.34478762500001ZM74.96307034375,110.434200625Q75.52103234375,109.606593625,76.09117134375,108.787322625L76.91197734375,109.358531625Q76.34598734375,110.171840625,75.79222834375,110.99320962499999L74.96307034375,110.434200625ZM70.17459834375,118.075591625Q71.18179334375,116.342231625,72.24001134375,114.639537625L73.08934234375,115.167388625Q72.03900134375,116.857421625,71.03923034375,118.578002625L70.17459834375,118.075591625ZM67.74809834375,122.435066625Q68.21651034375,121.555656625,68.69785134375,120.683250625L69.57342334375,121.166335625Q69.09561934375,122.032340625,68.63070634375,122.905181625L67.74809834375,122.435066625ZM63.77491234375,130.535812625Q64.59721934375,128.707084625,65.47347634375001,126.903587625L66.37293334375,127.340598625Q65.50319334375,129.130691625,64.68694834375,130.94592262499998L63.77491234375,130.535812625ZM61.81617734375,135.11592862499998Q62.19018134375,134.194740625,62.57771334375,133.279167625L63.49861634375,133.668960625Q63.11394434375,134.57776662499998,62.74272734375,135.492103625L61.81617734375,135.11592862499998ZM58.70139644375,143.590309625Q59.32948014375,141.68723262499998,60.01377584375,139.803634625L60.95367434375,140.145095625Q60.27444074375,142.01474762499998,59.65101524375,143.90371662500002L58.70139644375,143.590309625ZM57.23094944375,148.337608625Q57.50677584375,147.385436625,57.79655554375,146.437423625L58.75287584375,146.729743625Q58.46523574375,147.670760625,58.19145874375,148.615852625L57.23094944375,148.337608625ZM55.00851894375,157.09652062499998Q55.43540334375,155.141840625,55.92002534375,153.200670625L56.89024594375,153.44289062500002Q56.40922264375,155.369640625,55.98549174375,157.309880625L55.00851894375,157.09652062499998ZM54.03744124375,161.972030625Q54.21408894375,160.991200625,54.40519834375,160.013070625L55.38664004375,160.204830625Q55.19694904375,161.17569062500002,55.02160814375,162.14928062500002L54.03744124375,161.972030625ZM52.73529070375,170.905160625Q52.95680414375,168.92325062499998,53.23676284375,166.948740625L54.22686024375,167.08912062500002Q53.94897554375,169.049010625,53.72910284375,171.016230625L52.73529070375,170.905160625ZM52.27231326375,175.879800625Q52.34762379375,174.86800062499998,52.43813353375,173.85744062499998L53.43414644375,173.946640625Q53.34430824375,174.949710625,53.26955454375,175.954020625L52.27231326375,175.879800625ZM51.90390639705,184.860640625Q51.91918294475,182.877210625,51.99272362175,180.895080625L52.99203594375,180.932160625Q52.91903994375,182.899610625,52.90387664375,184.868350625L51.90390639705,184.860640625ZM51.95618113875,189.798100625Q51.92755823775,188.807130625,51.91349196075,187.815860625L52.91340004375,187.801680625Q52.92734464375,188.785600625,52.95577414375,189.769210625L51.95618113875,189.798100625ZM52.51921534375,198.816700625Q52.32639241375,196.810580625,52.19353938375,194.799590625L53.19136834375,194.733670625Q53.32323644375,196.729800625,53.51463374375,198.721020625L52.51921534375,198.816700625ZM53.08498834375,203.748890625Q52.95320044375,202.760830625,52.83601707375,201.770950625L53.82908034375,201.653400625Q53.94539304375,202.635990625,54.07620764375,203.616670625L53.08498834375,203.748890625ZM54.57651444375,212.649610625Q54.18028684375,210.689540625,53.84228794375,208.718610625L54.82789354375,208.549590625Q55.16338734375,210.505920625,55.55669664375,212.451460625L54.57651444375,212.649610625ZM55.65406724375,217.515750625Q55.41985654375,216.543460625,55.20007654375,215.567810625L56.17564344375,215.348070625Q56.39379784375,216.316590625,56.62625454375,217.281550625L55.65406724375,217.515750625ZM58.05708834375,226.205840625Q57.46272754375,224.305880625,56.92464824375,222.389210625L57.88740964375,222.118910625Q58.42152504375,224.021390625,59.011475043749996,225.907290625L58.05708834375,226.205840625ZM59.63648034375,230.945050625Q59.30222274375,230.000690625,58.98201604375,229.051450625L59.92957304375,228.731840625Q60.24734024375,229.673920625,60.57916064375,230.611370625L59.63648034375,230.945050625ZM62.92490434375,239.334460625Q62.13796734375,237.508650625,61.40513894375,235.660460625L62.33471534375,235.291850625Q63.06212434375,237.126330625,63.84324234375,238.938640625L62.92490434375,239.334460625ZM64.98919934375,243.889880625Q64.55863934375,242.984710625,64.14156734375,242.073260625L65.05088434375,241.657150625Q65.46478034375,242.561610625,65.89225234375,243.460340625L64.98919934375,243.889880625ZM69.12807034375,251.891270625Q68.15404134375,250.152950625,67.23174234375,248.386640625L68.11816634375,247.923780625Q69.03356134375,249.676860625,70.00045034375,251.402430625L69.12807034375,251.891270625ZM71.65441534375,256.21025062499996Q71.13243834375,255.354690625,70.62322434375,254.491450625L71.48452334375,253.983350625Q71.99026334375,254.840650625,72.50808734374999,255.689480625L71.65441534375,256.21025062499996ZM76.59985134375,263.739320625Q75.44887934375001,262.108350625,74.34663434375,260.44408062499997L75.18037234375001,259.89191062500004Q76.27441234375,261.54384062500003,77.41688134374999,263.162720625L76.59985134375,263.739320625ZM79.56030434375,267.77353062500003Q78.95281234375,266.977080625,78.35720634375,266.171690625L79.16120534375,265.577090625Q79.75263434375,266.37678062500004,80.35541334375,267.167070625L79.56030434375,267.77353062500003ZM85.25969334375,274.750090625Q83.94377134375,273.244720625,82.67300834375,271.701050625L83.44507234375,271.065490625Q84.70643634375,272.597760625,86.01258834375,274.091920625L85.25969334375,274.750090625ZM88.62186434374999,278.455380625Q87.93557734375,277.726670625,87.26017334375,276.987840625L87.99826834375,276.313120625Q88.66878134375,277.04663062500003,89.34984234375,277.769770625L88.62186434374999,278.455380625ZM95.01414134375,284.804410625Q93.54703134375,283.441420625,92.12099034375001,282.03549062499997L92.82307434375,281.323390625Q94.23854834375,282.718950625,95.69476734375,284.071780625L95.01414134375,284.804410625ZM98.74149334375,288.140760625Q97.98397034375,287.48758062499996,97.23621034375,286.82324062500004L97.90038334375001,286.075650625Q98.64258534375,286.735050625,99.39452734375,287.383420625L98.74149334375,288.140760625ZM105.75791534375,293.793760625Q104.15506734375,292.588320625,102.58873034375,291.335800625L103.21324134375,290.55481062499996Q104.76791734375,291.797970625,106.35897434374999,292.994540625L105.75791534375,293.793760625ZM109.80996334375,296.725200625Q108.98950534375,296.154490625,108.17758934375,295.571700625L108.76071134375,294.759310625Q109.56671134375,295.337840625,110.38101234375,295.904280625L109.80996334375,296.725200625ZM117.37522134375,301.621250625Q115.65377434375,300.58702062500004,113.96385534375,299.502030625L114.50412734375,298.660540625Q116.18145034375,299.737440625,117.89021334375,300.764070625L117.37522134375,301.621250625ZM121.70740534375,304.116030625Q120.83309934375,303.63388062499996,119.96601834375,303.138840625L120.46184534375,302.27042062500004Q121.32270834375,302.761920625,122.19030034375,303.240360625L121.70740534375,304.116030625ZM129.74089034374998,308.202670625Q127.91979234375,307.351560625,126.12483234375,306.446610625L126.57503534375,305.553660625Q128.35720834375002,306.45219062499996,130.16427634375,307.296720625L129.74089034374998,308.202670625ZM134.30453534375,310.233520625Q133.38627634375,309.845090625,132.47385434375002,309.443110625L132.87699934375001,308.527980625Q133.78177634374998,308.926570625,134.69414534375,309.312530625L134.30453534375,310.233520625ZM142.72155034374998,313.467130625Q140.82155634375,312.809140625,138.94199334375,312.094850625L139.29724834375,311.160030625Q141.16293334375,311.869050625,143.04880534375002,312.522190625L142.72155034374998,313.467130625ZM147.46373034375,315.011930625Q146.51221434375,314.721280625,145.56508634375,314.416660625L145.87127734375,313.464690625Q146.81035634375002,313.766720625,147.75585934375,314.055540625L147.46373034375,315.011930625ZM156.17633234375,317.357850625Q154.22004234374998,316.900630625,152.27823234375,316.385410625L152.53469234375,315.418850625Q154.46216234374998,315.930270625,156.40391234375,316.384090625L156.17633234375,317.357850625ZM161.03998234375,318.400450625Q160.06669234375,318.210480625,159.09630234374998,318.006260625L159.30227234375002,317.027710625Q160.26522234375,317.230410625,161.23153234375002,317.418980625L161.03998234375,318.400450625ZM169.95750234374998,319.833040625Q167.96923234374998,319.581510625,165.98929234374998,319.271090625L166.14419234375,318.283140625Q168.10985234375,318.591340625,170.08301234375,318.840940625L169.95750234374998,319.833040625ZM174.88553234375001,320.364710625Q173.90076234375,320.276730625,172.91739234375,320.174320625L173.02094234375,319.179690625Q173.99721234375,319.281340625,174.97455234375002,319.368680625L174.88553234375001,320.364710625ZM183.91084234375,320.867310625Q181.91636234375,320.823120625,179.92407234375,320.720030625L179.97575234375,319.721370625Q181.95305234375,319.823700625,183.93298234375,319.867520625L183.91084234375,320.867310625ZM188.84326234375,320.886410625Q187.87163234375,320.900390625,186.89990234375,320.900390625L186.87219234375,320.900390625L186.87219234375,319.900390625L186.89990234375,319.900390625Q187.86360234375,319.900390625,188.82887234375,319.886500625L188.84326234375,320.886410625ZM197.84508234375,320.455960625Q195.83415234375,320.619540625,193.81924234375,320.722960625L193.76797234375,319.724270625Q195.76820234375,319.621610625,197.76401234375,319.459260625L197.84508234375,320.455960625ZM202.79832234375,319.960970625Q201.81343234375,320.077790625,200.82692234375,320.180080625L200.72372234375,319.185450625Q201.70291234375,319.083860625,202.68057234375,318.967930625L202.79832234375,319.960970625ZM211.73442234375,318.596470625Q209.74951234375,318.967930625,207.75439234375,319.279880625L207.59993234375,318.291870625Q209.58032234375,317.982270625,211.55046234375,317.613520625L211.73442234375,318.596470625ZM216.59475234375,317.594020625Q215.62327234375,317.813080625,214.64868234375,318.017790625L214.44311234375,317.039150625Q215.41093234375,316.835880625,216.37478234375,316.618530625L216.59475234375,317.594020625ZM225.33255234375,315.314180625Q223.40765234375,315.885830625,221.46661234375,316.399990625L221.21054234375,315.433350625Q223.13707234375,314.923000625,225.04788234375,314.355590625L225.33255234375,315.314180625ZM230.07766234375,313.809260625Q229.13174234375,314.128570625,228.18120234375,314.433870625L227.87542234375,313.481750625Q228.81894234375,313.178740625,229.75781234375,312.861790625L230.07766234375,313.809260625ZM238.52577234375,310.639190625Q236.67615234375,311.404690625,234.80462234375,312.115050625L234.44978234375,311.180080625Q236.30800234375,310.474820625,238.14335234375,309.715210625L238.52577234375,310.639190625ZM243.09843234375,308.646970625Q242.18945234375,309.063140625,241.27440234375,309.465820625L240.87161234375,308.550540625Q241.77916234375,308.151150625,242.68216234375,307.737730625L243.09843234375,308.646970625ZM251.16830234375,304.620960625Q249.40996234375,305.572810625,247.62420234375,306.47218062499996L247.17436234375,305.579090625Q248.94716234375,304.686170625,250.69227234375,303.741530625L251.16830234375,304.620960625ZM255.51530234375,302.162700625Q254.65378234375,302.67116062499997,253.78480234375,303.166790625L253.28937234375,302.298140625Q254.15130234375,301.80652062499996,255.00708234375,301.301500625L255.51530234375,302.162700625ZM263.12166234375,297.324110625Q261.47130234375004,298.453080625,259.78822234375,299.53267062500004L259.24832234375003,298.690950625Q260.91876234375,297.619480625,262.55702234374996,296.498750625L263.12166234375,297.324110625ZM267.19391234374996,294.426300625Q266.38952234375,295.021420625,265.57641234375,295.604570625L264.99363234375,294.791920625Q265.80020234375,294.213500625,266.59909234375,293.622390625L267.19391234374996,294.426300625ZM274.25570234375,288.827380625Q272.73015234375,290.122150625,271.16688234375,291.371120625L270.54269234375,290.58986062500003Q272.09428234375,289.350200625,273.60862234374997,288.064960625L274.25570234375,288.827380625ZM278.00819234375,285.521070625Q277.26976234375,286.196400625,276.52141234375,286.860700625L275.85756234375003,286.112840625Q276.60016234374996,285.453660625,277.33328234375,284.783140625L278.00819234375,285.521070625ZM284.44983234375,279.222470625Q283.06537234375,280.669660625,281.63859234375,282.07513062500004L280.93681234375003,281.36273062500004Q282.35322234374996,279.967440625,283.72722234375,278.531190625L284.44983234375,279.222470625ZM287.84149234375,275.54298062500004Q287.17701234375,276.29121062499996,286.50152234375,277.029510625L285.76372234375003,276.35449062500004Q286.43422234375,275.62163062499997,287.09379234375,274.878950625L287.84149234375,275.54298062500004ZM293.59396234375004,268.613020625Q292.36571234375003,270.19737062499996,291.09096234375,271.744570625L290.31918234374996,271.108670625Q291.58462234374997,269.572810625,292.80362234375,268.00034062500004L293.59396234375004,268.613020625ZM296.58766234375,264.59979062499997Q296.00433234375,265.412800625,295.40902234375,266.217070625L294.60524234375,265.622150625Q295.19630234375,264.823580625,295.77514234374996,264.016830625L296.58766234375,264.59979062499997ZM301.58969234375,257.113110625Q300.53100234375,258.818150625,299.42212234375,260.490950625L298.58861234375,259.938450625Q299.68930234375,258.27797062499997,300.74013234375,256.585600625L301.58969234375,257.113110625ZM304.15233234375,252.809780625Q303.65651234375,253.678660625,303.14787234375,254.540080625L302.28679234375,254.031630625Q302.79158234375,253.176760625,303.28378234375,252.314180625L304.15233234375,252.809780625ZM308.35110234375,244.846190625Q307.47333234375003,246.654740625,306.54210234375,248.436340625L305.65585234375,247.973110625Q306.58026234375,246.204590625,307.45146234375,244.409560625L308.35110234375,244.846190625ZM310.45398234375,240.300670625Q310.05111234375,241.215670625,309.63473234375,242.124590625L308.72558234375,241.708100625Q309.13904234375,240.805590625,309.53875234375,239.897720625L310.45398234375,240.300670625ZM313.80539234375,231.943860625Q313.11786234375,233.838820625,312.37405234375,235.712400625L311.44461234375,235.343430625Q312.18292234375,233.483570625,312.86535234375,231.602780625L313.80539234375,231.943860625ZM315.42477234375,227.208450625Q315.11929234375,228.158980625,314.79974234375,229.104870625L313.85232234375,228.784840625Q314.16986234375,227.844820625,314.47275234375,226.902450625L315.42477234375,227.208450625ZM317.89349234375,218.545130625Q317.40573234375,220.502360625,316.85971234375,222.444150625L315.89706234375,222.173450625Q316.43878234375,220.247040625,316.92318234375,218.303330625L317.89349234375,218.545130625ZM319.01153234375,213.676570625Q318.80661234375,214.651200625,318.58734234375,215.622700625L317.61188234375,215.402540625Q317.82943234375,214.438660625,318.03293234375,213.470810625L319.01153234375,213.676570625ZM320.57095234375,204.796100625Q320.28909234375,206.790110625,319.94787234375,208.774830625L318.96231234375,208.605380625Q319.30108234375,206.635070625,319.58081234375,204.656130625L320.57095234375,204.796100625ZM321.17672234375,199.855150625Q321.07419234375,200.841690625,320.95718234375,201.826630625L319.96417234375,201.708660625Q320.08035234375,200.730570625,320.18210234375,199.751770625L321.17672234375,199.855150625ZM321.80914234375,190.849490625Q321.73559234375,192.854460625,321.60251234375,194.856350625L320.60467234375,194.789990625Q320.73684234375,192.802700625,320.80981234375,190.812850625L321.80914234375,190.849490625ZM321.86984234375,183.051150625Q321.89990234375,184.475620625,321.89990234375,185.900390625Q321.89990234375,186.886050625,321.88550234375,187.871600625L320.88562234375,187.856980625Q320.89990234375,186.879780625,320.89990234375,185.900390625Q320.89990234375,184.486590625,320.87005234375,183.072250625L321.86984234375,183.051150625ZM321.67221234375,178.06314062500002Q321.73044234375,179.064220625,321.77377234375,180.066070625L320.77472234375,180.109340625Q320.73169234375,179.115890625,320.67389234375,178.12115062499998L321.67221234375,178.06314062500002ZM320.85013234375,169.09751062499998Q321.09698234375,171.065310625,321.28592234375,173.039520625L320.29043234375,173.134800625Q320.10284234375,171.17481062500002,319.85791234375,169.221950625L320.85013234375,169.09751062499998ZM320.13376234375,164.13487062500002Q320.29605234375,165.12831062499998,320.44351234375,166.124050625L319.45431234375,166.27058062499998Q319.30786234375,165.281900625,319.14685234375,164.296070625L320.13376234375,164.13487062500002ZM318.38940234375,155.314210625Q318.84057234375,157.253910625,319.23437234375,159.206070625L318.25412234375,159.403780625Q317.86340234375,157.466600625,317.41537234375,155.540810625L318.38940234375,155.314210625ZM317.15988234375,150.441406625Q317.42471234375,151.414280625,317.67499234375,152.390990625L316.70624234375,152.639160625Q316.45791234375,151.66979062500002,316.19497234375,150.704131625L317.15988234375,150.441406625ZM314.51282234375,141.855598625Q315.16418234375,143.742866625,315.75949234375,145.64857462499998L314.80493234375,145.946716625Q314.21417234375,144.055267625,313.56753234375,142.181877625L314.51282234375,141.855598625ZM312.78381234375,137.133163625Q313.14807234375,138.073417625,313.49823234375,139.01901262500002L312.56042234375,139.366226625Q312.21329234375,138.428642625,311.85135234375,137.494430625L312.78381234375,137.133163625ZM309.26199234375,128.869521625Q310.10660234375,130.681671625,310.89718234375,132.51803562499998L309.97870234375,132.913474625Q309.19403234375,131.090965625,308.35559234375,129.29195362500002L309.26199234375,128.869521625ZM307.05388234375,124.353484625Q307.51312234375,125.250045625,307.95895234375,126.153358625L307.06222234375,126.595939625Q306.61969234375,125.699310625,306.16385234375,124.809387625L307.05388234375,124.353484625ZM302.69351234375,116.496940625Q303.72204234375,118.212959625,304.69928234375004,119.958701625L303.82669234375,120.447166625Q302.85669234375,118.714378625,301.83577234375,117.011031625L302.69351234375,116.496940625ZM300.03236234375004,112.238689625Q300.58107234375,113.081424625,301.11717234375,113.932243625L300.27113234374997,114.465373625Q299.73877234375,113.620567625,299.19432234375,112.784294625L300.03236234375004,112.238689625ZM294.87814234375,104.871375625Q296.07930234375,106.472026625,297.23248234375,108.107574625L296.41520234375,108.683818625Q295.27049234375,107.060287625,294.07829234375004,105.47159962500001L294.87814234375,104.871375625ZM291.79469234375,100.917560625Q292.42644234375,101.697326625,293.04652234375,102.486396625L292.26025234375004,103.104270625Q291.64509234375,102.321449625,291.01770234375,101.547077625L291.79469234375,100.917560625ZM285.89998234375,94.118125625Q287.26066234375,95.585819625,288.57725234375,97.09320062500001L287.82406234375003,97.75103362499999Q286.51741234375004,96.254978625,285.16664234375,94.798004625L285.89998234375,94.118125625ZM282.42921234375,90.510925625Q283.13675234375,91.219489625,283.83368234375,91.938472625L283.11564234375,92.63448762499999Q282.42401234375,91.920959625,281.72159234375,91.21751362500001L282.42921234375,90.510925625ZM275.85577234375,84.353099625Q277.36130234375,85.671939625,278.82705234375,87.03483162500001L278.14612234375,87.76716962500001Q276.69136234375003,86.414512625,275.19684234375,85.10530862499999L275.85577234375,84.353099625ZM272.03647234375,81.130332625Q272.81181234375003,81.76038162500001,273.57774234375,82.401836625L272.93567234375,83.168491625Q272.17499234375,82.53142162500001,271.40584234375,81.906410625L272.03647234375,81.130332625ZM264.85399234375,75.681697625Q266.48802234375,76.837394625,268.08706234375,78.041021625L267.48568234375,78.839986625Q265.89856234375,77.645337625,264.27655234375004,76.498132625L264.85399234375,75.681697625ZM260.72816234375,72.876554625Q261.56288234375,73.42179862500001,262.38945234375,73.979310625L261.83027234375004,74.808360625Q261.00979234375,74.254962625,260.18129234375,73.713767625L260.72816234375,72.876554625ZM253.01359234375,68.197461625Q254.75825234375,69.177434625,256.47310234375004,70.208686625L255.95775234375,71.065662625Q254.25560234375,70.042055625,252.52386234375,69.069333625L253.01359234375,68.197461625ZM248.62404234375,65.837362625Q249.51043234375,66.293059625,250.39001234375,66.761793625L249.91971234375,67.644298625Q249.04683234375,67.179111625,248.16684234375,66.72672862499999L248.62404234375,65.837362625ZM240.46307234375,61.981116625Q242.29878234375,62.774583625,244.11017234375,63.622079625L243.68638234375,64.527844625Q241.88835234375,63.686595625,240.06631234375,62.899036625L240.46307234375,61.981116625ZM235.85312234375,60.088695525Q236.78447234375,60.451081325000004,237.71034234375,60.827215225L237.33398234375,61.753682624999996Q236.41508234375,61.380392625,235.49049234375,61.020627625L235.85312234375,60.088695525ZM227.33920234375,57.099525425Q229.24470234375,57.697792525,231.13168234375,58.352166625L230.80404234375,59.296970325000004Q228.93109234375,58.647457125,227.03966234375,58.053608925L227.33920234375,57.099525425ZM222.55142234375,55.692982625Q223.52249234375,55.958869025,224.48950234375,56.239209224999996L224.21106234375,57.199662724999996Q223.25126234375,56.921408225,222.28734234375,56.657480225L222.55142234375,55.692982625ZM213.78616234375,53.604778725Q215.73858234375,54.001567125,217.67845234375,54.455798125L217.45047234375,55.429462425Q215.52498234375,54.978601425,213.58700234375,54.584746125L213.78616234375,53.604778725ZM208.86210234375,52.698808025Q209.86056234375,52.863432325,210.85643234375,53.043005725L210.67897234375,54.027135325Q209.69044234375,53.848882725,208.69943234375,53.685486525L208.86210234375,52.698808025ZM199.95469234375,51.533086775Q201.92964234375,51.724967955,203.89810234375,51.974809725L203.77218234375,52.966851425Q201.81830234375,52.718860725,199.85798234375,52.528399425L199.95469234375,51.533086775ZM194.93542234375,51.139749575Q195.94269234375,51.199810865,196.94894234375,51.274922165L196.87451234375,52.272147925Q195.87575234375,52.197595625,194.87590234375,52.137977025L194.93542234375,51.139749575ZM189.94488234375,50.934735443L189.92233234375,51.934480825Q188.41130234375,51.900390625,186.90245234375,51.900387405000004L186.21744234375,51.902124525L186.00497234375,51.903372425L185.99910234375,50.9033960113Q186.44949234375,50.90039062500003,186.89990234375,50.900390625Q188.42259234375,50.900390625,189.94488234375,50.934735443Z" fill-rule="evenodd" fill="#67E4F4" fill-opacity="1"/><ellipse cx="305.89990234375" cy="124.900390625" rx="5" ry="5" fill="#67E4F4" fill-opacity="1"/><ellipse cx="67.89990234375" cy="124.900390625" rx="5" ry="5" fill="#67E4F4" fill-opacity="1"/><ellipse cx="187.89990234375" cy="51.900390625" rx="5" ry="5" fill="#67E4F4" fill-opacity="1"/><ellipse cx="59.89990234375" cy="231.900390625" rx="5" ry="5" fill="#67E4F4" fill-opacity="1"/><ellipse cx="311.89990234375" cy="238.900390625" rx="5" ry="5" fill="#67E4F4" fill-opacity="1"/><ellipse cx="191.89990234375" cy="320.900390625" rx="5" ry="5" fill="#67E4F4" fill-opacity="1"/><path d="M362.89990234375,87.300391925Q363.04237334375,87.300391925,363.18415034375,87.286427525Q363.32593534375,87.272463325,363.46566034375,87.244669225Q363.60539234375,87.216875125,363.74172234375,87.175519025Q363.87805934375,87.134162425,364.00967834375,87.079642325Q364.14130434375,87.025122425,364.26695234375,86.957963425Q364.39260134375,86.890804525,364.51105534375,86.811653425Q364.62951634374997,86.732502425,364.73964734375,86.642121825Q364.84977334375003,86.551741125,364.95050834375,86.451001125Q365.05125034375,86.350261125,365.14163234375,86.240131825Q365.23201034375,86.130002625,365.31115734375,86.011544825Q365.39031234375,85.893087125,365.45747034375,85.767441725Q365.52462734375,85.641796225,365.57914734375,85.510172925Q365.63366734375,85.378549815,365.67502634375,85.242216585Q365.71638534375,85.105883245,365.74417834375,84.966152725Q365.77197634375,84.826422335,365.78594234375,84.684640435Q365.79990434375,84.542858545,365.79990434375,84.400390625Q365.79990434375,84.257922705,365.78594234375,84.116140815Q365.77197634375,83.974358915,365.74417834375,83.834628525Q365.71638534375,83.694898005,365.67502634375,83.558564725Q365.63366734375,83.422231435,365.57914734375,83.290608325Q365.52462734375,83.158985025,365.45747034375,83.033339625Q365.39031234375,82.907694125,365.31116134375,82.789236525Q365.23201334375,82.670778725,365.14163634375,82.560649425Q365.05125434375,82.450520125,364.95051234375,82.349780125Q364.84977734375,82.249040125,364.73964734375,82.158659225Q364.62951634374997,82.068278525,364.51105534375,81.989127625Q364.39260134375,81.909976525,364.26695234375,81.842817825Q364.14131134375,81.775658825,364.00968134375,81.721138925Q363.87805934375,81.666618825,363.74172934375,81.625262225Q363.60539234375,81.583906125,363.46566034375,81.556112025Q363.32593534375,81.528317925,363.18415034375,81.514353525Q363.04237334375,81.500389325,362.89990234375,81.500389325Q362.75743534375,81.500389325,362.61565034375,81.514353725Q362.47386934375,81.528317925,362.33413734375,81.556112025Q362.19440834375,81.583906125,362.05807534375,81.625262225Q361.92173734375,81.666618825,361.79011134375,81.721138925Q361.65849334375,81.775658825,361.53284834375,81.842817825Q361.40720334375,81.909976725,361.28874234375,81.989127825Q361.17028834375003,82.068278825,361.06015734375,82.158659425Q360.95003134374997,82.249040125,360.84928934375,82.349780125Q360.74855034375,82.450520125,360.65816834375,82.560649425Q360.56778734375,82.670778625,360.48863234375,82.789236425Q360.40948534375,82.907694125,360.34232734375,83.033339525Q360.27516934375,83.158985025,360.22064634375,83.290608325Q360.16613034375,83.422231435,360.12477534375,83.558564665Q360.08341934375,83.694898005,360.05562234375,83.834628525Q360.02783234375,83.974358915,360.01386634375,84.116140815Q359.99990034375,84.257922705,359.99990034375,84.400390625Q359.99990034375,84.542858545,360.01386634375,84.684640435Q360.02783234375,84.826422335,360.05562234375,84.966152725Q360.08341934375,85.105883245,360.12477534375,85.242216525Q360.16613034375,85.378549815,360.22064634375,85.510172925Q360.27516934375,85.641796225,360.34232334375,85.767441625Q360.40948534375,85.893087125,360.48863234375,86.011544725Q360.56778734375,86.130002525,360.65816834375,86.240131825Q360.74855034375,86.350261125,360.84928934375,86.451001125Q360.95003134374997,86.551741125,361.06016134375,86.642122025Q361.17028834375003,86.732502725,361.28874634375,86.811653625Q361.40720334375,86.890804725,361.53285234375,86.957963425Q361.65849334375,87.025122425,361.79011534375,87.079642325Q361.92174534375,87.134162425,362.05807834375,87.175519025Q362.19441234375,87.216875125,362.33413734375,87.244669225Q362.47386934375,87.272463325,362.61565434375,87.286427725Q362.75743534375,87.300391925,362.89990234375,87.300391925ZM359.11136234375,87.747195725L360.74371734375,86.570725225L360.15903134375003,85.759468125L358.52667634375,86.935938825L359.11136234375,87.747195725ZM355.84665634375,90.100137225L357.47901134375,88.923666525L356.89432534375,88.112409325L355.26197034375,89.288879825L355.84665634375,90.100137225ZM352.58195134375,92.453078225L354.21430234375,91.276608025L353.62961534375,90.465350625L351.99726534375,91.641820925L352.58195134375,92.453078225ZM349.31724534375,94.80601862500001L350.94960034375,93.629548025L350.36491434375,92.818291625L348.73255934375,93.994762425L349.31724534375,94.80601862500001ZM346.05253634375,97.158961625L347.68489034375,95.982490625L347.10020434375,95.171234625L345.46784934375,96.347704625L346.05253634375,97.158961625ZM342.78783434375,99.51190162500001L344.42018534375,98.335430625L343.83549834375,97.524174625L342.20314834375,98.70064562499999L342.78783434375,99.51190162500001ZM339.52312834375,101.86484362499999L341.15547934375,100.688373625L340.57079334375,99.877116625L338.93843834375,101.05358662500001L339.52312834375,101.86484362499999ZM336.25842134375,104.21778462500001L337.89077534375,103.041314625L337.30608534375,102.230058625L335.67373134375,103.40652862499999L336.25842134375,104.21778462500001ZM332.99371734375,106.570724625L334.62607034375003,105.394254625L334.04138034375,104.582998625L332.40902734375,105.759467625L332.99371734375,106.570724625ZM329.72900934375,108.92366762500001L331.36136234375,107.747197625L330.77667234375,106.935941625L329.14431934375,108.112411625L329.72900934375,108.92366762500001ZM326.46430434375,111.27660962499999L328.09665834375,110.100137625L327.51196834375,109.288881625L325.87961434375,110.46535262500001L326.46430434375,111.27660962499999ZM323.19959834375,113.629548625L324.83194934375,112.453079625L324.24725934375,111.641822625L322.61490834375,112.818292625L323.19959834375,113.629548625ZM319.93489234375,115.98249262499999L321.56724734375,114.80601862500001L320.98255734375,113.99476262499999L319.35020234375,115.17123562500001L319.93489234375,115.98249262499999ZM316.67018704375,118.335430625L318.30253834375,117.158962625L317.71784734375,116.347705625L316.08549694375,117.524173625L316.67018704375,118.335430625ZM313.40548134375,120.688373625L315.03783224375,119.511905625L314.45314214375003,118.700649625L312.82079124375,119.877117625L313.40548134375,120.688373625ZM310.14077164375,123.04131662500001L311.77312664375,121.864845625L311.18843674375,121.053588625L309.55608204375,122.230060625L310.14077164375,123.04131662500001ZM307.69224721375,124.80601862500001L308.50842454375,124.21778462500001L307.92373484375,123.40652862499999L307.10755747375,123.99476262499999L307.69224721375,124.80601862500001Z" fill-rule="evenodd" fill="#67E4F4" fill-opacity="1"/><path d="M311.73714587375,240.373159405L312.69027471375,240.701284405L313.01578764375,239.755746845L312.06265881375,239.427621845L311.73714587375,240.373159405ZM314.59652094375,241.357534425L316.50277094375,242.013784425L316.82828374375,241.068246825L314.92203374375,240.411996845L314.59652094375,241.357534425ZM318.40902094375,242.670034425L320.31527044375,243.326284425L320.64078424375,242.380746825L318.73453374375,241.724496825L318.40902094375,242.670034425ZM322.22152034375,243.982534425L324.12777034375,244.638784425L324.45328434375,243.693246825L322.54703434375,243.036996825L322.22152034375,243.982534425ZM326.03402034375,245.295032525L327.94027534375,245.951284425L328.26578734375,245.005746825L326.35953434375,244.349494925L326.03402034375,245.295032525ZM329.84652134375,246.607534425L331.75277134375,247.263784425L332.07828334375,246.318246825L330.17203334375,245.661996825L329.84652134375,246.607534425ZM333.65902134375,247.920034425L335.56527134375,248.576284425L335.89078334375,247.630746825L333.98453334375,246.974496825L333.65902134375,247.920034425ZM337.47152134375,249.23253342499999L339.37777134375,249.88878342499999L339.70328334375,248.94324592499999L337.79703334375,248.28699592499999L337.47152134375,249.23253342499999ZM341.28401934375,250.545033625L343.19027134375,251.201284625L343.51578334375,250.255746625L341.60953134375,249.59949592499999L341.28401934375,250.545033625ZM345.09651934375,251.857533625L347.00276934375,252.513784625L347.32828534375,251.568246625L345.42203534375,250.911995625L345.09651934375,251.857533625ZM348.90901934375,253.170034625L350.81526934375,253.826284625L351.14078534375,252.880746625L349.23453534375,252.224496625L348.90901934375,253.170034625ZM352.72151934375,254.482534625L354.62776934375,255.138784625L354.95328534375,254.193246625L353.04703534375,253.536996625L352.72151934375,254.482534625ZM356.53401934375,255.795034625L358.44026934375,256.45128462499997L358.76578534375,255.505746625L356.85953534375,254.849496625L356.53401934375,255.795034625ZM360.34651934375,257.10753462499997L362.25276934375,257.76378462499997L362.57828534375,256.81824662500003L360.67203534375,256.16199662500003L360.34651934375,257.10753462499997ZM364.15901934375,258.42003462499997L366.06526934375,259.07628462499997L366.39078534375,258.13074662500003L364.48453534375,257.47449662500003L364.15901934375,258.42003462499997ZM372.89990234375,263.800392625Q373.04237334375,263.800392625,373.18415034375,263.786428625Q373.32593534375,263.772464625,373.46566034375,263.744666625Q373.60539234375,263.716874625,373.74172634375,263.675517625Q373.87805934375,263.634162625,374.00967434375,263.579639625Q374.14130434375,263.525121625,374.26694834375,263.457963625Q374.39259334375,263.390804625,374.51104734375,263.311653625Q374.62950934375,263.232501625,374.73963934375,263.142124625Q374.84976934375,263.051742625,374.95050834375,262.951000625Q375.05125034375,262.85026162500003,375.14163234375,262.740131625Q375.23201034375,262.630000625,375.31115734375,262.511543625Q375.39031234375,262.393085625,375.45747034375,262.267438625Q375.52462734375,262.141794625,375.57914334375,262.010169625Q375.63366734375,261.878547625,375.67502634375,261.742214625Q375.71638534375,261.605882625,375.74417534375,261.466150625Q375.77197234375,261.326421625,375.78594234375,261.184640625Q375.79990434375,261.042857625,375.79990434375,260.900390625Q375.79990434375,260.757923625,375.78593434375,260.616142625Q375.77197234375,260.474359625,375.74417534375,260.334627625Q375.71638534375,260.194896625,375.67502634375,260.058563625Q375.63367034375,259.922229625,375.57914734375,259.790605625Q375.52462734375,259.658985625,375.45747034375,259.533338625Q375.39031234375,259.407691625,375.31115734375,259.289234625Q375.23201034375,259.170778625,375.14162834374997,259.060649625Q375.05125034375,258.95051962499997,374.95050834375,258.849779625Q374.84976934375,258.749040625,374.73963934375,258.658658625Q374.62950934375,258.568279625,374.51104734375,258.489126625Q374.39259334375,258.409976625,374.26694834375,258.342817625Q374.14130434375,258.275657625,374.00967834375,258.221137625Q373.87805934375,258.166620625,373.74172934375,258.125263625Q373.60539234375,258.083907625,373.46566034375,258.056110625Q373.32593534375,258.028318625,373.18415034375,258.014354625Q373.04237334375,258.000388625,372.89990234375,258.000388625Q372.75743834375,258.000388625,372.61565434375,258.014354625Q372.47386934375,258.028320625,372.33413734375,258.056112625Q372.19440434375,258.083907625,372.05807534375,258.125264625Q371.92173734375,258.166620625,371.79010734375,258.221137625Q371.65848534375,258.275657625,371.53284434375,258.342817625Q371.40719634375,258.409976625,371.28873834374997,258.489126625Q371.17028834375003,258.568279625,371.06015734375,258.658660625Q370.95002734375,258.749040625,370.84928534375,258.849779625Q370.74855034375,258.95051962499997,370.65816534375,259.060649625Q370.56778734375,259.170778625,370.48863234375,259.289234625Q370.40948534375,259.407691625,370.34232734375,259.533338625Q370.27516934375,259.658985625,370.22064234375,259.790605625Q370.16612234375,259.922229625,370.12477134375,260.058563625Q370.08341234375,260.194896625,370.05561834375,260.334627625Q370.02782834375,260.474359625,370.01386634375,260.616142625Q369.99990034375,260.757923625,369.99990034375,260.900390625Q369.99990034375,261.042857625,370.01386234375,261.184638625Q370.02782834375,261.326421625,370.05561834375,261.466150625Q370.08341234375,261.605882625,370.12476734375,261.742215625Q370.16612234375,261.878547625,370.22064234375,262.010169625Q370.27516934375,262.141794625,370.34232734375,262.267440625Q370.40948534375,262.393085625,370.48863234375,262.511543625Q370.56778734375,262.630000625,370.65816834375,262.740131625Q370.74855034375,262.85026162500003,370.84928934375,262.951000625Q370.95003534375,263.051742625,371.06016134375,263.142122625Q371.17028834375003,263.232501625,371.28874234375,263.311651625Q371.40720334375,263.390804625,371.53284834375,263.457961625Q371.65849334375,263.525121625,371.79011134375,263.579639625Q371.92173734375,263.634162625,372.05807534375,263.675517625Q372.19440834375,263.716876625,372.33413734375,263.744668625Q372.47386934375,263.772464625,372.61565434375,263.786430625Q372.75743834375,263.800392625,372.89990234375,263.800392625ZM367.97151934375,259.73253462499997L369.87776934375,260.38878462499997L370.20328534375,259.44324662500003L368.29703534375,258.78699662500003L367.97151934375,259.73253462499997Z" fill-rule="evenodd" fill="#67E4F4" fill-opacity="1"/><path d="M191.39990234375,320.900390625L191.39990234375,321.921222725L192.39990234375,321.921222725L192.39990234375,320.900390625L191.39990234375,320.900390625ZM191.39990234375,323.962890625L191.39990234375,326.004554725L192.39990234375,326.004554725L192.39990234375,323.962890625L191.39990234375,323.962890625ZM191.39990234375,328.046222725L191.39990234375,330.087890625L192.39990234375,330.087890625L192.39990234375,328.046222725L191.39990234375,328.046222725ZM191.39990234375,332.129554625L191.39990234375,334.171222625L192.39990234375,334.171222625L192.39990234375,332.129554625L191.39990234375,332.129554625ZM191.39990234375,336.212890625L191.39990234375,338.254556625L192.39990234375,338.254556625L192.39990234375,336.212890625L191.39990234375,336.212890625ZM191.39990234375,340.296222625L191.39990234375,342.337888625L192.39990234375,342.337888625L192.39990234375,340.296222625L191.39990234375,340.296222625ZM191.39990234375,344.379556625L191.39990234375,346.421222625L192.39990234375,346.421222625L192.39990234375,344.379556625L191.39990234375,344.379556625ZM191.39990234375,348.462890625L191.39990234375,350.504556625L192.39990234375,350.504556625L192.39990234375,348.462890625L191.39990234375,348.462890625ZM191.39990234375,352.546222625L191.39990234375,354.587890625L192.39990234375,354.587890625L192.39990234375,352.546222625L191.39990234375,352.546222625ZM191.39990234375,356.62955462499997L191.39990234375,358.671222625L192.39990234375,358.671222625L192.39990234375,356.62955462499997L191.39990234375,356.62955462499997ZM191.39990234375,360.712890625L191.39990234375,362.754558625L192.39990234375,362.754558625L192.39990234375,360.712890625L191.39990234375,360.712890625ZM191.39990234375,364.796222625L191.39990234375,366.837890625L192.39990234375,366.837890625L192.39990234375,364.796222625L191.39990234375,364.796222625ZM191.89990234375,372.800392625Q192.04237027375,372.800392625,192.18415218375,372.786430625Q192.32593411375,372.772464625,192.46566450375,372.744666625Q192.60539496375,372.716873625,192.74172830375,372.675521625Q192.87806165375,372.634162625,193.00968484375,372.579639625Q193.14130804375,372.525123625,193.26695344375,372.457961625Q193.39259884375,372.390800625,193.51105664375,372.311649625Q193.62951444375,372.232498625,193.73964364375001,372.14211662499997Q193.84977294375,372.051738625,193.95051284375,371.950996625Q194.05125284375,371.850257625,194.14163374375,371.740127625Q194.23201444375,371.629997625,194.31116534375,371.511539625Q194.39031644375,371.393081625,194.45747514375,371.267436625Q194.52463414375,371.141792625,194.57915404375,371.010166625Q194.63367434375,370.878547625,194.67503074375,370.742217625Q194.71638704375,370.605880625,194.74418094375,370.466148625Q194.77197554375,370.326423625,194.78593964375,370.184638625Q194.79990414375,370.042861625,194.79990384375,369.900390625Q194.79990414375,369.757926625,194.78593994375,369.616142625Q194.77197554375,369.474357625,194.74418114375,369.334625625Q194.71638724375,369.194900625,194.67503094375,369.058563625Q194.63367464375,368.922233625,194.57915424375,368.790603625Q194.52463434375,368.658981625,194.45747544375,368.533332625Q194.39031644375,368.407691625,194.31116534375,368.289230625Q194.23201444375,368.17077662500003,194.14163354375,368.060645625Q194.05125284375,367.950515625,193.95051284375,367.849777625Q193.84977294375,367.749038625,193.73964354375,367.658656625Q193.62951444375,367.568275625,193.51105654375,367.489124625Q193.39259884375,367.409973625,193.26695344375,367.342815625Q193.14130804375,367.275657625,193.00968484375,367.221134625Q192.87806165375,367.166618625,192.74172830375,367.125263625Q192.60539496375,367.083907625,192.46566450375,367.056110625Q192.32593411375,367.028320625,192.18415218375,367.014354625Q192.04237027375,367.000392625,191.89990234375,367.000388625Q191.75743441375,367.000392625,191.61565250375,367.014358625Q191.47387057375,367.028320625,191.33414018375,367.056110625Q191.19440972375,367.083907625,191.05807638375,367.125263625Q190.92174303375,367.166618625,190.79011984375,367.221134625Q190.65849664375,367.275657625,190.53285124375,367.342815625Q190.40720584375,367.409973625,190.28874804375,367.489120625Q190.17029024375,367.568275625,190.06016104374999,367.658656625Q189.95003174375,367.749038625,189.84929184375,367.849777625Q189.74855184375,367.950515625,189.65817094375,368.060645625Q189.56779024375,368.17077662500003,189.48863934375,368.289230625Q189.40948824375,368.407691625,189.34232954375,368.533336625Q189.27517054375,368.658981625,189.22065064375,368.790603625Q189.16613034375,368.922233625,189.12477394375,369.058566625Q189.08341764375,369.194900625,189.05562374375,369.334625625Q189.02782914375,369.474357625,189.01386504375,369.616142625Q188.99990054375,369.757926625,188.99990084375,369.900390625Q188.99990054375,370.042861625,189.01386474375,370.184642625Q189.02782914375,370.326423625,189.05562354375,370.466152625Q189.08341744375,370.605884625,189.12477374375,370.742214625Q189.16613004375,370.878547625,189.22065044375,371.010166625Q189.27517034375,371.141792625,189.34232924375,371.267440625Q189.40948824375,371.393081625,189.48863934375,371.511539625Q189.56779024375,371.629997625,189.65817114375,371.740127625Q189.74855184375,371.850257625,189.84929184375,371.950996625Q189.95003174375,372.051738625,190.06016114375,372.142120625Q190.17029024375,372.232498625,190.28874814375,372.311645625Q190.40720584375,372.390800625,190.53285124375,372.457958625Q190.65849664375,372.525115625,190.79011984375,372.579635625Q190.92174303375,372.634162625,191.05807638375,372.675517625Q191.19440972375,372.716873625,191.33414018375,372.744666625Q191.47387057375,372.772464625,191.61565250375,372.786430625Q191.75743441375,372.800392625,191.89990234375,372.800392625Z" fill-rule="evenodd" fill="#67E4F4" fill-opacity="1"/><path d="M59.78063934375,231.414822455L58.83064634375,231.648154705L59.06916834375,232.619291065L60.01916134375,232.385958795L59.78063934375,231.414822455ZM56.93064134375,232.114821735L55.03064334375,232.581487895L55.26916934375,233.552624225L57.16916634375,233.085958125L56.93064134375,232.114821735ZM53.13064534375,233.048154125L51.23064034375,233.514821125L51.46916534375,234.485957425L53.36916734375,234.019290425L53.13064534375,233.048154125ZM49.33064234375,233.981488225L47.43064534375,234.448154425L47.66916634375,235.419290525L49.56916434375,234.952624325L49.33064234375,233.981488225ZM45.53064334375,234.914820625L43.63064234375,235.381488525L43.86916334375,236.352624425L45.76916934375,235.885956725L45.53064334375,234.914820625ZM41.73064034375,235.848154825L39.83064634375,236.314820725L40.06916834375,237.285956825L41.96916534375,236.819290625L41.73064034375,235.848154825ZM37.93064134375,236.781487925L36.03064334375,237.248155125L36.26916534375,238.219291225L38.16916634375,237.752624025L37.93064134375,236.781487925ZM34.130645343750004,237.714821325L32.23064234375,238.181488025L32.46916534375,239.152624625L34.36916934375,238.685957425L34.130645343750004,237.714821325ZM30.33064234375,238.648155225L28.43064134375,239.114820925L28.66916434375,240.085957525L30.56916634375,239.619291825L30.33064234375,238.648155225ZM26.53064134375,239.581487225L24.63064234375,240.048154825L24.86916534375,241.019291925L26.76916534375,240.552623725L26.53064134375,239.581487225ZM22.73064234375,240.514821025L20.83064234375,240.981487225L21.06916634375,241.952624625L22.96916534375,241.485958125L22.73064234375,240.514821025ZM18.93064134375,241.448154425L17.03064134375,241.914821625L17.26916534375,242.885958625L19.16916434375,242.419291625L18.93064134375,241.448154425ZM15.13064034375,242.381487625L13.23064034375,242.848154625L13.46916534375,243.819291625L15.36916534375,243.352624625L15.13064034375,242.381487625ZM2.89990234375,248.800392625Q3.04237029375,248.800392625,3.18415218375,248.78642862499999Q3.32593411375,248.772464625,3.4656645037500002,248.744668625Q3.60539502375,248.716874625,3.74172830375,248.675517625Q3.87806165375,248.634162625,4.00968484375,248.579639625Q4.14130804375,248.525121625,4.26695344375,248.457961625Q4.39259914375,248.390804625,4.51105674375,248.311651625Q4.62951454375,248.232499625,4.73964384375,248.142120625Q4.84977304375,248.05173862499998,4.950513143749999,247.951000625Q5.05125334375,247.850260625,5.14163394375,247.740131625Q5.23201464375,247.630001625,5.31116534375,247.511543625Q5.390316443750001,247.393087625,5.45747544375,247.267440625Q5.52463434375,247.141795625,5.579154243750001,247.010171625Q5.63367464375,246.878549625,5.67503094375,246.742215625Q5.71638724375,246.605882625,5.74418114375,246.466152625Q5.77197554375,246.326421625,5.78593964375,246.184640625Q5.799904343750001,246.042857625,5.79990414375,245.900390625Q5.799904343750001,245.757923625,5.78593994375,245.616140625Q5.77197554375,245.474359625,5.74418114375,245.334627625Q5.71638724375,245.194898625,5.67503094375,245.058565625Q5.63367464375,244.922231625,5.579154243750001,244.790607625Q5.52463434375,244.658985625,5.45747544375,244.533338625Q5.390316443750001,244.407693625,5.31116534375,244.289234625Q5.23201464375,244.170778625,5.14163394375,244.060648625Q5.05125334375,243.950519625,4.950513143749999,243.849779625Q4.84977304375,243.749040625,4.73964384375,243.658658625Q4.62951454375,243.568278625,4.51105674375,243.489126625Q4.39259914375,243.409975625,4.26695354375,243.342817625Q4.14130804375,243.275657625,4.00968484375,243.22113662499999Q3.87806165375,243.166618625,3.74172836375,243.125261625Q3.60539502375,243.083906625,3.4656645037500002,243.056112625Q3.32593411375,243.028318625,3.18415218375,243.014353625Q3.04237029375,243.000388625,2.89990234375,243.000388625Q2.75743439375,243.000388625,2.61565250375,243.014354625Q2.47387057375,243.028318625,2.3341401837499998,243.056112625Q2.19440966375,243.083906625,2.05807638375,243.125263625Q1.9217430337499999,243.166618625,1.79011984375,243.221137625Q1.65849664375,243.275659625,1.53285124375,243.342818625Q1.40720554375,243.409976625,1.28874794375,243.489127625Q1.17029014375,243.568279625,1.06016084375,243.658659625Q0.95003164375,243.749040625,0.8492915437500002,243.849779625Q0.74855134375,243.950519625,0.65817074375,244.060647625Q0.5677900437500001,244.170778625,0.48863934375000007,244.289234625Q0.4094882437499998,244.407693625,0.34232924375000007,244.533338625Q0.27517034375000016,244.658985625,0.22065044374999987,244.790607625Q0.16613004374999996,244.922231625,0.12477374375000005,245.058565625Q0.08341744375000015,245.194898625,0.05562354374999989,245.334627625Q0.027829143750000007,245.474359625,0.013865043750000083,245.616142625Q-0.00009965625000019074,245.757923625,-0.00009945625000007396,245.900390625Q-0.00009965625000019074,246.042857625,0.01386474375000013,246.184640625Q0.027829143750000007,246.326421625,0.05562354374999989,246.466152625Q0.08341744375000015,246.605882625,0.12477374375000005,246.742215625Q0.16613004374999996,246.878549625,0.22065044374999987,247.010171625Q0.27517034375000016,247.141795625,0.34232924375000007,247.267441625Q0.4094882437499998,247.393087625,0.48863934375000007,247.511543625Q0.5677900437500001,247.630001625,0.65817074375,247.740131625Q0.74855134375,247.850260625,0.8492915437500002,247.951000625Q0.95003164375,248.05173862499998,1.06016084375,248.142120625Q1.17029014375,248.232499625,1.28874794375,248.311651625Q1.40720554375,248.390804625,1.53285114375,248.457961625Q1.65849664375,248.525121625,1.79011984375,248.579639625Q1.9217430337499999,248.634162625,2.05807632375,248.675517625Q2.19440966375,248.716874625,2.3341401837499998,248.744668625Q2.47387057375,248.772464625,2.61565250375,248.78642862499999Q2.75743439375,248.800392625,2.89990234375,248.800392625ZM11.33064074375,243.314821625L9.43064074375,243.781487625L9.669164643750001,244.752624625L11.56916524375,244.285957625L11.33064074375,243.314821625ZM7.53064064375,244.248154625L5.630640243749999,244.714820625L5.86916514375,245.68595762500001L7.76916504375,245.219291625L7.53064064375,244.248154625Z" fill-rule="evenodd" fill="#67E4F4" fill-opacity="1"/><path d="M3.89990234375,104.300392125Q4.04237027375,104.300392125,4.18415218375,104.286428225Q4.32593411375,104.272463825,4.46566450375,104.244669425Q4.60539496375,104.216875525,4.7417283037499995,104.175519225Q4.87806165375,104.134162925,5.00968484375,104.079642525Q5.14130804375,104.025122625,5.26695344375,103.957963725Q5.39259884375,103.890804725,5.51105664375,103.811653625Q5.62951444375,103.732502725,5.73964364375,103.642121825Q5.84977294375,103.551741125,5.9505128437499994,103.451001125Q6.0512528437499995,103.350261225,6.14163374375,103.240131825Q6.23201444375,103.130002725,6.31116534375,103.011544825Q6.390316443750001,102.893087125,6.45747514375,102.767441725Q6.52463414375,102.641796325,6.57915404375,102.510173125Q6.63367434375,102.378549935,6.67503074375,102.242216585Q6.71638704375,102.105883245,6.74418094375,101.966152785Q6.77197554375,101.826422395,6.78593964375,101.684640465Q6.79990414375,101.542858555,6.79990384375,101.400390625Q6.79990414375,101.257922695,6.78593994375,101.116140785Q6.77197554375,100.974358855,6.74418114375,100.834628465Q6.71638724375,100.694898005,6.67503094375,100.558564665Q6.63367464375,100.422231315,6.579154243750001,100.290608125Q6.52463434375,100.158984925,6.45747544375,100.033339525Q6.390316443750001,99.907694125,6.31116534375,99.789236325Q6.23201444375,99.670778525,6.14163354375,99.560649325Q6.0512528437499995,99.450520025,5.9505128437499994,99.349780125Q5.84977294375,99.249040125,5.73964354375,99.158659225Q5.62951444375,99.068278525,5.51105654375,98.989127625Q5.39259884375,98.909976525,5.26695344375,98.842817825Q5.14130804375,98.775658825,5.00968484375,98.721138925Q4.87806165375,98.666618625,4.7417283037499995,98.625262225Q4.60539496375,98.583905925,4.46566450375,98.556112025Q4.32593411375,98.528317425,4.18415218375,98.514353325Q4.04237027375,98.500389125,3.89990234375,98.500389125Q3.75743441375,98.500389125,3.61565250375,98.514353025Q3.47387057375,98.528317425,3.3341401837499998,98.556111825Q3.1944097237499998,98.583905725,3.05807638375,98.625262025Q2.92174303375,98.666618325,2.7901198437500003,98.721138725Q2.65849664375,98.775658625,2.5328512437499997,98.842817525Q2.40720584375,98.909976525,2.28874804375,98.989127625Q2.1702902437500002,99.068278525,2.06016104375,99.158659425Q1.95003174375,99.249040125,1.84929184375,99.349780125Q1.74855184375,99.450520025,1.65817094375,99.560649425Q1.5677902437500002,99.670778525,1.48863934375,99.789236425Q1.4094882437499998,99.907694125,1.34232954375,100.033339525Q1.2751705437499998,100.158984925,1.22065064375,100.290608125Q1.16613034375,100.422231315,1.1247739437500002,100.558564665Q1.0834176437499998,100.694898005,1.05562374375,100.834628465Q1.02782914375,100.974358855,1.01386504375,101.116140785Q0.9999005437499999,101.257922695,0.9999008437499999,101.400390625Q0.9999005437499999,101.542858555,1.0138647437500001,101.684640465Q1.02782914375,101.826422395,1.05562354375,101.966152785Q1.0834174437500002,102.105883245,1.12477374375,102.242216585Q1.16613004375,102.378549935,1.2206504437499999,102.510173125Q1.2751703437500002,102.641796325,1.34232924375,102.767441725Q1.4094882437499998,102.893087125,1.48863934375,103.011544925Q1.5677902437500002,103.130002725,1.6581711437500002,103.240131925Q1.74855184375,103.350261225,1.84929184375,103.451001125Q1.95003174375,103.551741125,2.0601611437500003,103.642122025Q2.1702902437500002,103.732502725,2.28874814375,103.811653625Q2.40720584375,103.890804725,2.5328512437499997,103.957963425Q2.65849664375,104.025122425,2.7901198437500003,104.079642325Q2.92174303375,104.134162625,3.05807638375,104.175519025Q3.1944097237499998,104.216875325,3.3341401837499998,104.244669225Q3.47387057375,104.272463825,3.61565250375,104.286427925Q3.75743441375,104.300392125,3.89990234375,104.300392125ZM8.76500944375,102.507302925L6.882655843749999,101.874949965L6.564207343750001,102.822890025L8.44656034375,103.455242825L8.76500944375,102.507302925ZM12.52971454375,103.772008625L10.647362243749999,103.139655725L10.32891324375,104.087595725L12.21126554375,104.719948525L12.52971454375,103.772008625ZM16.294421343750003,105.036714525L14.41206734375,104.404361725L14.09361834375,105.352301625L15.97597234375,105.984654425L16.294421343750003,105.036714525ZM20.05912634375,106.301420225L18.176774343749997,105.669067825L17.85832534375,106.617007725L19.74067734375,107.249360125L20.05912634375,106.301420225ZM23.82383134375,107.566126325L21.94147834375,106.933773525L21.62303134375,107.881713425L23.50538434375,108.514066225L23.82383134375,107.566126325ZM27.58853734375,108.830832525L25.70618434375,108.198479225L25.38773734375,109.146419025L27.27009034375,109.778772325L27.58853734375,108.830832525ZM31.35324334375,110.095537225L29.47089034375,109.463184325L29.15244334375,110.411125225L31.03479534375,111.043478025L31.35324334375,110.095537225ZM35.117950343749996,111.360243825L33.23559734375,110.727890925L32.917150343749995,111.675831625L34.799503343750004,112.308184625L35.117950343749996,111.360243825ZM38.88265634375,112.624949625L37.00030534375,111.992596625L36.68185434375,112.940537625L38.56420534375,113.572890625L38.88265634375,112.624949625ZM42.64736134375,113.889654625L40.76501034375,113.257302625L40.44656034375,114.205242625L42.32891034375,114.837595625L42.64736134375,113.889654625ZM46.41207134375,115.154361625L44.52971634375,114.522008625L44.21126534375,115.469949625L46.09362034375,116.102302625L46.41207134375,115.154361625ZM50.17677334375,116.419066625L48.29442234375,115.786713625L47.97597134375,116.734654625L49.85832234375,117.367007625L50.17677334375,116.419066625ZM53.94147834375,117.683772625L52.05912734375,117.051420625L51.74067734375,117.99936062500001L53.62302734375,118.631713625L53.94147834375,117.683772625ZM57.70618834375,118.948478625L55.82383334375,118.316125625L55.50538234375,119.264066625L57.38773734375,119.896419625L57.70618834375,118.948478625ZM61.47089034375,120.213184625L59.58853934375,119.580831625L59.27008834375,120.528772625L61.15243934375,121.161125625L61.47089034375,120.213184625ZM65.23559934375001,121.477889625L63.35324434375,120.84553762499999L63.03479434375,121.79347762500001L64.91714834375,122.425830625L65.23559934375001,121.477889625ZM68.05912734375,122.426418625L67.11794634374999,122.110242625L66.79949534375001,123.058183625L67.74067734375001,123.374359625L68.05912734375,122.426418625Z" fill-rule="evenodd" fill="#67E4F4" fill-opacity="1"/><path d="M188.39990234375,5.800392125Q188.54237027375,5.800392125,188.68415218375,5.786428225Q188.82593411375,5.772463825,188.96566450375,5.744669425Q189.10539496375,5.716875525,189.24172830375,5.675519225Q189.37806165375,5.634162925,189.50968484375,5.579642525000001Q189.64130804375,5.525122625,189.76695344375,5.457963725Q189.89259884375,5.390804725000001,190.01105664375,5.311653625Q190.12951444375,5.232502725,190.23964364375001,5.142121825Q190.34977294375,5.0517411249999995,190.45051284375,4.9510011249999994Q190.55125284375,4.850261225,190.64163374375,4.740131825Q190.73201444375,4.630002725,190.81116534375,4.511544825Q190.89031644375,4.393087125,190.95747514375,4.267441725Q191.02463414375,4.141796325,191.07915404375,4.010173125Q191.13367434375,3.878549935,191.17503074375,3.742216585Q191.21638704375,3.6058832450000002,191.24418094375,3.4661527850000002Q191.27197554375,3.326422395,191.28593964375,3.184640465Q191.29990414375,3.042858555,191.29990384375,2.900390625Q191.29990414375,2.757922695,191.28593994375,2.616140785Q191.27197554375,2.474358855,191.24418114375,2.3346284649999998Q191.21638724375,2.1948980049999998,191.17503094375,2.058564665Q191.13367464375,1.9222313149999999,191.07915424375,1.790608125Q191.02463434375,1.658984925,190.95747544375,1.533339525Q190.89031644375,1.407694125,190.81116534375,1.289236325Q190.73201444375,1.170778525,190.64163354375,1.060649325Q190.55125284375,0.9505200250000001,190.45051284375,0.8497801250000001Q190.34977294375,0.7490401250000001,190.23964354375,0.6586592250000001Q190.12951444375,0.5682785250000002,190.01105654375,0.48912762500000007Q189.89259884375,0.4099765249999998,189.76695344375,0.342817825Q189.64130804375,0.27565882499999983,189.50968484375,0.221138925Q189.37806165375,0.1666186249999999,189.24172830375,0.12526222500000017Q189.10539496375,0.08390592499999983,188.96566450375,0.05611202500000001Q188.82593411375,0.028317425000000007,188.68415218375,0.014353325000000083Q188.54237027375,0.00038912499999987915,188.39990234375,0.00038912499999987915Q188.25743441375,0.00038912499999987915,188.11565250375,0.01435302500000013Q187.97387057375,0.028317425000000007,187.83414018375,0.05611182499999989Q187.69440972375,0.08390572500000015,187.55807638375,0.12526202500000005Q187.42174303375,0.16661832499999996,187.29011984375,0.22113872499999987Q187.15849664375,0.27565862500000016,187.03285124375,0.34281752500000007Q186.90720584375,0.4099765249999998,186.78874804375,0.48912762500000007Q186.67029024375,0.5682785250000002,186.56016104374999,0.6586594250000002Q186.45003174375,0.7490401250000001,186.34929184375,0.8497801250000001Q186.24855184375,0.9505200250000001,186.15817094375,1.060649425Q186.06779024375,1.170778525,185.98863934375,1.289236425Q185.90948824375,1.407694125,185.84232954375,1.533339525Q185.77517054375,1.658984925,185.72065064375,1.790608125Q185.66613034375,1.9222313149999999,185.62477394375,2.058564665Q185.58341764375,2.1948980049999998,185.55562374375,2.3346284649999998Q185.52782914375,2.474358855,185.51386504375,2.616140785Q185.49990054375,2.757922695,185.49990084375,2.900390625Q185.49990054375,3.042858555,185.51386474375,3.184640465Q185.52782914375,3.326422395,185.55562354375,3.4661527850000002Q185.58341744375,3.6058832450000002,185.62477374375,3.742216585Q185.66613004375,3.878549935,185.72065044375,4.010173125Q185.77517034375,4.141796325,185.84232924375,4.267441725Q185.90948824375,4.393087125,185.98863934375,4.511544925Q186.06779024375,4.630002725,186.15817114375,4.740131925Q186.24855184375,4.850261225,186.34929184375,4.9510011249999994Q186.45003174375,5.0517411249999995,186.56016114375,5.142122025Q186.67029024375,5.232502725,186.78874814375,5.311653625Q186.90720584375,5.390804725000001,187.03285124375,5.457963425Q187.15849664375,5.525122425,187.29011984375,5.579642325Q187.42174303375,5.634162625,187.55807638375,5.675519025Q187.69440972375,5.716875325,187.83414018375,5.744669225Q187.97387057375,5.772463825,188.11565250375,5.786427925Q188.25743441375,5.800392125,188.39990234375,5.800392125ZM188.89990234375,8.004557625L188.89990234375,5.962890625L187.89990234375,5.962890625L187.89990234375,8.004557625L188.89990234375,8.004557625ZM188.89990234375,12.087890625L188.89990234375,10.046224125L187.89990234375,10.046224125L187.89990234375,12.087890625L188.89990234375,12.087890625ZM188.89990234375,16.171224625L188.89990234375,14.129557625L187.89990234375,14.129557625L187.89990234375,16.171224625L188.89990234375,16.171224625ZM188.89990234375,20.254558625L188.89990234375,18.212891624999997L187.89990234375,18.212891624999997L187.89990234375,20.254558625L188.89990234375,20.254558625ZM188.89990234375,24.337890625L188.89990234375,22.296224625L187.89990234375,22.296224625L187.89990234375,24.337890625L188.89990234375,24.337890625ZM188.89990234375,28.421224625L188.89990234375,26.379558625L187.89990234375,26.379558625L187.89990234375,28.421224625L188.89990234375,28.421224625ZM188.89990234375,32.504558625L188.89990234375,30.462892625L187.89990234375,30.462892625L187.89990234375,32.504558625L188.89990234375,32.504558625ZM188.89990234375,36.587890625L188.89990234375,34.546224625L187.89990234375,34.546224625L187.89990234375,36.587890625L188.89990234375,36.587890625ZM188.89990234375,40.671226625L188.89990234375,38.629558625L187.89990234375,38.629558625L187.89990234375,40.671226625L188.89990234375,40.671226625ZM188.89990234375,44.754558625L188.89990234375,42.712890625L187.89990234375,42.712890625L187.89990234375,44.754558625L188.89990234375,44.754558625ZM188.89990234375,48.837890625L188.89990234375,46.796226625L187.89990234375,46.796226625L187.89990234375,48.837890625L188.89990234375,48.837890625ZM188.89990234375,51.900390625L188.89990234375,50.879558625L187.89990234375,50.879558625L187.89990234375,51.900390625L188.89990234375,51.900390625Z" fill-rule="evenodd" fill="#67E4F4" fill-opacity="1"/></svg>
\ No newline at end of file
diff --git a/src/assets/system/baogong.svg b/src/assets/system/baogong.svg
new file mode 100644
index 0000000..daddd9c
--- /dev/null
+++ b/src/assets/system/baogong.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="62.90625" viewBox="0 0 59.5 62.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35815"><rect x="14" y="0" width="30" height="30" rx="0"/></clipPath></defs><path d="M1.204819142818451,26.096379L28.69276814281845,42.307213000000004L58.29516614281845,26.096379L28.69276814281845,12L1.204819142818451,26.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,26.065809L28.43877614281845,42.737896L28.68361514281845,42.882288L59.39288714281845,26.065309L28.684561142818453,11.44229615L0.16870074281845082,26.065809ZM28.70192014281845,41.732138L2.240937742818451,26.12695L28.70097614281845,12.55770427L57.19744514281845,26.127449L28.70192014281845,41.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,26.80120277404785L0.5,45.83131777404785L28.692764,62.042150774047855L28.692764,43.01204077404785L0.5,26.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,62.906411774047854L29.192764,42.722777774047856L28.941999,42.578587774047854L-5.999999996841865e-8,25.93693918404785L0,46.12058077404785L29.192764,62.906411774047854ZM28.192764,43.30130377404785L28.192764,61.17788877404785L1,45.542054774047855L1,27.66546636404785L28.192764,43.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,26.80120277404785L59,45.12649377404785L88.5,62.00042177404785L88.5,42.26604677404785L59,26.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,62.86243677404785L89,41.96362277404785L88.732151,41.82320777404785L58.50000003,25.97454732404785L58.50000003,45.41651177404785L89,62.86243677404785ZM88,42.568469774047855L88,61.13840677404785L59.5,44.836475774047855L59.5,27.627858224047852L88,42.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35815)"><path d="M17.76220696875,10.375L20.44873021875,10.375C20.92626951875,10.375,21.35986331875,9.985351999999999,21.35986331875,9.5078125C21.35986331875,9.030272499999999,20.97021481875,8.640624500000001,20.44873021875,8.640624500000001L17.76220696875,8.640624500000001C17.28466784875,8.640624500000001,16.85107421875,9.030272499999999,16.85107421875,9.5078125C16.85400386155,9.985351099999999,17.24365239875,10.375,17.76220696875,10.375ZM21.31591801875,20.51465C21.31591801875,20.037111,20.92626951875,19.647463,20.40478491875,19.647463L17.76220696875,19.647463C17.28466784875,19.647463,16.85107421875,20.037111,16.85107421875,20.51465C16.85107421875,20.992188,17.24072274875,21.381836,17.76220696875,21.381836L20.44873021875,21.381836C20.92626951875,21.381836,21.31591801875,20.992188,21.31591801875,20.51465ZM33.66748021875,20.643555L33.27783221875,20.382812C32.88818321875,20.078123,32.80029421875,19.515625,33.10498021875,19.125975L35.31396521875,16.395505L34.61962921875,15.833005L32.36669821875,18.563475C32.062010218750004,18.953123,31.49951221875,18.997068,31.109861218749998,18.692382000000002L30.764159218750002,18.431639L40.90380821875,6.2119140999999996C40.90380821875,4.2607421,39.30126921875,2.875,37.35009721875,2.875L21.74951221875,2.875C20.27587891875,2.875,18.97509791875,3.69824213,18.97509791875,5.171875L18.97509791875,6.90625L20.31982471875,6.90625C21.48877001875,6.90625,22.66064501875,7.9023438,22.66064501875,9.203125C22.66064501875,10.5039062,21.74951221875,11.5,20.45166061875,11.5L18.97802781875,11.5L18.97802781875,17.87207L20.32275461875,17.87207C21.49170021875,17.87207,22.66357521875,18.868164999999998,22.66357521875,20.168947C22.66357521875,21.469728,21.75244191875,22.465822,20.45459051875,22.465822L18.98095731875,22.465822L18.98095731875,24.5459C18.98095731875,26.019533,20.28173831875,27.103518,21.755372018750002,27.103518L38.22314421875,27.103518C39.69677721875,27.103518,41.12646521875,26.019533,41.12646521875,24.5459L41.12646521875,11.6728516L33.66748021875,20.643555ZM30.37451121875,22.333984C30.069822218749998,22.462893,29.29052621875,22.205078,29.33447121875,21.856445L30.24560321875,19.125977L33.02001721875,21.334963L30.37451121875,22.333984Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/baogongtaizhang.svg b/src/assets/system/baogongtaizhang.svg
new file mode 100644
index 0000000..d668f96
--- /dev/null
+++ b/src/assets/system/baogongtaizhang.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35824"><rect x="12.5" y="0" width="34.000003814697266" height="34" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35824)"><path d="M30.364756937499997,25.1723935L31.5122539375,23.7415655C30.7614219375,22.8348995,30.3080869375,21.6732315,30.3080869375,20.4265635C30.3080869375,17.5648925,32.6455929375,15.2273945,35.5214249375,15.2273945C37.0655859375,15.2273945,38.4680879375,15.9073935,39.417254937500005,16.969893499999998L39.417254937500005,4.4890625C39.417254937500005,3.55406219,38.652257937499996,2.7890625,37.7172569375,2.7890625L19.3005861375,2.7890625C18.3655856875,2.7890625,17.6005859375,3.55406243,17.6005859375,4.4890625L17.6005859375,26.5890575C17.6005859375,27.5240575,18.3655862175,28.2890625,19.3005861375,28.2890625L27.4747514375,28.2890625C27.8289189375,26.8015635,28.933920937499998,25.6115625,30.364756937499997,25.1723935ZM23.706419037499998,6.7982302L33.339754937500004,6.7982302C33.963088937500004,6.7982302,34.4730839375,7.3082304,34.4730839375,7.9315624C34.4730839375,8.5548954,33.963088937500004,9.0648956,33.339754937500004,9.0648956L23.7064218375,9.0648956C23.083087437499998,9.0648956,22.5730877375,8.5548968,22.5730877375,7.9315639C22.5730877375,7.3082304,23.0689206375,6.7982302,23.706419037499998,6.7982302ZM23.706419037499998,11.8982306L33.339754937500004,11.8982306C33.963088937500004,11.8982306,34.4730839375,12.4082298,34.4730839375,13.0315625C34.4730839375,13.6548975,33.963088937500004,14.1648965,33.339754937500004,14.1648965L23.7064218375,14.1648965C23.083087437499998,14.1648965,22.5730877375,13.6548975,22.5730877375,13.0315625C22.5730877375,12.4082298,23.0689206375,11.8982306,23.706419037499998,11.8982306ZM22.5730872375,18.1315635C22.5730872375,17.5082325,23.0830865375,16.9982295,23.706419037499998,16.9982295L27.6730879375,16.9982295C28.296420937500002,16.9982295,28.8064209375,17.5082265,28.8064209375,18.1315575C28.8064209375,18.754890500000002,28.296420937500002,19.2648965,27.6730879375,19.2648965L23.706419037499998,19.2648965C23.0689187375,19.2648965,22.5730872375,18.7548925,22.5730872375,18.1315635Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M39.43028168125,31.168883875L31.596113881249998,31.168883875C30.51944607125,31.168883875,29.64111328125,30.290549875,29.64111328125,29.213882875C29.64111328125,28.137214874999998,30.51944607125,27.258882475,31.596113881249998,27.258882475L34.81194638125,23.263881675C33.52277968125,22.952215175,32.57361388125,21.804714675,32.57361388125,20.430547675C32.57361388125,18.815546775,33.89111378125,17.498046875,35.52027988125,17.498046875C37.14944748125,17.498046875,38.46694468125,18.815546775,38.46694468125,20.430547675C38.46694468125,21.804714675,37.51777978125,22.952215175,36.22861288125,23.263881675L39.44444748125,27.258882475C40.52111428125,27.258882475,41.39944628125,28.137214874999998,41.39944628125,29.213882875C41.39944628125,30.290549875,40.52111428125,31.168883875,39.43028168125,31.168883875Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/caigoubaobiao.svg b/src/assets/system/caigoubaobiao.svg
new file mode 100644
index 0000000..164efe4
--- /dev/null
+++ b/src/assets/system/caigoubaobiao.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="60.90625" viewBox="0 0 59.5 60.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35725"><rect x="16.5" y="0" width="27" height="27" rx="0"/></clipPath></defs><path d="M1.204819142818451,24.096379L28.69276814281845,40.307213000000004L58.29516614281845,24.096379L28.69276814281845,10L1.204819142818451,24.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,24.065809L28.43877614281845,40.737896L28.68361514281845,40.882288L59.39288714281845,24.065309L28.684561142818453,9.44229615L0.16870074281845082,24.065809ZM28.70192014281845,39.732138L2.240937742818451,24.12695L28.70097614281845,10.55770427L57.19744514281845,24.127449L28.70192014281845,39.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,24.80120277404785L0.5,43.83131777404785L28.692764,60.042150774047855L28.692764,41.01204077404785L0.5,24.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,60.906411774047854L29.192764,40.722777774047856L28.941999,40.578587774047854L-5.999999996841865e-8,23.93693918404785L0,44.12058077404785L29.192764,60.906411774047854ZM28.192764,41.30130377404785L28.192764,59.17788877404785L1,43.542054774047855L1,25.66546636404785L28.192764,41.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,24.80120277404785L59,43.12649377404785L88.5,60.00042177404785L88.5,40.26604677404785L59,24.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,60.86243677404785L89,39.96362277404785L88.732151,39.82320777404785L58.50000003,23.97454732404785L58.50000003,43.41651177404785L89,60.86243677404785ZM88,40.568469774047855L88,59.13840677404785L59.5,42.836475774047855L59.5,25.627858224047852L88,40.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35725)"><path d="M18.2960399,19.401375L41.644558,19.401375C42.208858,19.348387,42.619251,18.840738,42.553804,18.276657L42.553804,1.1247175C42.619251,0.56063783,42.208858,0.052988321,41.644558,0L18.2960399,0C17.7349908,0.059026856,17.3279168,0.56256902,17.38679475,1.1247175L17.38679475,18.321648C17.34767658,18.868998,17.7509638,19.347902,18.2960399,19.401375ZM34.628777,3.554107L39.46686,3.554107C39.800758,3.5838315,40.052634999999995,3.8708398,40.039347,4.2064433C40.05232,4.5398693,39.799026,4.8235159,39.46686,4.8475323L34.628777,4.8475323C34.305557,4.8122854,34.065008,4.5319171,34.078739,4.2064433C34.064516,3.8786428,34.303837,3.5948114,34.628777,3.554107ZM34.628777,6.7145634L39.46686,6.7145634C39.799026,6.7385783,40.05232,7.0222259,40.039347,7.3556523C40.052634999999995,7.6912551,39.800758,7.9782634,39.46686,8.007988L34.628777,8.007988C34.303835,7.9672842,34.064516,7.6834526,34.078739,7.3556523C34.082552,7.0430193,34.31859,6.7823882,34.628777,6.7483044L34.628777,6.7145634ZM34.628777,9.976243L39.46686,9.976243C39.797287,9.9944181,40.052101,10.27476,40.039347,10.606086C40.052634999999995,10.941689,39.800758,11.228697,39.46686,11.258421L34.628777,11.258421C34.303835,11.217718,34.064516,10.933886,34.078739,10.606086C34.06542,10.282872,34.307281,10.005919,34.628777,9.976243ZM26.322093000000002,3.554107C26.4553547,3.4100845,26.682741,3.4100845,26.816004,3.554107L29.061052,6.4333839L28.163033,6.4333839L26.277193099999998,4.0827241C26.1536102,3.9213576,26.1730719,3.6922283,26.322093000000002,3.554107ZM21.5176859,6.4783726L23.7627358,3.610343C23.8959985,3.4663203,24.123385,3.4663203,24.2566466,3.610343C24.392286300000002,3.7603433,24.392286300000002,3.9889596,24.2566466,4.1389604L22.382030999999998,6.5346084L21.4840107,6.5346084L21.5176859,6.4783726ZM20.0247281,7.2769227L30.542787,7.2769227C30.746521,7.2944822,30.902746,7.4656887,30.901995,7.6705737C30.908293999999998,7.8693829,30.75244,8.0356159,30.554012,8.0417309L30.206031,8.0417309L29.083506,14.126452C29.001704,14.465208,28.701669000000003,14.705706,28.353864,14.711306L22.191201200000002,14.711306C21.841960399999998,14.709742,21.5397458,14.467498,21.4615598,14.126452L20.3390353,8.0304842L20.0247283,8.0304842C19.8418345,7.9987054,19.7082825,7.8396893,19.7082825,7.6537042C19.7082825,7.4677172,19.8418345,7.308702,20.0247281,7.2769227ZM23.482104800000002,12.833026C23.6805339,12.826911,23.8363857,12.660679,23.8300877,12.461868L23.8300877,9.4588737C23.8300886,9.2663126,23.6742921,9.1102114,23.482105699999998,9.1102114C23.2899208,9.1102114,23.1341233,9.2663126,23.1341228,9.4588737L23.1341228,12.461869C23.1278248,12.660679,23.2836776,12.826911,23.482104800000002,12.833026ZM42.991589000000005,20.919744L16.94900998,20.919744C16.69082925,20.919744,16.5,21.549585,16.5,21.853258C16.5,22.156931,16.71327975,22.798021,16.94900998,22.798021L23.897439,22.798021L22.1126246,25.868502C21.9664502,26.204638,22.0473838,26.596581,22.3146791,26.847004C22.6148901,27.015087,22.9897623,26.964701,23.2351494,26.723286L25.480198899999998,22.798023L34.898184,22.798023L36.952404,26.71204C37.138704000000004,26.994795,37.512434,27.083481,37.805521,26.91449C38.056238,26.717609,38.147625000000005,26.378819,38.030027000000004,26.082197L36.335014,22.775528L43.070164,22.775528C43.328342,22.775528,43.519172999999995,22.134438,43.519172999999995,21.830765C43.519172999999995,21.527092,43.249767,20.919744,42.991589000000005,20.919744ZM27.141537,12.833026C27.339965,12.826911,27.495817000000002,12.660679,27.489519,12.461868L27.489519,9.4588737C27.48952,9.2663126,27.333722,9.1102114,27.141537,9.1102114C26.949351,9.1102114,26.793554,9.2663126,26.793553,9.4588737L26.793553,12.461869C26.787255000000002,12.66068,26.943109,12.826912,27.141537,12.833026ZM25.311821000000002,12.833026C25.5102491,12.826911,25.6661024,12.660679,25.6598034,12.461868L25.6598034,9.4588737C25.6598034,9.2663126,25.5040064,9.1102114,25.311821899999998,9.1102114C25.119635600000002,9.1102114,24.963838600000003,9.2663126,24.963838600000003,9.4588737L24.963838600000003,12.461869C24.957541499999998,12.660679,25.1133938,12.826911,25.311821000000002,12.833026Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/caigoupeizhi.svg b/src/assets/system/caigoupeizhi.svg
new file mode 100644
index 0000000..56cbd1b
--- /dev/null
+++ b/src/assets/system/caigoupeizhi.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="89.5693359375" height="96" viewBox="0 0 89.5693359375 96"><defs><filter id="master_svg0_143_35986" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="-0.6666666666666666" y="-0.6666666666666666" width="2.3333333333333335" height="2.3333333333333335"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="0" dx="0"/><feGaussianBlur stdDeviation="8"/><feColorMatrix type="matrix" values="0 0 0 0 0.12895070016384125 0 0 0 0 0.29307788610458374 0 0 0 0 0.9107142686843872 0 0 0 0.5299999713897705 0"/><feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><clipPath id="master_svg1_143_35990"><rect x="29.78466796875" y="36" width="27" height="26" rx="0"/></clipPath></defs><path d="M44.78466796875,24.000000000000004L65.56927496875,36L65.56927496875,60L44.78466796875,72L24.00005836875,60L24.00005796875,36.000001L44.78466796875,24.000000000000004Z" fill="#496FFE" fill-opacity="1" filter="url(#master_svg0_143_35986)"/><g clip-path="url(#master_svg1_143_35990)"><path d="M38.936583953125,55.370050875000004C37.733132853125,55.370050875000004,36.759445153125,56.318214874999995,36.759445153125,57.477092875C36.759445153125,58.635968875,37.733132853125,59.584132875,38.936583953125,59.584132875C40.140035153125,59.584132875,41.124664353125,58.635968875,41.124664353125,57.477092875C41.124664353125,56.318214874999995,40.140035153125,55.370050875000004,38.936583953125,55.370050875000004ZM32.372314453125,38.513671875L32.372314453125,40.620712975000004L34.560395253125,40.620712975000004L38.498940453125,48.616956875L37.021982153125,51.198091875C36.846930553125,51.493078875,36.748476053125,51.840727875,36.748476053125,52.209476875C36.748476053125,53.368354875,37.733105153125,54.316516875,38.936556353125,54.316516875L52.065095453125,54.316516875L52.065095453125,52.209476875L39.396084753125,52.209476875C39.242918053125,52.209476875,39.122578653125004,52.093592875,39.122578653125004,51.946099875L39.155405553125,51.819678875L40.140035153125,50.102435875L48.290658453125,50.102435875C49.111179453125004,50.102435875,49.833271453125,49.670489875,50.205232453125,49.017316875L54.121921453125,42.179950975C54.209434453125,42.032456875,54.253204453125,41.853351075,54.253204453125,41.674271375000004C54.253204453125,41.094831975,53.760877453125005,40.620738275,53.159151453125,40.620738275L36.978240053125,40.620738275L35.949840753125,38.513697251678L32.372314453125,38.513671875ZM49.877016453125,55.370050875000004C48.673564453124996,55.370050875000004,47.699876453125,56.318214874999995,47.699876453125,57.477092875C47.699876453125,58.635968875,48.673564453124996,59.584132875,49.877016453125,59.584132875C51.080467453124996,59.584132875,52.065095453125,58.635968875,52.065095453125,57.477092875C52.065095453125,56.318214874999995,51.080467453124996,55.370050875000004,49.877016453125,55.370050875000004Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/caigoutaizhang.svg b/src/assets/system/caigoutaizhang.svg
new file mode 100644
index 0000000..a6cf257
--- /dev/null
+++ b/src/assets/system/caigoutaizhang.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="58.90625" viewBox="0 0 59.5 58.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35697"><rect x="18" y="0" width="23" height="23" rx="0"/></clipPath></defs><path d="M1.204819142818451,22.096379L28.69276814281845,38.307213000000004L58.29516614281845,22.096379L28.69276814281845,8L1.204819142818451,22.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,22.065809L28.43877614281845,38.737896L28.68361514281845,38.882288L59.39288714281845,22.065309L28.684561142818453,7.44229615L0.16870074281845082,22.065809ZM28.70192014281845,37.732138L2.240937742818451,22.12695L28.70097614281845,8.55770427L57.19744514281845,22.127449L28.70192014281845,37.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,22.80120277404785L0.5,41.83131777404785L28.692764,58.042150774047855L28.692764,39.01204077404785L0.5,22.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,58.906411774047854L29.192764,38.722777774047856L28.941999,38.578587774047854L-5.999999996841865e-8,21.93693918404785L0,42.12058077404785L29.192764,58.906411774047854ZM28.192764,39.30130377404785L28.192764,57.17788877404785L1,41.542054774047855L1,23.66546636404785L28.192764,39.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,22.80120277404785L59,41.12649377404785L88.5,58.00042177404785L88.5,38.26604677404785L59,22.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,58.86243677404785L89,37.96362277404785L88.732151,37.82320777404785L58.50000003,21.97454732404785L58.50000003,41.41651177404785L89,58.86243677404785ZM88,38.568469774047855L88,57.13840677404785L59.5,40.836475774047855L59.5,23.627858224047852L88,38.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35697)"><path d="M40.99999,13.416666C41.00259,13.384775,41.00259,13.352724,40.99999,13.320833C41.002308,13.287331,41.002308,13.253709,40.99999,13.220208L38.278324,1.4375043C38.059512999999995,0.59004736,37.294407,-0.0015301184,36.419159,0.0000048838556L22.580831500000002,0.0000048838556C21.6940155,0.000090580994,20.9230585,0.60853219,20.7168739,1.4710461L18.023958318,13.20104C18.021638496,13.234541,18.021638496,13.268163,18.023958318,13.301665C18.012162563,13.339105,18.0041366061,13.377629,18,13.416666L18,21.08333C18,22.141876,18.8581205,22.999996,19.916665899999998,22.999996L39.083326,22.999996C40.14187,22.999996,40.99999,22.141876,40.999992,21.08333L40.99999,13.416666ZM22.580831500000002,1.9166707L36.414367999999996,1.9166707L38.838949,12.458332L34.770826,12.458332C34.241554,12.458332,33.812493,12.887392,33.812494,13.416665L33.812494,15.812497L25.1874971,15.812497L25.1874971,13.416665C25.1874971,12.887392,24.7584372,12.458332,24.2291641,12.458332L20.1610408,12.458332L22.580831500000002,1.9166707ZM22.7916646,9.583334C22.7916641,9.0540609,23.2207246,8.625001,23.7499971,8.625001L35.249992,8.625001C35.778898,8.6255178,36.207388,9.0544252,36.207388,9.583333C36.207388,10.112241,35.778898,10.541149,35.249992,10.541666L23.7499976,10.541666C23.2207251,10.541666,22.7916651,10.112606,22.7916646,9.583334ZM24.2291641,5.2708354C24.2291651,4.7415628,24.6582246,4.3125029,25.1874971,4.3125029L33.812494,4.3125029C34.341768,4.3125029,34.770828,4.7415628,34.770828,5.2708359C34.770828,5.8001089,34.341768,6.2291689,33.812494,6.2291689L25.1874971,6.2291689C24.6582246,6.2291689,24.2291641,5.8001089,24.2291641,5.2708354Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/caigoutuihuo.svg b/src/assets/system/caigoutuihuo.svg
new file mode 100644
index 0000000..6b2df38
--- /dev/null
+++ b/src/assets/system/caigoutuihuo.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35706"><rect x="12.5" y="0" width="34.000003814697266" height="34" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35706)"><path d="M16.5,17.5C16.5,10.0479994,22.547999400000002,4,30,4C37.452,4,43.5,10.0479999,43.5,17.5C43.5,24.952,37.452,31,30,31C22.547999400000002,31,16.5,24.952,16.5,17.5ZM25.2099543,11.2335448C25.056938199999998,11.1590481,24.889226,11.1196365,24.719044699999998,11.118180800000001C24.4576359,11.118180800000001,24.2600451,11.2102261,24.1250448,11.3930907C23.965045,11.566371,23.8772473,11.7942061,23.8795905,12.0300455C23.8795905,12.2902269,23.9716368,12.4779997,24.1545,12.5945911C24.1946921,12.6422205,24.2439098,12.681428,24.2993183,12.7099552C24.812317800000002,13.0376368,25.309363400000002,13.3910923,25.789226499999998,13.7654095C25.875135399999998,13.8550005,25.9782276,13.9249544,26.0935907,13.9691372C26.1991358,14.026819,26.3292265,14.055046,26.4838629,14.055046C26.763681,14.046455,26.98459,13.9114552,27.149045,13.6500463C27.266969,13.4697084,27.327709,13.2579737,27.323318,13.0425463C27.319848,12.8229294,27.219160000000002,12.6161594,27.048409,12.4780006C26.492164600000002,11.9851937,25.874157,11.5668635,25.2099543,11.2335448ZM34.731136,11.2924538L29.478408,11.2924538C28.610726,11.2924538,28.177500000000002,11.648363100000001,28.177500000000002,12.3626356L28.177500000000002,19.944725C28.176272,20.042908,28.18609,20.138634,28.205727,20.234362C28.070726,20.349726,28.003225999999998,20.553452,28.003225999999998,20.841862C28.013044999999998,21.11186,28.070726,21.309452,28.176271,21.434633C28.292863,21.569633,28.500272000000002,21.637133,28.798499,21.637133C29.464908,21.637133,30.404999,21.487406,31.621223999999998,21.189178C31.861770999999997,21.140087,32.026225,21.059088,32.112133,20.943726C32.243669,20.79126,32.310976,20.593739,32.299906,20.392679C32.299906,20.17177,32.252043,19.997498,32.156316000000004,19.872315999999998C32.033533,19.737026,31.860347,19.658427,31.677678999999998,19.655088C31.157317,19.732407000000002,30.632043,19.804814999999998,30.100635,19.872315999999998L30.100635,17.455816L34.673452,17.455816C34.759361,17.455816,34.837906000000004,17.450908,34.905409,17.441088999999998C34.893873,17.462564,34.878954,17.482039999999998,34.861225000000005,17.498772000000002C34.521141,17.859035,34.158792,18.197606999999998,33.776316,18.512499C33.275587,18.193407999999998,32.749089999999995,17.895182,32.199270999999996,17.615363000000002C32.035903,17.54202,31.857872,17.507168,31.678905999999998,17.513499C31.417496999999997,17.513499,31.21009,17.590817,31.056679000000003,17.745455C30.902043,17.880454999999998,30.823497,18.082954,30.823497,18.352954C30.828218,18.505149,30.890499,18.649888,30.997768,18.757953999999998C31.051738999999998,18.809553,31.116205,18.848902000000002,31.186768999999998,18.873317999999998C32.266769,19.520091999999998,33.48177,20.369364,34.831768,21.419909C35.01586,21.604,35.246586,21.694817,35.527632,21.694817C35.766716,21.695692,35.992073000000005,21.583241,36.135132,21.39168C36.289076,21.227486,36.371994,21.009171,36.36586,20.78418C36.362389,20.564564,36.261703,20.357796,36.090952,20.219635C35.802544,19.968045,35.503088000000005,19.728727,35.195042,19.495544000000002C35.705585,19.197316999999998,36.115498,18.873317,36.424769999999995,18.526C36.533014,18.357194,36.592867,18.161924,36.597816,17.961454C36.611883,17.651581,36.456854,17.358437000000002,36.192816,17.195636999999998C36.041086,17.073852000000002,35.852282,17.007597,35.657722,17.007863999999998C35.753451999999996,16.853229,35.802544,16.645819,35.802544,16.385637L35.802544,12.3626366C35.802544,11.6483641,35.445406,11.2924547,34.731136,11.2924538ZM33.878181,13.664773L30.100636,13.664773L30.100636,13.1002264C30.100636,12.9468174,30.192681999999998,12.8695002,30.375545000000002,12.8695002L33.603271,12.8695002C33.786135,12.8695002,33.87818,12.9468174,33.87818,13.1002264L33.878181,13.664773ZM33.603271,15.864044L30.100636,15.864044L30.100636,15.02459L33.878181,15.02459L33.878181,15.646818C33.878181,15.791636,33.786135,15.864044,33.603271,15.864044ZM25.6296825,15.473772L24.2698641,15.473772C23.9507732,15.473772,23.724954099999998,15.546182,23.5899544,15.690999C23.4451365,15.844409,23.3727274,16.076363999999998,23.3727274,16.385635C23.3727274,16.723136,23.4402275,16.950181999999998,23.5752277,17.065544C23.6905913,17.248407,23.9225464,17.340454,24.2698641,17.340454L24.834409700000002,17.340454C24.9497738,17.340454,25.0074549,17.398136,25.0074549,17.513499L25.0074549,21.637135C25.0074549,21.714453,24.9546824,21.786861,24.847909899999998,21.854361C24.4527292,22.139252,24.0315437,22.386209,23.5899544,22.591951C23.4451365,22.698725,23.3727274,22.814087,23.3727274,22.939268C23.3771172,23.0942,23.4117188,23.246782,23.4745903,23.388451C23.6476359,23.697725,23.835408700000002,23.943178,24.0391369,24.126041C24.1385455,24.200905,24.260046,24.242634,24.3852277,24.242634C24.5752201,24.217705,24.7579012,24.153328,24.921546,24.053633C25.228364,23.907587,25.5204544,23.728407,25.7892284,23.518543C25.8849545,23.432632,25.9622736,23.388451,26.0211821,23.388451C26.132575,23.390455,26.2397785,23.431255,26.3243189,23.503817C27.153955,23.842543,28.572682999999998,24.010681,30.578046,24.010681L35.97559,24.010681C36.313091,23.991043,36.545048,23.900225,36.670227,23.735771C36.805227,23.61059,36.872726,23.363907,36.872726,22.99818C36.872726,22.67909,36.790501,22.453272,36.627274,22.317045C36.492271,22.201681,36.294682,22.144001,36.033272,22.144001C35.368092000000004,22.144001,34.566679,22.163635,33.6315,22.201681C32.551497999999995,22.239727,31.379454000000003,22.259361,30.115364,22.259361C28.996092,22.259361,28.114910000000002,22.191862,27.468138,22.056862C27.071728999999998,21.979544,26.874138000000002,21.8605,26.874138000000002,21.694817L26.874138000000002,16.601637C26.874138000000002,15.849319,26.4593201,15.472546,25.6296825,15.472546L25.6296825,15.473772Z" fill="#F56127" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/cangchuwuliu.svg b/src/assets/system/cangchuwuliu.svg
new file mode 100644
index 0000000..47ee791
--- /dev/null
+++ b/src/assets/system/cangchuwuliu.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="89.5693359375" height="96" viewBox="0 0 89.5693359375 96"><defs><filter id="master_svg0_143_36004" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="-0.6666666666666666" y="-0.6666666666666666" width="2.3333333333333335" height="2.3333333333333335"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="0" dx="0"/><feGaussianBlur stdDeviation="8"/><feColorMatrix type="matrix" values="0 0 0 0 0.12895070016384125 0 0 0 0 0.29307788610458374 0 0 0 0 0.9107142686843872 0 0 0 0.5299999713897705 0"/><feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><clipPath id="master_svg1_143_36007"><rect x="31.78466796875" y="34" width="27" height="27" rx="0"/></clipPath></defs><path d="M44.78466796875,24.000000000000004L65.56927496875,36L65.56927496875,60L44.78466796875,72L24.00005836875,60L24.00005796875,36.000001L44.78466796875,24.000000000000004Z" fill="#496FFE" fill-opacity="1" filter="url(#master_svg0_143_36004)"/><g clip-path="url(#master_svg1_143_36007)"><path d="M34.169981631875,44.43093495L43.148853271875,36.70824987C44.265293171875,35.80037498,45.805637171875,35.80037498,46.867416171875,36.70824987L55.794290171875005,44.43024925C56.165541171875,44.71509455,56.272196171874995,45.22674945,56.112884171874995,45.68034455C55.964262171875,46.11337375,55.561472171874996,46.40785775,55.103762171875005,46.41812375L34.914511871875,46.41812375C34.456565501875,46.40813475,34.053443121875,46.113611750000004,33.904727786875,45.680370350000004C33.711113065875,45.25040145,33.818446621275,44.74454685,34.169981631875,44.43024925L34.169981631875,44.43093495ZM50.745292171875,58.40140375L39.270291771875,58.40140375C38.554649371875,58.40620775,37.873565171875,58.094085750000005,37.409981271875,57.54887375C36.908443671875,57.007405750000004,36.624764471875,56.29965575,36.613481471875,55.561685749999995L36.613481471875,47.15793475C36.613481471875,46.41880975,36.878761971875,45.68103025,37.409981771875,45.17006015C37.889231671875,44.65906425,38.579761471875,44.31818965,39.270291771875,44.31818965L50.745292171875,44.31818965C52.233667171875,44.31818965,53.403446171875004,45.56693935,53.403446171875004,47.15724975L53.403446171875004,55.61905875C53.403446171875004,56.35615575,53.136822171875,57.09527975,52.606947171875,57.60625075C52.121288171875,58.11399275,51.449251171875005,58.40124275,50.746635171875,58.40140375L50.745292171875,58.40140375ZM42.511636771875004,49.99765575L47.505977171875,49.99765575L47.505977171875,46.02190495L42.511636771875004,46.02190495L42.511636771875004,49.99765575ZM38.739731771875,55.73175275L43.734072671875,55.73175275L43.734072671875,51.75668875L38.739072771875,51.75668875L38.739072771875,55.73243875L38.739731771875,55.73175275ZM46.231571171875004,55.73175275L51.224542171875,55.73175275L51.224542171875,51.75668875L46.229543171875,51.75668875L46.229543171875,55.73243875L46.230887171875,55.73243875L46.231571171875004,55.73175275Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/chanpinweihu.svg b/src/assets/system/chanpinweihu.svg
new file mode 100644
index 0000000..eeb2bd4
--- /dev/null
+++ b/src/assets/system/chanpinweihu.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35548"><rect x="12.5" y="0" width="34.000003814697266" height="34" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35548)"><path d="M28.938397000000002,16.1305256C34.699799999999996,16.1305256,39.376799,14.6742373,39.376799,12.8673234L39.376799,10.2632031C39.376799,8.4562893,34.699799999999996,7,28.938399,7C23.1769919,7,18.5,8.4562893,18.5,10.2632031L18.5,12.8673234C18.50033210215,14.663614299999999,23.1666999,16.1305256,28.938397000000002,16.1305256ZM44.276911,18.339863C44.276911,18.339863,42.873419,19.757969,42.724998,19.899082C42.583887000000004,20.040194,42.093805,20.025255,42.093805,20.025255C42.093805,20.025255,40.809180999999995,19.884143,40.623573,19.698537C40.437962999999996,19.512926,40.311792,18.168866,40.311792,18.168866C40.311792,18.168866,40.274605,17.797656,40.460212999999996,17.612047L42.019760000000005,16.0528297C42.019760000000005,16.0528297,42.198063000000005,15.8522825,41.93808,15.8522825C41.113977,15.8522825,39.443195,15.8668947,38.633708999999996,16.6763859L38.470348,16.8397465C37.512438,17.804958,37.453001,19.25295,38.225306,20.292540000000002L33.487556,24.584711C33.108707,24.963554,32.611326,25.988201,33.487556,26.8568C34.363788,27.73303,35.388435,27.235645,35.759642,26.8568C35.759642,26.8568,40.04418,22.119374999999998,40.036541,22.127012L40.043846,22.119711000000002C41.083433,22.899317,42.524117000000004,22.839883,43.489328,21.874662999999998L43.652695,21.711306999999998C44.439938999999995,20.924397,44.462188999999995,19.268223,44.462188999999995,18.429181C44.477458999999996,18.169201,44.276911,18.339866,44.276911,18.339863ZM34.749937,26.381657C34.311662,26.381657,33.955388,26.025389,33.955388,25.587109C33.955388,25.148829,34.311662,24.792561,34.749937,24.792561C35.187893,24.792561,35.544493,25.148829,35.544493,25.587109C35.544493,26.025389,35.188225,26.381657,34.749937,26.381657ZM32.203593,23.791481C31.17629,23.897064,30.078592999999998,23.954185,28.93873,23.954185C23.1773219,23.954185,18.510955571,22.497892999999998,18.510955571,20.690977L18.510955571,24.602633C18.510955571,26.398924,23.1773219,27.865839,28.949353000000002,27.865839C29.741912,27.865839,30.513885000000002,27.838282,31.256308,27.78582C31.17955,27.72587,31.106586,27.661226,31.037833,27.592243C29.979317,26.542686,30.580291000000003,25.304878,31.037833,24.847677L32.203593,23.791481Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M28.938066,21.99160385C31.111878,21.99160385,33.131288,21.78408435,34.803736,21.42881015L36.760063,19.65642495C36.216522,18.92463065,36.013987,18.02515645,36.169043,17.171171649999998C34.29274,17.73429655,31.744064,18.079609650000002,28.9384,18.079609650000002C23.176991,18.079609650000002,18.5,16.62332105,18.5,14.81640625L18.5,18.72806505C18.5,20.524686850000002,23.1663661,21.99159955,28.938066,21.99160385Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/chukuguanli.svg b/src/assets/system/chukuguanli.svg
new file mode 100644
index 0000000..6c8f0e9
--- /dev/null
+++ b/src/assets/system/chukuguanli.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="61.40625" viewBox="0 0 59.5 61.40625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35869"><rect x="17" y="0" width="27" height="27" rx="0"/></clipPath></defs><path d="M1.204819142818451,24.596379L28.69276814281845,40.807213000000004L58.29516614281845,24.596379L28.69276814281845,10.5L1.204819142818451,24.596379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,24.565809L28.43877614281845,41.237896L28.68361514281845,41.382288L59.39288714281845,24.565309L28.684561142818453,9.94229615L0.16870074281845082,24.565809ZM28.70192014281845,40.232138L2.240937742818451,24.62695L28.70097614281845,11.05770427L57.19744514281845,24.627449L28.70192014281845,40.232138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,25.30120277404785L0.5,44.33131777404785L28.692764,60.542150774047855L28.692764,41.51204077404785L0.5,25.30120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,61.406411774047854L29.192764,41.222777774047856L28.941999,41.078587774047854L-5.999999996841865e-8,24.43693918404785L0,44.62058077404785L29.192764,61.406411774047854ZM28.192764,41.80130377404785L28.192764,59.67788877404785L1,44.042054774047855L1,26.16546636404785L28.192764,41.80130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,25.30120277404785L59,43.62649377404785L88.5,60.50042177404785L88.5,40.76604677404785L59,25.30120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,61.36243677404785L89,40.46362277404785L88.732151,40.32320777404785L58.50000003,24.47454732404785L58.50000003,43.91651177404785L89,61.36243677404785ZM88,41.068469774047855L88,59.63840677404785L59.5,43.336475774047855L59.5,26.127858224047852L88,41.068469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35869)"><path d="M28.74531903125,25.271427375C28.39732503125,25.271427375,28.17831903125,25.178430375,28.058323031249998,24.938408375C27.938325031250002,24.695407375,27.99530403125,23.342403375,27.99530403125,22.961397375L27.99530403125,16.871421375C27.99530403125,15.995425375,28.04933103125,15.815414375,28.95533503125,15.815414375L35.04831503125,15.815414375C37.12731503125,15.815414375,36.860321031249995,15.620430375,36.860321031249995,18.101423375L36.860321031249995,24.161420375C36.860321031249995,25.046407375,36.84832403125,25.271427375,35.91832703125,25.268419375L33.90832903125,25.268419375C33.50032403125,22.874410375,30.17331203125,22.874410375,29.76530603125,25.268419375C29.42633003125,25.268419375,29.08432103125,25.268419375,28.74531903125,25.271427375ZM38.03632503125,25.259428375C38.50434303125,23.054420375,41.04832603125,22.958418375,41.93331303125,24.536441375C42.08932903125,24.812425375,42.07432703125,24.992408375,42.18831203125,25.259428375C43.53232603125,25.415416375,43.35833203125,24.809417375,43.35833203125,23.711410375C43.35833203125,23.033430375,43.448324031249996,21.659410375,43.22032403125,21.119409375C42.98331103125,20.549430375,42.24231303125,19.649438375,41.837313031250005,19.109439375C41.738329031250004,18.977419375,41.633308031249996,18.824411375,41.54031203125,18.716411375C41.32731803125,18.470407375,41.177315031250004,18.197424375,40.68830903125,18.179416375L37.958332031249995,18.188406375C37.52933703125,18.248417375,37.44831103125,18.575422375,37.44831103125,19.031419375L37.44831103125,24.494434375C37.44831103125,24.926408375,37.589323031250004,25.259428375,38.03632503125,25.259428375L38.03632503125,25.259428375ZM42.359327031250004,21.722429375C41.498308031250005,21.731420375,40.046320031250005,21.746423375,39.221317031249995,21.719423375L39.221317031249995,19.364412375C39.60532903125,19.340421375,40.21731003125,19.337413375,40.59831803125,19.358427375C40.88632403125,19.373432375,41.07529803125,19.751432375,41.28831903125,20.048429375C41.53730603125,20.396423375,42.34730703125,21.407421375,42.359327031250004,21.722429375ZM33.16432603125,25.262409375C33.35630803125,26.084432375,32.77432803125,26.753416375,32.13832803125,26.894432375C31.31329903125,27.080427375,30.66532503125,26.516433375,30.512316031250002,25.877424375C30.30831203125,25.031431375,30.88730903125,24.401416375,31.532330031249998,24.236408375C32.35730503125,24.029426375,33.01432103125,24.629411375,33.16432603125,25.262409375ZM41.46231803125,25.427415375C41.53730803125,26.228426375,40.94931803125,26.855409375,40.23832703125,26.918424375C39.44032503125,26.993415375,38.81331203125,26.399412375,38.75332603125,25.676426375C38.68432403125,24.866426375,39.28133003125,24.281417375,40.00431803125,24.209406375C40.77231603125,24.134418375,41.39632203125,24.737409375,41.46231803125,25.427415375ZM17.46533203125,6.377412775L17.46533203125,26.912439375L22.15431403125,26.912439375L22.15431403125,10.127406375L38.62431103125,10.127406375L38.62431103125,13.475406375L43.313322031249996,13.475406375L43.313322031249996,6.437397475C43.313322031249996,6.185406175,42.82431403125,6.050406475,42.62632403125,5.960415375L41.40832103125,5.384397475C41.23732903125,5.309382875,41.153320031250004,5.246392275,40.98233003125,5.171403375C40.667322031249995,5.030391675,40.46331803125,4.928403875,40.14833603125,4.790397675C38.65732603125,4.127394675,36.75232103125,3.122409775,35.270327031250005,2.486407075L30.752310031249998,0.347395155C29.94832203125,-0.042601921,30.131310031250003,-0.04560776800000001,29.51632203125,0.230403925L25.47230913125,2.273412675C25.19932893125,2.411418875,24.938320131250002,2.519418475,24.650311931250002,2.669421475L18.20933491125,5.903409975C18.03531152125,5.993427275,17.465332081541415,6.149415475,17.46533203125,6.377412775ZM23.54033093125,19.565410375L26.42632583125,19.565410375L26.42632583125,22.061432375L23.54033093125,22.061432375L23.54033093125,19.565410375ZM23.54033093125,16.235420375L26.42632583125,16.235420375L26.42632583125,18.677415375L23.54033093125,18.677415375L23.54033093125,16.235420375L23.54033093125,16.235420375Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/fahuotaizhang.svg b/src/assets/system/fahuotaizhang.svg
new file mode 100644
index 0000000..67e1b3f
--- /dev/null
+++ b/src/assets/system/fahuotaizhang.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="62.90625" viewBox="0 0 59.5 62.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35626"><rect x="15" y="0" width="29" height="29" rx="0"/></clipPath></defs><path d="M1.204819142818451,26.096379L28.69276814281845,42.307213000000004L58.29516614281845,26.096379L28.69276814281845,12L1.204819142818451,26.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,26.065809L28.43877614281845,42.737896L28.68361514281845,42.882288L59.39288714281845,26.065309L28.684561142818453,11.44229615L0.16870074281845082,26.065809ZM28.70192014281845,41.732138L2.240937742818451,26.12695L28.70097614281845,12.55770427L57.19744514281845,26.127449L28.70192014281845,41.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,26.80120277404785L0.5,45.83131777404785L28.692764,62.042150774047855L28.692764,43.01204077404785L0.5,26.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,62.906411774047854L29.192764,42.722777774047856L28.941999,42.578587774047854L-5.999999996841865e-8,25.93693918404785L0,46.12058077404785L29.192764,62.906411774047854ZM28.192764,43.30130377404785L28.192764,61.17788877404785L1,45.542054774047855L1,27.66546636404785L28.192764,43.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,26.80120277404785L59,45.12649377404785L88.5,62.00042177404785L88.5,42.26604677404785L59,26.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,62.86243677404785L89,41.96362277404785L88.732151,41.82320777404785L58.50000003,25.97454732404785L58.50000003,45.41651177404785L89,62.86243677404785ZM88,42.568469774047855L88,61.13840677404785L59.5,44.836475774047855L59.5,27.627858224047852L88,42.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35626)"><path d="M21.7729373375,2.85937521606684C24.1931619375,2.85937521606684,26.1551654375,4.8214065999999995,26.1551654375,7.2416601C26.1551654375,9.661829000000001,24.1932191375,11.6238594,21.772936837499998,11.6238594C19.3526830375,11.6238594,17.3906514375,9.661829000000001,17.3906514375,7.2416601C17.3906514375,4.8214065999999995,19.3526828375,2.859375,21.7729373375,2.85937521606684ZM23.9577636375,6.8265414L23.9577636375,5.148194800000001L21.1443958375,7.656723L19.5880813375,6.2642415L19.5880813375,7.9425879L21.1443958375,9.3350978L23.9577636375,6.8265414ZM41.402877437499995,17.636632C41.2427544375,17.645353,41.056009437499995,17.649941,40.8424184375,17.649941L35.9334904375,17.649941C35.8089674375,17.649941,35.684467437500004,17.587636,35.5599444375,17.463169999999998C35.4354194375,17.338504,35.3731444375,17.231906000000002,35.3731444375,17.142895L35.3731444375,17.116274C35.3555274375,16.244659,35.346351437500005,15.453276,35.346351437500005,14.741616L35.346351437500005,12.3138857C35.346351437500005,12.1182203,35.426643437500005,11.9358091,35.5866224375,11.7669363C35.7466604375,11.5979471,35.942268437500005,11.5136681,36.1735594375,11.5136681C36.1913474375,11.5136681,36.3247334375,11.504632,36.5738674375,11.4868193C36.8228604375,11.4689779,37.1295984375,11.4822874,37.4943634375,11.5267506C37.8590144375,11.5711298,38.245813437500004,11.6691179,38.654903437499996,11.8202353C39.0638734375,11.9714098,39.4463124375,12.216011,39.802125437499996,12.5540142C40.3535234375,13.123253,40.744798437499995,13.812456,40.9760074375,14.62168C41.2072714375,15.430904,41.4208314375,16.271338,41.6162684375,17.142867000000003C41.6162684375,17.178466999999998,41.620914437500005,17.205171999999997,41.6296654375,17.223014C41.6385594375,17.240686,41.6428904375,17.267477,41.6428904375,17.303047C41.6429194375,17.516666999999998,41.5630284375,17.627825,41.4029064375,17.636662L41.402877437499995,17.636632ZM43.497190437499995,17.956765C43.363775437499996,16.951846,43.1280674375,15.924557,42.7901764375,14.875204C42.4520304375,13.825795,41.9452974375,12.8384638,41.2692894375,11.9139185C40.8958854375,11.3980083,40.4334694375,10.9533787,39.881877437499995,10.5799184C39.3335594375,10.207787,38.7423764375,9.9031267,38.1211204375,9.672535400000001C37.4985274375,9.4413004,36.867096437499995,9.2769294,36.226747437499995,9.1791105C35.5864524375,9.0812922,34.9727214375,9.0591178,34.3857844375,9.1124163C34.1902884375,9.1300879,34.0256614375,9.2681208,33.8922464375,9.5259213C33.7588554375,9.783721,33.6922204375,10.0105953,33.6922204375,10.2061749L33.6922204375,23.066061C33.6922204375,23.386337,33.8077664375,23.661949,34.0390304375,23.893127C34.2703224375,24.124277,34.5457364375,24.239882,34.8660414375,24.239882L35.346351437500005,24.239882C35.346351437500005,23.795309,35.4308054375,23.372713,35.5998214375,22.972548C35.7688924375,22.572323,36.0000154375,22.221321,36.2935274375,21.918835C36.5870934375,21.616402,36.9293154375,21.376131,37.320705437499996,21.198366C37.7119484375,21.020514,38.1387654375,20.931503,38.6011794375,20.931503C39.0637624375,20.931503,39.503860437499995,20.993809,39.9219534375,21.118334C40.3399624375,21.242828,40.7047254375,21.438437,41.015682437500004,21.705215C41.3270644375,21.972076,41.576114437499996,22.318859,41.762888437499996,22.74576C41.949518437500004,23.172689,42.042860437499996,23.688599,42.042860437499996,24.29324L43.136875437499995,24.29324C43.243528437500004,24.29324,43.3281514375,24.239828,43.3904534375,24.13323C43.4524744375,24.026405,43.5060004375,23.897461,43.5502914375,23.746147C43.5943754375,23.597946,43.625642437500005,23.446234,43.6437514375,23.292681C43.661592437500005,23.141449,43.670429437500005,23.012423,43.670429437500005,22.905769C43.670429437500005,22.354401,43.6749284375,21.642796,43.6837384375,20.771267C43.6928004375,19.900023,43.6303824375,18.961798,43.496967437500004,17.956794000000002L43.497190437499995,17.956794000000002L43.497190437499995,17.956765ZM38.734764437500004,22.612343C39.197120437500004,22.612343,39.5974274375,22.7813,39.935373437500004,23.11936C40.273376437500005,23.457363,40.4423064375,23.857302,40.4423064375,24.319971C40.4423064375,24.800087,40.2733214375,25.2092,39.935373437500004,25.547007C39.5974274375,25.885094,39.1972884375,26.054052,38.734764437500004,26.054052C38.254676437499995,26.054052,37.8498684375,25.885094,37.5207824375,25.547007C37.1917614375,25.209059,37.0272444375,24.800114,37.0272444375,24.319971C37.0272444375,23.857357,37.1917874375,23.457333,37.5207824375,23.11936C37.8498654375,22.7813,38.2544764375,22.61237,38.734764437500004,22.61237L38.734764437500004,22.612343ZM20.3789520375,22.585806C19.8986959375,22.585806,19.4939141375,22.754765,19.1649737375,23.092569C18.835835437500002,23.430544,18.6714358375,23.839544,18.6714358375,24.320026C18.6714358375,24.782158,18.8358349375,25.182467,19.1649737375,25.520525C19.4939708375,25.858528,19.8986964375,26.027487,20.3789520375,26.027487C20.8592076375,26.027487,21.263820137499998,25.858501,21.5929026375,25.520554C21.9220414375,25.182493,22.0863556375,24.782356,22.0863556375,24.320026C22.0863556375,23.839769,21.9218993375,23.430487,21.5929026375,23.092569C21.2638206375,22.754765,20.8591795375,22.585806,20.3789520375,22.585806ZM27.1951694375,5.8573070000000005C27.3276244375,6.328613799999999,27.3944584375,6.8189235,27.3944584375,7.3281794C27.3944584375,8.1049209,27.2467114375,8.8312807,26.9510474375,9.506775900000001C26.6555254375,10.182272399999999,26.2544524375,10.773316900000001,25.7479444375,11.279911C25.2412948375,11.7864199,24.6504764375,12.1834698,23.9748087375,12.470439C23.2992000375,12.7574387,22.5816755375,12.900966,21.8216157375,12.900966C21.044789837499998,12.900966,20.318656937500002,12.7574387,19.6431894375,12.470439C18.9676652375,12.1834126,18.3767049375,11.7864199,17.8700547375,11.279911C17.3634042375,10.773316900000001,16.9623885375,10.182272399999999,16.6669227375,9.506775900000001C16.3713153575,8.8312807,16.2235116975,8.105062499999999,16.2235116975,7.3281794C16.2235116975,7.2433033,16.2257206475,7.1590791,16.2292040575,7.075222C15.9749726075,7.3872271,15.7748329975,7.7281752,15.6298046675,8.098464C15.4696249815,8.507465400000001,15.3896484375,8.9255304,15.3896484375,9.3524303L15.3896484375,23.226042C15.3896484375,23.564045,15.4874668125,23.821957,15.6831034975,23.999754C15.8789101275,24.177435,16.1278457075,24.266588,16.4301931375,24.266588L17.0438944375,24.266588C17.0438944375,23.128279,17.3330446375,22.278898,17.9110057375,21.718695C18.4888818375,21.158379,19.3205645375,20.87809,20.405487037500002,20.87809C21.5439634375,20.87809,22.3800354375,21.180494,22.9134769375,21.785387C23.4470596375,22.390112,23.7139778375,23.217234,23.7139778375,24.266588L30.9974874375,24.266588C31.282276437500002,24.266588,31.5265384375,24.16877,31.7312084375,23.973017C31.9357104375,23.777466,32.038061437500005,23.52853,32.038061437500005,23.226097L31.9846784375,5.8573070000000005L27.1951694375,5.8573070000000005Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/gongxu.svg b/src/assets/system/gongxu.svg
new file mode 100644
index 0000000..8d313c1
--- /dev/null
+++ b/src/assets/system/gongxu.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="61.90625" viewBox="0 0 59.5 61.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35769"><rect x="15.5" y="0" width="28" height="28" rx="0"/></clipPath></defs><path d="M1.204819142818451,25.096379L28.69276814281845,41.307213000000004L58.29516614281845,25.096379L28.69276814281845,11L1.204819142818451,25.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,25.065809L28.43877614281845,41.737896L28.68361514281845,41.882288L59.39288714281845,25.065309L28.684561142818453,10.44229615L0.16870074281845082,25.065809ZM28.70192014281845,40.732138L2.240937742818451,25.12695L28.70097614281845,11.55770427L57.19744514281845,25.127449L28.70192014281845,40.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,25.80120277404785L0.5,44.83131777404785L28.692764,61.042150774047855L28.692764,42.01204077404785L0.5,25.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,61.906411774047854L29.192764,41.722777774047856L28.941999,41.578587774047854L-5.999999996841865e-8,24.93693918404785L0,45.12058077404785L29.192764,61.906411774047854ZM28.192764,42.30130377404785L28.192764,60.17788877404785L1,44.542054774047855L1,26.66546636404785L28.192764,42.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,25.80120277404785L59,44.12649377404785L88.5,61.00042177404785L88.5,41.26604677404785L59,25.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,61.86243677404785L89,40.96362277404785L88.732151,40.82320777404785L58.50000003,24.97454732404785L58.50000003,44.41651177404785L89,61.86243677404785ZM88,41.568469774047855L88,60.13840677404785L59.5,43.836475774047855L59.5,26.627858224047852L88,41.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35769)"><path d="M31.250000999999997,28.000002L18.6675,28.000002C17.88696605,28.000973,17.2528940293,27.370031,17.25,26.589502L17.25,5.7189999C17.253842816,4.9388809,17.88735223,4.3084998,18.6675,4.3084998L20.7045,4.3084998L20.7045,10.0485L35.901500999999996,10.0485L35.901500999999996,4.3084998L37.938501,4.3084998C38.720751,4.3084998,39.356003,4.9419994,39.356003,5.7189994L39.356003,12.726C35.280792000000005,11.314371,30.784750000000003,13.082648,28.763004000000002,16.892187C26.7412615,20.701725,27.79683,25.416275,31.250000999999997,28.000002ZM34.519001,8.6047497L22.0852499,8.6047497L22.0852499,3.9567502C22.0852499,2.9697499,22.7835007,2.1682501,23.6410003,2.1682501L25.24575,2.1682501C25.8197508,0.85225004,26.9975014,0,28.303,0C29.606749999999998,0,30.784501,0.85225004,31.3585,2.1682501L32.965001,2.1682501C33.822500000000005,2.1682501,34.519001,2.9697502,34.519001,3.9567502L34.519001,8.6047497ZM20.7045,15.058749C20.7045,15.44375,21.0195003,15.77625,21.4045005,15.77625L27.60125,15.77625C27.997515999999997,15.77625,28.318751,15.455014,28.318751,15.058749C28.318751,14.662486,27.997515999999997,14.34125,27.60125,14.34125L21.40625,14.34125C21.016150500000002,14.349814,20.7044065,14.668555,20.7045,15.058749ZM20.7045,20.79525C20.7045,21.18025,21.023,21.512751,21.416750399999998,21.512751L26.21,21.512751C26.602631600000002,21.50613,26.9185143,21.187918,26.9222498,20.79525C26.9222498,20.41025,26.6037502,20.077749,26.21,20.077749L21.4150004,20.077749C21.0223703,20.084372,20.7064886,20.402582,20.7027502,20.79525L20.7045,20.79525ZM25.1932502,6.454C25.7770567,6.4434648,26.241730699999998,5.9615531,26.231000899999998,5.3777499C26.2407513,4.7946243,25.7763624,4.3137889,25.1932502,4.3032494C24.610827,4.3147411,24.1474919,4.7952948,24.1572504,5.3777499C24.1572504,5.9727497,24.6209998,6.454,25.1932502,6.454ZM31.411,6.454C31.994120000000002,6.442512,32.457737,5.9608827,32.447001,5.3777499C32.456759,4.7952943,31.993423999999997,4.3147411,31.411,4.3032494C30.828578,4.3147411,30.365243,4.7952948,30.375000999999997,5.3777499C30.375000999999997,5.9727497,30.838752,6.454,31.411,6.454ZM36.500001999999995,28.000002C32.634008,28.000002,29.500000999999997,24.865995,29.500000999999997,21.000002C29.500000999999997,17.134008,32.634008,14.000001,36.500001999999995,14.000001C40.365995,14.000001,43.500001999999995,17.134008,43.500001999999995,21.000002C43.500001999999995,24.865995,40.365995,28.000002,36.500001999999995,28.000002ZM40.73675,18.669003L40.73675,15.795501L36.8675,15.795501L36.8675,16.747499L35.17,16.747499L35.17,24.4055L36.858749,24.4055L36.858749,25.845751L40.721001,25.845751L40.721001,22.902248L36.858749,22.902248L36.858749,23.44475L36.0275,23.44475L36.0275,17.678499L36.867498,17.678499L36.867498,18.669001L40.738501,18.669001L40.73675,18.669003ZM34.720248999999995,20.02C34.421001000000004,19.460003,34.424501,19.451252,34.424501,19.451252C34.424501,19.451252,33.392002000000005,19.775002,33.199501,18.667252L32.601001,18.667252C32.601001,18.667252,32.436502000000004,19.776752,31.381251,19.447752L31.066252,20.035753C31.066252,20.035753,31.892252,20.683254,31.066252,21.558254L31.386499999999998,22.149754C31.386499999999998,22.149754,32.298251,21.708754,32.597502,22.912754L33.203001,22.912754C33.203001,22.912754,33.392002000000005,21.806753,34.417501,22.134005C34.709751,21.574005,34.715002,21.570503,34.715002,21.570503C34.715002,21.570503,33.939752999999996,20.821505,34.720248999999995,20.02Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/gongyingshangdangan.svg b/src/assets/system/gongyingshangdangan.svg
new file mode 100644
index 0000000..39e4859
--- /dev/null
+++ b/src/assets/system/gongyingshangdangan.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="62.90625" viewBox="0 0 59.5 62.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35686"><rect x="13.5" y="0" width="32" height="32" rx="0"/></clipPath></defs><path d="M1.204819142818451,26.096379L28.69276814281845,42.307213000000004L58.29516614281845,26.096379L28.69276814281845,12L1.204819142818451,26.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,26.065809L28.43877614281845,42.737896L28.68361514281845,42.882288L59.39288714281845,26.065309L28.684561142818453,11.44229615L0.16870074281845082,26.065809ZM28.70192014281845,41.732138L2.240937742818451,26.12695L28.70097614281845,12.55770427L57.19744514281845,26.127449L28.70192014281845,41.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,26.80120277404785L0.5,45.83131777404785L28.692764,62.042150774047855L28.692764,43.01204077404785L0.5,26.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,62.906411774047854L29.192764,42.722777774047856L28.941999,42.578587774047854L-5.999999996841865e-8,25.93693918404785L0,46.12058077404785L29.192764,62.906411774047854ZM28.192764,43.30130377404785L28.192764,61.17788877404785L1,45.542054774047855L1,27.66546636404785L28.192764,43.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,26.80120277404785L59,45.12649377404785L88.5,62.00042177404785L88.5,42.26604677404785L59,26.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,62.86243677404785L89,41.96362277404785L88.732151,41.82320777404785L58.50000003,25.97454732404785L58.50000003,45.41651177404785L89,62.86243677404785ZM88,42.568469774047855L88,61.13840677404785L59.5,44.836475774047855L59.5,27.627858224047852L88,42.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35686)"><path d="M25.178437199999998,6.013828425L25.162812199999998,6.013828425C25.055625900000003,5.080703315,24.4187503,4.361328125,23.6415634,4.361328125L18.1996875,4.361328125C17.42218757,4.361328125,16.78562498,5.081015645,16.678437473,6.013828425L16.65625,6.013828425L16.65625,12.286016925L16.6628124719,12.286016925L16.6628124719,14.008203525C16.66187501,14.038516025,16.65625,14.066953625,16.65625,14.097578025L16.65625,25.993517125L16.678437473,25.993517125C16.78562498,26.926641125,17.42218739,27.646017125,18.1996875,27.646332125L23.6415634,27.646332125C24.4190626,27.646332125,25.055625900000003,26.926641125,25.162812199999998,25.993517125L25.178437199999998,25.993517125L25.178437199999998,25.849769125L25.1849995,25.849769125L25.1849995,12.170390625L25.178437199999998,12.170390625L25.178437199999998,10.595078025C25.1793747,10.566952725,25.1849995,10.540703324999999,25.1849995,10.512577024999999L25.1849995,6.287265825C25.1849995,6.259141125,25.1790628,6.232890725,25.178437199999998,6.204765825L25.178437199999998,6.013828425ZM33.707815,6.013828425L33.692503,6.013828425C33.585001,5.080703315,32.948439,4.361328125,32.170938,4.361328125L26.729062,4.361328125C25.951875700000002,4.361328125,25.3149996,5.081015645,25.207813299999998,6.013828425L25.185626,6.013828425L25.185626,12.286016925L25.192188299999998,12.286016925L25.192188299999998,14.008203525C25.1912498,14.038516025,25.185626,14.066953625,25.185626,14.097578025L25.185626,25.993517125L25.207813299999998,25.993517125C25.3149996,26.926641125,25.951875700000002,27.646017125,26.729062,27.646332125L32.170937,27.646332125C32.948437,27.646332125,33.584998999999996,26.926641125,33.692501,25.993517125L33.707813,25.993517125L33.707813,25.849769125L33.714376,25.849769125L33.714376,12.170390625L33.707813,12.170390625L33.707813,10.595078025C33.708752000000004,10.566952725,33.714376,10.540703324999999,33.714376,10.512577024999999L33.714376,6.287265825C33.714376,6.259141125,33.708752000000004,6.232890725,33.707813,6.204765825L33.707815,6.013828425ZM27.336877,7.185703525L31.563439000000002,7.185703525L31.563439000000002,17.928203125L27.336876,17.928203125L27.336877,7.185703525ZM30.604689999999998,24.859453125C29.890158,25.271952125,29.009847,25.271952125,28.295313999999998,24.859453125C27.580841,24.446863125,27.140695,23.684502125,27.140627000000002,22.859453125C27.140627000000002,22.034452125,27.580939,21.271953125,28.295313999999998,20.859453125C29.009847,20.446957125,29.890158,20.446957125,30.604689999999998,20.859453125C31.319263,21.271946125,31.759445,22.034368125,31.759377,22.859453125C31.759377,23.684454125,31.319376,24.446953125,30.604689999999998,24.859453125Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M29.988359475,21.926954125C29.655124775,21.734768125,29.244719565,21.734768125,28.911484715,21.926954125C28.578357715,22.119329125,28.373121261604,22.474771125,28.373046875,22.859453125C28.373046875,23.454141125,28.854922355,23.936329125,29.449609775,23.936329125C30.044298175,23.936329125,30.526485475,23.454141125,30.526485475,22.859453125C30.526752475,22.474760125,30.321571475,22.119207125,29.988359475,21.926954125ZM42.343673875,10.512578525L42.343673875,6.287265825C42.343673875,6.259141125,42.338047875,6.232890725,42.337108875,6.204765825L42.337108875,6.013828425L42.321483875,6.013828425C42.214296875,5.080703315,41.577421875,4.361328125,40.800234875,4.361328125L35.358357875,4.361328125C34.580858675,4.361328125,33.944295875,5.081015645,33.836795775,6.013828425L33.814920875,6.013828425L33.814920875,12.286016925L33.821484075,12.286016925L33.821484075,14.008203525C33.820545175,14.038516025,33.814920875,14.066953625,33.814920875,14.097578025L33.814920875,25.993517125L33.836795775,25.993517125C33.944295875,26.926641125,34.580858675,27.646017125,35.358045575,27.646332125L40.799920875,27.646332125C41.577108875,27.646332125,42.213984875,26.926641125,42.321170875,25.993517125L42.336795875,25.993517125L42.336795875,25.849769125L42.343668875,25.849769125L42.343668875,12.170390625L42.337107875,12.170390625L42.337107875,10.595078025C42.338045875,10.566952725,42.343668875,10.541015125000001,42.343673875,10.512578525ZM35.965858475,7.185703525L40.192420874999996,7.185703525L40.192420874999996,17.928203125L35.965858475,17.928203125L35.965858475,7.185703525ZM39.233984875000004,24.859453125C38.519452875,25.271953125,37.639140175,25.271953125,36.924609175,24.859453125C36.210134475000004,24.446863125,35.769990875,23.684502125,35.769920875,22.859453125C35.769920875,22.034452125,36.210234675,21.271953125,36.924609175,20.859453125C37.639140175,20.446957125,38.519452875,20.446957125,39.233984875000004,20.859453125C39.948458875,21.272045125,40.388600875,22.034408125,40.388672875,22.859453125C40.388672875,23.684454125,39.948671875,24.446953125,39.233984875000004,24.859453125Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M38.6179295875,21.92148398C38.2848072875,21.729297638,37.8744889475,21.729297638,37.5413666975,21.92148398C37.2082405375,22.11385918,37.003004074111,22.46930122,37.0029296875,22.85398475C37.0029296875,23.23867225,37.2082424475,23.59398465,37.5413666975,23.78648545C38.0563736875,24.08376885,38.7148630875,23.90727045,39.0121481875,23.39226535C39.3094334875,22.87726005,39.1329366875,22.21876907,38.6179295875,21.92148398Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/gongyingshangwanglai.svg b/src/assets/system/gongyingshangwanglai.svg
new file mode 100644
index 0000000..69de69e
--- /dev/null
+++ b/src/assets/system/gongyingshangwanglai.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="62.90625" viewBox="0 0 59.5 62.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35715"><rect x="16" y="0" width="30" height="30" rx="0"/></clipPath></defs><path d="M1.204819142818451,26.096379L28.69276814281845,42.307213000000004L58.29516614281845,26.096379L28.69276814281845,12L1.204819142818451,26.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,26.065809L28.43877614281845,42.737896L28.68361514281845,42.882288L59.39288714281845,26.065309L28.684561142818453,11.44229615L0.16870074281845082,26.065809ZM28.70192014281845,41.732138L2.240937742818451,26.12695L28.70097614281845,12.55770427L57.19744514281845,26.127449L28.70192014281845,41.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,26.80120277404785L0.5,45.83131777404785L28.692764,62.042150774047855L28.692764,43.01204077404785L0.5,26.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,62.906411774047854L29.192764,42.722777774047856L28.941999,42.578587774047854L-5.999999996841865e-8,25.93693918404785L0,46.12058077404785L29.192764,62.906411774047854ZM28.192764,43.30130377404785L28.192764,61.17788877404785L1,45.542054774047855L1,27.66546636404785L28.192764,43.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,26.80120277404785L59,45.12649377404785L88.5,62.00042177404785L88.5,42.26604677404785L59,26.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,62.86243677404785L89,41.96362277404785L88.732151,41.82320777404785L58.50000003,25.97454732404785L58.50000003,45.41651177404785L89,62.86243677404785ZM88,42.568469774047855L88,61.13840677404785L59.5,44.836475774047855L59.5,27.627858224047852L88,42.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35715)"><path d="M41.17005759375,2.549529299C38.500059593749995,2.549529299,36.340057593750004,3.98952925,36.340057593750004,5.75952935C36.340057593750004,6.95952895,37.30005659375,7.97952935,38.74005659375,8.549529549999999C38.68005559375,8.93952985,38.53005559375,9.35952945,38.290056593749995,9.80952885C38.290056593749995,9.80952885,39.64005659375,9.689528450000001,40.33005759375,8.939528450000001C40.60005759375,8.96952815,40.870057593750005,8.99952885,41.17005759375,8.99952885C43.84005559375,8.99952885,46.000059593749995,7.55952835,46.000059593749995,5.78952885C46.000059593749995,3.98952875,43.84005559375,2.549528852,41.17005759375,2.549529299ZM39.22005659375,6.20952915C38.83005759375,6.20952915,38.53005759375,5.90952925,38.53005759375,5.51952915C38.53005759375,5.12952945,38.83005759375,4.82952905,39.22005659375,4.82952905C39.61005759375,4.82952905,39.91005659375,5.12952945,39.91005659375,5.51952915C39.91005659375,5.87952925,39.58005759375,6.20952915,39.22005659375,6.20952915ZM41.290058593750004,6.20952915C40.90005659375,6.20952915,40.60005759375,5.90952925,40.60005759375,5.51952915C40.60005759375,5.12952945,40.90005659375,4.82952905,41.290058593750004,4.82952905C41.68005759375,4.82952905,41.98005659375,5.12952945,41.98005659375,5.51952915C41.98005659375,5.87952925,41.65005859375,6.20952915,41.290058593750004,6.20952915ZM43.36005759375,6.20952915C42.97005659375,6.20952915,42.67005759375,5.90952925,42.67005759375,5.51952915C42.67005759375,5.12952945,42.97005659375,4.82952905,43.36005759375,4.82952905C43.75005759375,4.82952905,44.050058593749995,5.12952945,44.050058593749995,5.51952915C44.050058593749995,5.87952925,43.72005859375,6.20952915,43.36005759375,6.20952915ZM25.66005799375,19.67952925C26.14005859375,19.52953125,26.620058593750002,19.28953025,27.04005859375,19.04953025C27.22005859375,18.92952925,27.34005859375,18.83952725,27.40005859375,18.71953025C27.46005859375,18.62952825,27.490057593750002,18.47952925,27.52005859375,18.29953025C27.49005859375,18.149530249999998,27.46005859375,17.99953125,27.46005859375,17.90952925C27.46005859375,17.819529250000002,27.430058593749997,17.72953025,27.40005859375,17.66952925C27.370058593750002,17.60953025,27.31005859375,17.54952925,27.250058593749998,17.48952925C27.190058593750003,17.42953025,27.10005859375,17.33953025,26.98005859375,17.24953025C26.86005759375,17.15952825,26.74005859375,17.009528250000002,26.65005759375,16.79952925C26.560057593750003,16.58952925,26.47005759375,16.379530250000002,26.41005859375,16.199529249999998C26.35005859375,15.95953025,26.29005859375,15.71953125,26.20005859375,15.44953025C26.11005859375,15.41953225,25.99005889375,15.35953025,25.90005879375,15.23953025C25.810059593749997,15.14952925,25.72005839375,15.02952825,25.63005919375,14.87952925C25.54005909375,14.72952925,25.45005799375,14.51953025,25.36005879375,14.24953125C25.27005859375,13.97953025,25.24005799375,13.73952925,25.27005859375,13.52953025C25.30005929375,13.31952925,25.330059093750002,13.10953025,25.39005949375,12.95953125C25.45005889375,12.77952925,25.54005909375,12.59953025,25.69005969375,12.47953035C25.69005969375,11.90952965,25.72005839375,11.33952995,25.810059593749997,10.73953055C25.90005879375,10.25952955,26.02005859375,9.74953035,26.17005859375,9.17953105C26.320058593749998,8.60953095,26.59005959375,8.09953065,26.92005959375,7.64953085C27.19005959375,7.28953125,27.49005859375,6.92953065,27.85005859375,6.56953095C28.21005859375,6.20953105,28.54005859375,5.939530850000001,28.84005859375,5.75953105C28.750059593750002,5.45953105,28.66005859375,5.15953135,28.60005859375,4.91953115C28.54005859375,4.67953105,28.42005859375,4.40953095,28.180059593750002,4.13953135C27.85005859375,3.74953155,27.370058593750002,3.38953143,26.71005959375,3.02953136C26.05005929375,2.66953133,25.30005929375,2.51953125,24.49005889375,2.51953125C24.16005899375,2.51953125,23.83005949375,2.549531311,23.47005889375,2.579531148C23.11005929375,2.63953105,22.78005889375,2.72953123,22.45005849375,2.84953102C22.12005849375,2.99953112,21.79005859375,3.17953098,21.46005869375,3.41953105C21.13005879375,3.6595311500000003,20.830059093750002,3.98953115,20.56005859375,4.3795309499999995C20.26005889375,4.799530949999999,20.050058593750002,5.24953075,19.90005879375,5.75953105C19.75005889375,6.26953125,19.66005849375,6.74953075,19.570058593749998,7.19953155C19.51005859375,7.73953155,19.48005869375,8.279531949999999,19.51005859375,8.78953125C19.39005879375,8.90953205,19.300058593750002,9.05953165,19.24005869375,9.23953105C19.18005849375,9.389530650000001,19.12005849375,9.56953145,19.12005849375,9.77953105C19.09005859375,9.98953105,19.15005849375,10.19953065,19.21005869375,10.43953085C19.30005839375,10.67952915,19.39005849375,10.85953045,19.48005869375,10.97953125C19.570058593749998,11.09953115,19.66005849375,11.21953015,19.75005889375,11.27953145C19.84005899375,11.33952995,19.96005889375,11.39953135,20.05005909375,11.42953105C20.11005929375,11.66952895,20.17005869375,11.90952965,20.26005889375,12.08953185C20.32005879375,12.26953125,20.41005899375,12.44952965,20.50005909375,12.62953125C20.590059293750002,12.80953125,20.71005869375,12.92953125,20.830059093750002,13.01953125C21.07005929375,13.22953025,21.28005889375,13.40953125,21.46005869375,13.58953225C21.64005849375,13.76953125,21.760059393749998,14.03953125,21.79005909375,14.36953025C21.82005929375,14.57953125,21.82005929375,14.78953125,21.82005929375,14.96953225C21.82005929375,15.14953125,21.79005909375,15.32953225,21.73005919375,15.50953225C21.67005869375,15.68953125,21.55005879375,15.83953225,21.40005879375,16.019532249999997C21.25005869375,16.16953225,21.01005839375,16.37953425,20.71005869375,16.55953225C20.32005879375,16.79953325,19.90005879375,16.97953325,19.42005849375,17.09953325C18.94005849375,17.219533249999998,18.46005819375,17.36953325,18.01005849375,17.519533250000002C17.56005849375,17.66953325,17.14005849375,17.87953425,16.81005853375,18.149534250000002C16.48005858375,18.41953325,16.27005860375,18.80953425,16.18005858375,19.31953225C16.06005857978016,20.24953225,16.03005858875,20.99953225,16.09005858575,21.56953425C16.15005857475,22.13953225,16.27005860375,22.49953225,16.42005857375,22.61953325C16.51005858375,22.70953325,16.75005853375,22.76953325,17.14005849375,22.85953325C17.53005849375,22.94953525,17.98005869375,23.00953525,18.52005859375,23.09953325C19.06005839375,23.18953525,19.66005849375,23.24953425,20.32005879375,23.30953625C20.98005869375,23.36953525,21.64005849375,23.42953525,22.27005859375,23.48953425C22.30005839375,23.45953325,22.30005839375,23.42953525,22.33005859375,23.39953425C22.36005879375,23.36953525,22.36005879375,23.33953525,22.39005849375,23.30953225C22.42005869375,23.15953425,22.42005869375,23.00953525,22.42005869375,22.82953425C22.42005869375,22.64953425,22.45005939375,22.46953425,22.48005919375,22.28953325C22.57005929375,21.68953325,22.78005889375,21.23953425,23.11005929375,20.90953425C23.44005919375,20.57953425,23.83005859375,20.33953325,24.280058893750002,20.12953425C24.70005889375,20.03953125,25.18005849375,19.85953325,25.66005799375,19.67952925Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M40.660066375,22.83203525C40.540063375,22.47203625,40.300064375000005,22.172036249999998,40.000063374999996,21.93203725C39.700063375,21.69203625,39.340065375,21.51203625,38.950064375,21.36203725C38.560063375,21.21203825,38.170063375,21.09203725,37.750064375,20.972036250000002C37.330062375,20.852036249999998,36.940062375,20.73203525,36.610063374999996,20.58203625C36.220063375,20.43203725,35.920063375,20.25203725,35.680063375,20.07203625C35.470061375,19.86203625,35.290063375,19.68203525,35.200063375,19.44203425C35.110063374999996,19.23203325,35.050063375,19.02203425,35.050063375,18.78203525C35.050063375,18.57203325,35.050063375,18.33203525,35.080063375,18.12203425C35.110063374999996,17.972033250000003,35.170065375,17.82203525,35.230063375,17.70203525C35.290063375,17.582033250000002,35.350063375,17.49203325,35.440063375,17.40203525L35.710064375,17.13203425C35.830063375,17.04203425,35.950065375,16.95203525,36.070065375,16.83203525C36.190065375,16.74203425,36.280065375,16.62203425,36.400064375,16.44203425C36.490064375,16.26203445,36.580063375,16.08203315,36.640065375,15.90203385C36.700063375,15.69203285,36.760065374999996,15.48203375,36.850066375,15.24203395C37.000064375,15.21203325,37.120066375,15.12203315,37.240066375,15.03203205C37.330066375,14.94203185,37.450066375,14.79203225,37.540065375,14.61203285C37.630066375,14.43203165,37.690065375,14.19203285,37.750066375,13.89203315C37.780065375,13.652032850000001,37.780065375,13.47203255,37.750066375,13.32203245C37.720067375,13.17203285,37.660065375,13.05203195,37.600067375,12.932032150000001C37.540067375,12.81203175,37.450066375,12.72203205,37.390065375,12.66203165C37.420066375,12.092031949999999,37.360066375,11.55203195,37.300065375,10.98203185C37.210064375,10.50203185,37.090064375,9.99203225,36.910064375,9.45203205C36.730066375,8.91203185,36.460065375,8.40203185,36.100064375,7.95203165C35.800065375,7.56203105,35.290064375,7.20203125,34.660065375,6.84203142C34.000064375,6.48203157,33.250064875,6.33203125,32.410065675,6.33203125C32.110065475,6.33203125,31.780065075,6.362031313,31.420065875,6.392031375C31.060065275,6.4520315,30.730065775,6.54203124,30.370065675,6.6620315C30.010066075,6.81203136,29.680065675,6.99203128,29.350065675,7.23203135C29.020065775,7.47203145,28.720065575,7.80203175,28.450065575,8.19203105C28.150065875,8.61203095,27.940065875000002,9.09203125,27.790065975,9.57203125C27.640066175,10.08203105,27.550066675,10.56203125,27.490066275,11.01203155C27.430066375,11.55203195,27.400066575,12.092031949999999,27.430066375,12.60203175C27.310065975,12.72203205,27.220066275,12.872032149999999,27.160066375,13.052031549999999C27.100065975,13.17203185,27.040065975,13.35203125,27.040065975,13.56203075C27.010066275,13.772031349999999,27.070065775,13.98203185,27.130065675,14.22203205C27.220065375,14.46203045,27.310065975,14.64203165,27.400065675,14.76203255C27.490065575,14.88203235,27.580066175,15.00203135,27.670065875,15.06203265C27.760065775,15.12203125,27.880065875,15.18203255,27.970065575,15.21203235C28.030065575000002,15.45203305,28.090065975,15.69203095,28.180065675,15.87203315C28.240065575,16.05203245,28.330065275,16.23203375,28.420065375,16.41203225C28.510064575,16.592032250000003,28.600065275,16.74203125,28.720065075,16.832033250000002C28.960064375,17.01203125,29.170064475,17.19203325,29.350064775,17.37203325C29.560064775,17.55203225,29.650064475,17.82203325,29.710064875,18.15203425C29.740064175,18.392034250000002,29.740064175,18.602033249999998,29.740064175,18.78203525C29.740064175,18.962033249999998,29.710064875,19.142034250000002,29.620064275,19.292035249999998C29.560063875,19.44203425,29.440063975,19.62203425,29.260064175,19.77203425C29.110064075,19.92203425,28.870063775,20.13203525,28.570064075,20.31203425C28.180063675,20.55203425,27.760063875,20.732034249999998,27.280063675,20.85203525C26.800063875,20.972035249999998,26.320063575,21.12203525,25.870064175,21.27203425C25.420064575,21.42203425,25.000064475,21.662035250000002,24.670064335,21.90203525C24.340064105,22.172036249999998,24.130064125,22.56203625,24.040064395,23.07203525C23.9200641513,23.97203425,23.890064538,24.72203425,23.980064273,25.29203425C24.070064005,25.86203425,24.160064635,26.22203625,24.310064495,26.34203725C24.400064225,26.40203525,24.580064595,26.49203525,24.910064815,26.55203825C25.240064975,26.61203625,25.630064475,26.70203825,26.080064775,26.76203725C26.560065075,26.82203625,27.070064575,26.91203925,27.610064775,26.97203825C28.180064675,27.03203725,28.750064375,27.09203925,29.320064975,27.12204025C29.890064674999998,27.18203725,30.460064875,27.21203825,30.970065075,27.24203825C31.510064575,27.27203925,31.990065575,27.30203825,32.380065875,27.30203825C32.770066275,27.30203825,33.280065575,27.27203925,33.820065475,27.24203825C34.360066375,27.21203825,34.930065375,27.18203925,35.500064375,27.12204025C36.070065375,27.06204025,36.670065375,27.00203925,37.240066375,26.94203925C37.810065375,26.88204025,38.350066375,26.79203825,38.830065375000004,26.70203925C39.310063375,26.61203725,39.700063375,26.52203925,40.030063375,26.43203725C40.360065375000005,26.34203925,40.540067375,26.22203625,40.600065375,26.13204025C40.690067375,25.98203825,40.780063375,25.77203725,40.810064374999996,25.47203825C40.870065374999996,25.17203925,40.870065374999996,24.87203825,40.870065374999996,24.51203925C40.870065374999996,24.18203925,40.840067375000004,23.85203725,40.810064374999996,23.52203925C40.780067375,23.34203925,40.720064375,23.07203825,40.660066375,22.83203525Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/jichupeizhi.svg b/src/assets/system/jichupeizhi.svg
new file mode 100644
index 0000000..bdaf618
--- /dev/null
+++ b/src/assets/system/jichupeizhi.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="89.5693359375" height="96" viewBox="0 0 89.5693359375 96"><defs><filter id="master_svg0_143_35968" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="-0.6666666666666666" y="-0.6666666666666666" width="2.3333333333333335" height="2.3333333333333335"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="0" dx="0"/><feGaussianBlur stdDeviation="8"/><feColorMatrix type="matrix" values="0 0 0 0 0.12895070016384125 0 0 0 0 0.29307788610458374 0 0 0 0 0.9107142686843872 0 0 0 0.5299999713897705 0"/><feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><clipPath id="master_svg1_143_34356"><rect x="32.78466796875" y="36" width="25" height="24" rx="0"/></clipPath></defs><path d="M44.78466796875,24.000000000000004L65.56927496875,36L65.56927496875,60L44.78466796875,72L24.00005836875,60L24.00005796875,36.000001L44.78466796875,24.000000000000004Z" fill="#496FFE" fill-opacity="1" filter="url(#master_svg0_143_35968)"/><g clip-path="url(#master_svg1_143_34356)"><path d="M45.88867596875,51.096690875C45.959985968750004,50.688688875,46.48291996875,50.544689875,46.76815496875,50.832688875L49.24020996875,53.304690875C49.59675396875,53.664689875,50.167228968749995,53.664689875,50.523774968750004,53.304690875L51.783568968750004,52.032688875C52.140115968749996,51.672690875,52.140115968749996,51.096691875,51.783568968750004,50.760690875L49.311517968749996,48.240688875000004C49.00251196875,47.952689875000004,49.14512796875,47.424689875,49.54921496875,47.352690875C50.99916796875,47.064690875,52.544200968750005,47.496689875,53.68514596875,48.648689875C54.92117496875,49.896689875,55.32525796875,51.672689875,54.84986496875,53.280688874999996C54.77855496875,53.544686875,54.826095968749996,53.832688875,55.016252968749995,54.024690875000005L57.53584496875,56.544690875C57.89239096875,56.904691875,57.89239096875,57.480689874999996,57.53584496875,57.816690875L56.252276968749996,59.088687875000005C55.89573496875,59.448688875,55.32525796875,59.448688875,54.96871196875,59.088687875000005L52.44912196875,56.520688875000005C52.25896296875,56.328687875,51.97372796875,56.280688874999996,51.71225896875,56.352689874999996C50.14345896875,56.808686875,48.38449896875,56.424689875,47.148470968750004,55.176688874999996C46.05506396875,54.072690875,45.65097696875,52.536686875,45.88867596875,51.096690875ZM55.77688396875,57.936690875C56.15719796875,57.936690875,56.46620596875,57.624688875000004,56.46620596875,57.240689875C56.46620596875,56.856690875,56.15719796875,56.544690875,55.77688396875,56.544690875C55.39656996875,56.544690875,55.08756296875,56.856690875,55.08756296875,57.240689875C55.08756296875,57.624688875000004,55.39656996875,57.936690875,55.77688396875,57.936690875ZM55.46787796875,46.224690475L54.944943968749996,44.304689875C54.89740596875,44.112690975,54.75478596875,43.944690675000004,54.58839796875,43.848690475C54.39823896875,43.728690575,54.18431096875,43.656691574999996,53.99415796875,43.704690975L52.87697996875,43.992689575C52.37781296875,44.088689775,51.854880968749995,43.896689375,51.54587396875,43.464689775L50.571313968750005,42.192689875C50.23853896875,41.832690675,50.14345896875,41.208689675,50.38115696875,40.776689975L50.97539896875,39.720690275C51.16555996875,39.360690075,51.02293796875,38.904690475,50.66639296875,38.736690275L48.88366296875,37.680690775C48.71727296875,37.584690805,48.50334796875,37.560690705,48.31318996875,37.608690795C48.12303096875,37.656690675,47.98041296875,37.776690675,47.88533296875,37.944690675L47.29109096875,38.952690575C47.02962396875,39.384690475,46.50668996875,39.600690375,46.00752496875,39.504690375L44.43872296875,39.288690575C43.96332796875,39.240690475,43.41662296875,38.856690675,43.32154696875,38.376690475L43.01253896875,37.248690605C42.96499896875,37.056690575,42.82238196875,36.888690625,42.65599346875,36.792690615C42.46583656875,36.672690658,42.22813796875,36.624690654,42.01420976875,36.672690658L40.08886286875,37.152690615C39.68477726875,37.248690605,39.44707866875,37.680690575,39.56592896875,38.064690575L39.87493566875,39.192690175C39.99378396875,39.696690075,39.80362656875,40.200690075,39.37577106875,40.488690575L38.11597536875,41.448689975C37.73566006875,41.784690875,37.16518686875,41.832690675,36.68979166875,41.592690475L35.66769336875,40.992690575C35.33491706875,40.776689975,34.90706206875,40.872690675,34.66936476875,41.208690175L33.59972607875,43.056691175C33.52841686875,43.224689975000004,33.50464713875,43.392690675,33.55218660875,43.560690375C33.62349575875,43.752690775,33.74234455875,43.920689575,33.90873256875,44.016689775L34.93083096875,44.616690675C35.38245586875,44.904689775,35.59638306875,45.432690575,35.50130466875,45.936691275L35.33491656875,47.520690875C35.31114646875,48.000689875,34.93083096875,48.528689875,34.45543626875,48.600688875L33.33825903875,48.888688875C32.93417358875,49.008689875,32.69647629575,49.416688875,32.81532496375,49.824688875L33.33825903875,51.744687875C33.45710759875,52.152688875,33.86119316875,52.392688875,34.28904826875,52.296688875L35.42999556875,52.008687875C35.92916006875,51.912686875,36.45209356875,52.104688875,36.76110026875,52.536686875L37.73565956875,53.808686875C38.06843516875,54.192685874999995,38.13974476875,54.768687875,37.90204766875,55.200687875L37.30780406875,56.208688875C37.21272566875,56.376687875,37.18895526875,56.592689875000005,37.236494568750004,56.784686875C37.28403426875,56.976686875,37.42665286875,57.144685875,37.59304046875,57.240686875L39.37577056875,58.272687875C39.54215856875,58.368686875,39.75608586875,58.392684875,39.94624326875,58.344688875C40.13640066875,58.296685875,40.30278966875,58.176684875,40.39786866875,58.008685875L40.99211216875,57.000686875C41.27734946875,56.568687874999995,41.800283468749996,56.352687875,42.29944706875,56.448686875L43.89201796875,56.664687875C44.36741496875,56.688687875,44.89034796875,57.096688875,45.00919596875,57.576686875L45.31820196875,58.704686875C45.43705196875,59.112687875,45.84113596875,59.352685875,46.26899196875,59.256686875L48.19433996875,58.776687875C48.47957896875,58.704686875,48.66973396875,58.464685875,48.74104396875,58.200687875C47.67140596875,57.888686875000005,46.69684696875,57.336686875,45.88867596875,56.520688875000005C45.128044968750004,55.752687875,44.581341968749996,54.816690875,44.29610396875,53.808688875L44.224794968750004,53.808688875C41.01588246875,53.808688875,38.42498156875,51.192689875,38.42498156875,47.952688875C38.42498156875,44.712689375,41.01588246875,42.096689175,44.224794968750004,42.096689175C46.53045896875,42.096689175,48.52711696875,43.440689075,49.454135968749995,45.408688575C49.81068196875,45.360690075,50.16722696875,45.312688875,50.523772968749995,45.312688875C52.21142196875,45.312688875,53.78022796875,45.960688575,54.99248496875,47.112687875L55.016252968749995,47.112687875C55.32525796875,47.040688875,55.56295796875,46.632689475,55.46787796875,46.224690475ZM44.03463696875,50.760689875C44.05840696875,50.544689875,44.12971596875,50.352689874999996,44.224794968750004,50.184689875000004C43.84447996875,50.208690875,43.440392968750004,50.112688875,43.08384796875,49.896689875C42.06174946875,49.296689875,41.70520396875,47.976688875,42.29944706875,46.944690875C42.89368896875,45.912689175,44.20102496875,45.552690475,45.22312496875,46.152690875C46.15014196875,46.680688875,46.50668996875,47.808690874999996,46.15014196875,48.792688874999996C46.245220968750004,48.792688874999996,46.31653096875,48.768689875,46.41161096875,48.768689875C46.81569496875,48.768689875,47.19600996875,48.864689874999996,47.52878596875,49.032688875C47.24354896875,48.480689874999996,47.148470968750004,47.808688875,47.338627968750004,47.184689875000004C47.48124796875,46.680688875,47.79025396875,46.248689675,48.170568968750004,45.960690475C47.43370796875,44.448689975,45.888674968749996,43.416690875,44.10594596875,43.416690875C41.61012456875,43.416690875,39.56592796875,45.456689875,39.56592796875,48.000689875C39.56592796875,50.472690875,41.49127676875,52.464687874999996,43.91578896875,52.560689875C43.89201796875,51.960688875,43.91578896875,51.360688875,44.03463696875,50.760689875Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/kehudangan.svg b/src/assets/system/kehudangan.svg
new file mode 100644
index 0000000..a0dd2ec
--- /dev/null
+++ b/src/assets/system/kehudangan.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="63.90625" viewBox="0 0 59.5 63.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35599"><rect x="14.5" y="0" width="32" height="32" rx="0"/></clipPath></defs><path d="M1.204819142818451,27.096379L28.69276814281845,43.307213000000004L58.29516614281845,27.096379L28.69276814281845,13L1.204819142818451,27.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,27.065809L28.43877614281845,43.737896L28.68361514281845,43.882288L59.39288714281845,27.065309L28.684561142818453,12.44229615L0.16870074281845082,27.065809ZM28.70192014281845,42.732138L2.240937742818451,27.12695L28.70097614281845,13.55770427L57.19744514281845,27.127449L28.70192014281845,42.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,27.80120277404785L0.5,46.83131777404785L28.692764,63.042150774047855L28.692764,44.01204077404785L0.5,27.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,63.906411774047854L29.192764,43.722777774047856L28.941999,43.578587774047854L-5.999999996841865e-8,26.93693918404785L0,47.12058077404785L29.192764,63.906411774047854ZM28.192764,44.30130377404785L28.192764,62.17788877404785L1,46.542054774047855L1,28.66546636404785L28.192764,44.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,27.80120277404785L59,46.12649377404785L88.5,63.00042177404785L88.5,43.26604677404785L59,27.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,63.86243677404785L89,42.96362277404785L88.732151,42.82320777404785L58.50000003,26.97454732404785L58.50000003,46.41651177404785L89,63.86243677404785ZM88,43.568469774047855L88,62.13840677404785L59.5,45.836475774047855L59.5,28.627858224047852L88,43.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35599)"><path d="M33.0601790625,19.699661125C33.0601790625,19.699661125,31.9935130625,19.415219125,31.7090700625,19.272997125C31.1401790625,18.917440125,30.7846260625,18.206329125,30.7846260625,17.495218125C30.7846260625,16.712996125,31.4246250625,16.072997125,31.8512940625,15.575218125C32.9179590625,14.295218125,33.4868490625,12.588551525,33.4868490625,10.668550925C33.4868490625,6.6863279250000005,30.6424040625,3.486328125,27.1579580625,3.486328125C23.6735133625,3.486328125,20.8290676625,6.757439625,20.8290676625,10.739662124999999C20.8290676625,12.659662225,21.4690680625,14.366329125,22.4646234625,15.646329125C23.104623762499997,16.001884125,23.5312900625,16.784108125,23.5312900625,17.566329125C23.5312900625,18.277439125,23.1757345625,18.917439125,22.606845862500002,19.344107125L22.606845862500002,19.415219125C22.5357351625,19.415219125,22.4646234625,19.486330125,22.4646234625,19.486330125C22.1090674625,19.699661125,21.753511862499998,19.841886125,21.3268451625,19.841886125C18.6246223625,20.766333125,16.3490668625,22.188555125,14.9979558625,23.966331125L15.0690669725,23.966331125C14.7135113625,24.464107125,14.571289122104652,25.033001125,14.571289151906974,25.601889125C14.571289151906974,27.308554125,15.9935116625,28.730776125,17.7712893625,28.730776125L36.5446260625,28.730776125C38.3935150625,28.730776125,39.8157370625,27.379669125,39.8157370625,25.601889125C39.8157370625,24.890777125,39.5312920625,24.250776125,39.175737062500005,23.681887125C37.8246270625,21.904108125,35.6912940625,20.552999125,33.0601790625,19.699661125ZM45.7890700625,22.828550125C44.5801810625,21.335218125,42.731295062499996,20.055218125,40.384626062500004,19.344107125C40.384626062500004,19.344107125,39.460182062499996,19.130773124999997,39.175737062500005,18.988552125C38.6779590625,18.632995125,38.3935150625,18.064107125,38.3935150625,17.424106125C38.3935150625,16.712996125,38.9624040625,16.144107124999998,39.3179570625,15.788550125C40.2424050625,14.650774125,40.8112940625,13.157439225,40.8112940625,11.450773224999999C40.8112940625,7.966328125,38.3224010625,5.050772425,35.1935140625,5.050772425C34.6957340625,5.050772425,34.1979580625,5.121883625,33.771292062499995,5.264105525C34.837957062499996,6.828550125,35.4068470625,8.677439725,35.4068470625,10.739662124999999C35.4068470625,12.944106125,34.624624062500004,15.077440125,33.2735140625,16.855217125L33.131292062499995,16.997439125L33.131292062499995,17.068550125C32.9890690625,17.210771125,32.7757360625,17.424106125,32.7046260625,17.637441125000002C32.7046260625,17.708552125,32.7046260625,17.708552125,32.7757380625,17.708552125C32.9179590625,17.779663125,33.131294062500004,17.850773125,33.344627062499995,17.850773125L33.415739062499995,17.850773125L33.7001840625,17.992995125C36.615740062499995,18.917439125,39.1046280625,20.552994125,40.7401830625,22.615217125C41.4512940625,23.539663125,41.8779620625,24.606331125,41.8779620625,25.744110125C41.8779620625,26.384107125,41.7357390625,26.881883125,41.522406062499996,27.450775125L43.584627062500005,27.450775125C45.2201820625,27.450775125,46.500181062500005,26.241884125,46.500181062500005,24.677442125C46.4290710625,23.895220125,46.2157380625,23.326330125,45.7890700625,22.828550125Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/kehuwanglai.svg b/src/assets/system/kehuwanglai.svg
new file mode 100644
index 0000000..41a62c0
--- /dev/null
+++ b/src/assets/system/kehuwanglai.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35644"><rect x="15" y="0" width="31" height="31" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35644)"><path d="M41.009501,2.634513605C38.250498,2.634513605,36.018496999999996,4.122513425,36.018496999999996,5.9515133250000005C36.018496999999996,7.191513025,37.0105,8.245513425,38.498497,8.834512725C38.436499,9.237513025,38.281496000000004,9.671513125,38.033497,10.136512725C38.033497,10.136512725,39.428499,10.012512725,40.141498999999996,9.237512625C40.420497999999995,9.268512225,40.699499,9.299512825,41.009501,9.299512825C43.768496999999996,9.299512825,46.0005,7.811512425,46.0005,5.982512724999999C46.0005,4.122513025,43.768496999999996,2.634513143,41.009501,2.634513605ZM38.994499000000005,6.416513425C38.591497000000004,6.416513425,38.281498,6.106513525,38.281498,5.703513425000001C38.281498,5.3005135249999995,38.591497000000004,4.990513325,38.994499000000005,4.990513325C39.397501,4.990513325,39.707499,5.3005135249999995,39.707499,5.703513425000001C39.707499,6.0755131250000005,39.366499000000005,6.416513425,38.994499000000005,6.416513425ZM41.133500999999995,6.416513425C40.730498999999995,6.416513425,40.420497999999995,6.106513525,40.420497999999995,5.703513425000001C40.420497999999995,5.3005135249999995,40.730498999999995,4.990513325,41.133500999999995,4.990513325C41.536499,4.990513325,41.846498,5.3005135249999995,41.846498,5.703513425000001C41.846498,6.0755131250000005,41.505499,6.416513425,41.133500999999995,6.416513425ZM43.272501,6.416513425C42.869499000000005,6.416513425,42.5595,6.106513525,42.5595,5.703513425000001C42.5595,5.3005135249999995,42.869499000000005,4.990513325,43.272501,4.990513325C43.675499,4.990513325,43.985498,5.3005135249999995,43.985498,5.703513425000001C43.985498,6.0755131250000005,43.644498999999996,6.416513425,43.272501,6.416513425ZM24.9825001,20.335512625C25.478499,20.180513625,25.9745,19.932514625,26.408499,19.684512625C26.594501,19.560512625,26.718499,19.467510625,26.780499,19.343513625C26.842501,19.250511625,26.8735,19.095512625,26.904501,18.909513625C26.873500999999997,18.754514625,26.842501,18.599513625,26.842501,18.506513625C26.842501,18.413512625,26.811501,18.320512625,26.780499,18.258511625C26.749499999999998,18.196513625,26.6875,18.134511625000002,26.625500000000002,18.072512625C26.563499,18.010514625,26.4705,17.917513624999998,26.346499,17.824512625C26.2225,17.731510625,26.098501,17.576512625,26.005499999999998,17.359513624999998C25.912499,17.142513625,25.819499999999998,16.925514624999998,25.7575,16.739514624999998C25.695498999999998,16.491513625,25.633499,16.243514625,25.5405,15.964514625C25.447499999999998,15.933514625,25.3235,15.871514625,25.2305,15.747513625C25.1375,15.654513625,25.0445004,15.530512625,24.9514999,15.375512625C24.8585014,15.220513625,24.7655001,15.003514625,24.6724997,14.724513625C24.5795012,14.445513625,24.5485001,14.197513625,24.5795012,13.980514625C24.610499400000002,13.763513625,24.6415005,13.546514625,24.7035007,13.391513625C24.765501,13.205513625,24.8585014,13.019513625,25.0135012,12.895513625C25.0135012,12.306513825,25.0445004,11.717514025,25.1375,11.097515125C25.2305,10.601513825,25.354501,10.074514425,25.509501,9.485514625C25.6645,8.896514925,25.943500999999998,8.369514425,26.2845,7.904515225C26.563499999999998,7.532515525,26.873500999999997,7.160514825,27.2455,6.788515125C27.6175,6.416515125,27.958501,6.137515325,28.268499,5.951514925C28.1755,5.641515025,28.0825,5.331515325,28.020501,5.083515425C27.958501,4.835515525,27.8345,4.5565153249999995,27.5865,4.2775156249999995C27.2455,3.874515725,26.749499999999998,3.5025157350000002,26.067500000000003,3.130515695C25.385502000000002,2.758515705,24.6105013,2.603515625,23.7735014,2.603515625C23.4325008,2.603515625,23.0915012,2.634515684,22.7195001,2.665515512C22.3475003,2.727515395,22.0065007,2.820515585,21.665499699999998,2.944515375C21.3244996,3.099515435,20.983500499999998,3.285515305,20.6424999,3.533515335C20.301499800000002,3.781515525,19.9915004,4.122515325,19.7125006,4.525515325C19.4025002,4.959515325,19.1855001,5.424515025,19.0304999,5.951514925C18.8755002,6.4785151249999995,18.7825,6.974514925,18.6894999,7.439515125C18.6275001,7.997515725,18.5964999,8.555515725,18.6275001,9.082515225C18.5035,9.206515325,18.4105,9.361515525,18.3485,9.547515425C18.2865002,9.702514625,18.2245002,9.888515025,18.2245002,10.105515024999999C18.1934998,10.322515025000001,18.2555001,10.539514525000001,18.3175001,10.787514725C18.4104998,11.035512925,18.5034997,11.221514725,18.5964999,11.345515225C18.6894999,11.469514825,18.7825,11.593514425,18.8755002,11.655514725C18.9685004,11.717514025,19.0925002,11.779515225,19.1855001,11.810515425C19.2475004,12.058512725,19.3095007,12.306513825,19.4025006,12.492514625C19.4645004,12.678514625,19.557500400000002,12.864513625,19.6505008,13.050515625C19.7435007,13.236513625,19.8675003,13.360515625,19.9915004,13.453514625C20.2395,13.670513625,20.4565005,13.856515625,20.6424999,14.042514625C20.8285003,14.228514625,20.9525008,14.507514625,20.983501,14.848514625C21.0145001,15.065514625,21.0145001,15.282513625,21.0145001,15.468516625C21.0145001,15.654515625,20.983501,15.840515625,20.9215002,16.026515625000002C20.8595004,16.212514625,20.7355008,16.367514625,20.5805006,16.553516625C20.4255004,16.708515625,20.1775002,16.925516625,19.8674998,17.111516625C19.4645,17.359516624999998,19.0304999,17.545515625,18.5345001,17.669515625000003C18.0384998,17.793516625000002,17.5424998,17.948516625,17.0775001,18.103517625000002C16.6124998,18.258515625,16.1785001,18.475516624999997,15.837499919999999,18.754516625C15.49650002,19.033515625,15.27950002,19.436517625,15.18649999,19.963516625C15.062499985564498,20.924516625,15.031499993,21.699516625,15.09349999,22.288516625C15.155499987,22.877515625,15.27950002,23.249513625,15.43449998,23.373515625C15.5275,23.466518625,15.77549994,23.528514625,16.1785001,23.621517625C16.5814999,23.714517625,17.0465,23.776515625,17.6045001,23.869516625C18.1624997,23.962518625,18.7825,24.024518625,19.4645,24.086519625C20.1465001,24.148517625,20.8285003,24.210517625,21.479500299999998,24.272518625C21.510500399999998,24.241519625,21.510500399999998,24.210517625,21.5415006,24.179517625C21.5725002,24.148517625,21.5725002,24.117519625,21.6035004,24.086515625C21.6345005,23.931516625,21.6345005,23.776515625,21.6345005,23.590516625C21.6345005,23.404518625,21.6655006,23.218515625,21.6965003,23.032514625C21.7895012,22.412517625,22.0065007,21.947515625,22.3475003,21.606515625C22.6885009,21.265518625,23.091499300000002,21.017516625,23.556501400000002,20.800517625C23.9905005,20.707515625,24.4865007,20.521516625,24.9825001,20.335512625Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M40.48196953125,23.59297175C40.35796753125,23.22097175,40.109968531250004,22.91097275,39.79996853125,22.66297375C39.48996953125,22.41497375,39.11797053125,22.22897475,38.71496853125,22.07397375C38.31196653125,21.91897375,37.90896753125,21.79497375,37.47496753125,21.67097375C37.040967531250004,21.546972750000002,36.63796753125,21.42297375,36.296967531250004,21.26797275C35.893968531249996,21.11297275,35.58396853125,20.92697475,35.33596753125,20.74097175C35.11896653125,20.52397175,34.93296753125,20.33797275,34.83996853125,20.08997175C34.74696753125,19.87297075,34.68496753125,19.65597175,34.68496753125,19.40797175C34.68496753125,19.19097175,34.68496753125,18.94297075,34.71596853125,18.725970750000002C34.74696753125,18.57097075,34.80896953125,18.41597075,34.87096853125,18.29197075C34.93296753125,18.16797175,34.99496853125,18.07496975,35.08796853125,17.98197175L35.36696953125,17.70297175C35.49096853125,17.609969749999998,35.61497053125,17.51697175,35.73896953125,17.39297075C35.86296953125,17.29997075,35.95597053125,17.175970749999998,36.07996853125,16.989970749999998C36.172969531250004,16.803971750000002,36.265968531249996,16.617970749999998,36.32796953125,16.43197155C36.38996853125,16.21496965,36.45197053125,15.99797055,36.54497053125,15.74997045C36.69997053125,15.71897025,36.82397053125,15.62597085,36.94797053125,15.53296945C37.04097153125,15.43996905,37.16497253125,15.28496935,37.25797053125,15.09896945C37.350971531249996,14.91296765,37.41297053125,14.66496945,37.47497053125,14.35496955C37.50597053125,14.106969849999999,37.50597053125,13.920969450000001,37.47497053125,13.76596975C37.44397153125,13.61096955,37.38197153125,13.48696945,37.31997153125,13.36296935C37.25797153125,13.23896885,37.16497253125,13.14596935,37.10297153125,13.08396915C37.13397053125,12.49496885,37.07197153125,11.93696925,37.00996953125,11.34796905C36.916969531250004,10.85196925,36.79296953125,10.324969750000001,36.60696953125,9.766969249999999C36.42097053125,9.20896915,36.14196953125,8.68196945,35.76996953125,8.21696885C35.45997053125,7.81396865,34.93296853125,7.44196874,34.28196953125,7.06996888C33.59996953125,6.69796906,32.82497023125,6.54296875,31.95697023125,6.54296875C31.64697073125,6.54296875,31.30596923125,6.573968815,30.93396993125,6.604968879C30.56197023125,6.66696901,30.22097063125,6.75996874,29.84897093125,6.88396898C29.47697063125,7.03896886,29.13597063125,7.22496873,28.79497053125,7.47296876C28.45396993125,7.72096885,28.143970531249998,8.06196915,27.86497073125,8.46496855C27.554970731250002,8.89896845,27.33797073125,9.39496855,27.182970731250002,9.89096855C27.02797103125,10.417968049999999,26.934971131250002,10.913968050000001,26.87297103125,11.37896875C26.81097103125,11.93696925,26.77997133125,12.49496885,26.81097103125,13.021969349999999C26.68697073125,13.14596935,26.59397073125,13.30096915,26.53197073125,13.48696895C26.46997073125,13.610968549999999,26.40797063125,13.796967949999999,26.40797063125,14.01396845C26.37697103125,14.23096795,26.43897013125,14.447968450000001,26.50097013125,14.69596955C26.59397003125,14.94396785,26.68697073125,15.12996865,26.77997043125,15.25397015C26.87297033125,15.37796975,26.96597103125,15.50196835,27.05897043125,15.56396865C27.15197013125,15.62596795,27.275970431250002,15.68797015,27.36897043125,15.71896835C27.43097023125,15.96696945,27.49297043125,16.21496775,27.58596993125,16.40096955C27.64797063125,16.58696975,27.740970131250002,16.77296975,27.83396963125,16.95896875C27.926969531250002,17.14496875,28.01996993125,17.299969750000002,28.14396953125,17.39296975C28.39196873125,17.57896975,28.60896923125,17.76496975,28.79496913125,17.95096975C29.01196953125,18.13696975,29.10496953125,18.415969750000002,29.16696933125,18.75697075C29.19796893125,19.00497175,29.19796893125,19.22197075,29.19796893125,19.40797175C29.19796893125,19.59397075,29.16696933125,19.77997275,29.07396843125,19.934971750000003C29.01196813125,20.08997175,28.88796803125,20.27597175,28.70196913125,20.43097075C28.54696893125,20.58597175,28.29896883125,20.802972750000002,27.98896883125,20.98897075C27.58596853125,21.236971750000002,27.15196823125,21.422970749999998,26.65596843125,21.54697175C26.15996813125,21.67097275,25.66396833125,21.82597275,25.19896863125,21.980970749999997C24.73396893125,22.13597075,24.29996903125,22.38397175,23.95896882125,22.63197375C23.61796862125,22.91097275,23.40096862125,23.31397475,23.30796889125,23.84097075C23.18396863345,24.77097175,23.15296903225,25.54597075,23.24596876325,26.13497175C23.33896848125,26.72397075,23.43196915125,27.09597175,23.58696902125,27.21997275C23.67996874125,27.28197075,23.86596912125,27.37497175,24.20696933125,27.43697375C24.54796953125,27.49897175,24.950969131249998,27.59197475,25.41596933125,27.65397275C25.91196943125,27.71597275,26.43896933125,27.80897375,26.99696943125,27.87097575C27.58596943125,27.93297175,28.17496923125,27.99497375,28.76396993125,28.02597475C29.352969631249998,28.08797475,29.94196983125,28.11897475,30.46897033125,28.14997675C31.026969431250002,28.18097475,31.52297023125,28.21197275,31.92597003125,28.21197275C32.32897093125,28.21197275,32.85596943125,28.18097475,33.41397053125,28.14997675C33.97196953125,28.11897475,34.56097053125,28.08797675,35.14997053125,28.02597475C35.73896953125,27.96397575,36.35896853125,27.90197375,36.94797053125,27.83997575C37.53697053125,27.77797475,38.094971531249996,27.68497475,38.59097053125,27.59197475C39.08696753125,27.49897375,39.48996953125,27.40597575,39.83096853125,27.31297675C40.17197253125,27.21997475,40.35797153125,27.09597575,40.41997153125,27.00297575C40.51297153125,26.84797475,40.60597053125,26.63097375,40.63697053125,26.32097675C40.69896853125,26.01097475,40.69896853125,25.70097575,40.69896853125,25.32897375C40.69896853125,24.98797375,40.66797253125,24.64697475,40.63697053125,24.30597475C40.60597453125,24.11997375,40.54397053125,23.84097675,40.48196953125,23.59297175Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/kucunguanli.svg b/src/assets/system/kucunguanli.svg
new file mode 100644
index 0000000..85b1219
--- /dev/null
+++ b/src/assets/system/kucunguanli.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="61.90625" viewBox="0 0 59.5 61.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35878"><rect x="13.5" y="0" width="32" height="32" rx="0"/></clipPath></defs><path d="M1.204819142818451,25.096379L28.69276814281845,41.307213000000004L58.29516614281845,25.096379L28.69276814281845,11L1.204819142818451,25.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,25.065809L28.43877614281845,41.737896L28.68361514281845,41.882288L59.39288714281845,25.065309L28.684561142818453,10.44229615L0.16870074281845082,25.065809ZM28.70192014281845,40.732138L2.240937742818451,25.12695L28.70097614281845,11.55770427L57.19744514281845,25.127449L28.70192014281845,40.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,25.80120277404785L0.5,44.83131777404785L28.692764,61.042150774047855L28.692764,42.01204077404785L0.5,25.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,61.906411774047854L29.192764,41.722777774047856L28.941999,41.578587774047854L-5.999999996841865e-8,24.93693918404785L0,45.12058077404785L29.192764,61.906411774047854ZM28.192764,42.30130377404785L28.192764,60.17788877404785L1,44.542054774047855L1,26.66546636404785L28.192764,42.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,25.80120277404785L59,44.12649377404785L88.5,61.00042177404785L88.5,41.26604677404785L59,25.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,61.86243677404785L89,40.96362277404785L88.732151,40.82320777404785L58.50000003,24.97454732404785L58.50000003,44.41651177404785L89,61.86243677404785ZM88,41.568469774047855L88,60.13840677404785L59.5,43.836475774047855L59.5,26.627858224047852L88,41.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35878)"><path d="M38.91415821875,30.224147875L20.39949081875,30.224147875C19.11332841875,30.269017875,18.02515268375,29.281917875,17.94482421875,27.997483875L17.94482421875,7.246370275C17.94482421875,6.032147875,19.124379618749998,5.126370475,20.45460221875,5.126370475L22.12793541875,5.126370475L22.138602218750002,5.526370575C22.14790441875,7.155996275,23.47563411875,8.470001674999999,25.10526891875,8.462370875000001L34.10704621875,8.462370875000001C35.73682621875,8.469508675,37.064411218749996,7.155250075,37.07371321875,5.525481975L37.18660121875,5.125481375L38.85993421875,5.125481375C40.29237921875,5.125481375,41.36971321875,6.030815075,41.36971321875,7.245481475L41.36971321875,28.401923875C41.07641021875,29.507728875,40.05750421875,30.263835875,38.91415821875,30.224147875ZM27.76704601875,13.421037875C27.37507341875,13.016912875,26.72657391875,13.016912875,26.334601418749997,13.421037875L23.87904551875,15.850370875L22.44748971875,14.433926875C22.05595681875,14.028763875,21.40657731875,14.028763875,21.01504511875,14.433926875C20.60587361875,14.817425875,20.60587361875,15.466869875,21.01504511875,15.850370875L23.05949071875,17.874814875C23.05845741875,17.932044875,23.10538391875,17.978566875,23.16260101875,17.977037875C23.219183918749998,17.974988875,23.26588101875,18.020871875,23.26482391875,18.077481875C23.65635581875,18.482642875,24.30573561875,18.482642875,24.69726801875,18.077481875L27.97015721875,14.838815875C28.42443721875,14.427935875,28.31841421875,13.687848875,27.76704601875,13.421037875ZM27.76704601875,19.998815875C27.37551311875,19.593654875,26.72613331875,19.593654875,26.334601418749997,19.998815875L23.87904551875,22.428149875L22.44748971875,21.010369875C22.05595591875,20.605210875,21.40657731875,20.605210875,21.01504511875,21.010369875C20.60547471875,21.394223875,20.60547471875,22.044293875,21.01504511875,22.428149875L23.05949071875,24.452592875C23.05896661875,24.509471875,23.10573861875,24.555438875,23.16260101875,24.553926875C23.21932891875,24.552398875,23.26585721875,24.598519875,23.26482391875,24.655261875C23.65635581875,25.060420875,24.30573561875,25.060420875,24.69726801875,24.655261875L27.97015721875,21.517037875C28.378157218749998,21.113927875,28.378157218749998,20.507260875,27.767046918749998,20.002814875L27.767046918749998,19.998370875L27.76704601875,19.998815875ZM38.12260221875,13.496593875L32.89415821875,13.496593875C32.01108221875,13.554154875,31.324264218750002,14.287201875,31.324264218750002,15.172150875C31.324264218750002,16.057098875,32.01108421875,16.790143875,32.89415821875,16.847704874999998L38.12260221875,16.847704874999998C39.02518621875,16.833244875,39.73615621875,16.073720875,39.69104721875,15.172148875C39.69799421875,14.285016875,39.008262218750005,13.548182875,38.12260221875,13.496593875ZM38.12260221875,20.183259875L32.89415821875,20.183259875C32.01249721875,20.242505875,31.32762721875,20.974942875,31.32762721875,21.858592875C31.327630218750002,22.742242875,32.01249921875,23.474679875,32.89415821875,23.533925875L38.12260221875,23.533925875C39.04142221875,23.558019875,39.77521321875,22.774531875,39.69104721875,21.859258875C39.69778221875,20.972129875,39.00823021875,20.235292875,38.12260221875,20.183259875ZM33.328378218750004,6.798814775L25.98926831875,6.798814775C24.81208661875,6.811668375,23.84158901875,5.879128975,23.80749031875,4.702370175C23.84182641875,3.525786675,24.81225441875,2.593511875,25.98926831875,2.6063706250000003L26.461268418750002,2.6063706250000003C26.68953801875,2.092310075,27.20474621875,1.766140461,27.76704601875,1.77970385551L31.55193621875,1.77970385551C32.113917218750004,1.766503215,32.62868121875,2.092614055,32.856825218750004,2.6063706250000003L33.33015921875,2.6063706250000003C34.50716021875,2.593498345,35.47777521875,3.5253773749999997,35.512825218749995,4.701925975C35.60971421875,5.845481375,34.61815821875,6.798369875,33.32837921875,6.798369875L33.328378218750004,6.798814775Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/rukuguanli.svg b/src/assets/system/rukuguanli.svg
new file mode 100644
index 0000000..bb7df01
--- /dev/null
+++ b/src/assets/system/rukuguanli.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35860"><rect x="12.5" y="0" width="34" height="34.000003814697266" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35860)"><path d="M35.790823312499995,24.330472625L40.532228312499996,24.330472625C41.1830103125,24.330472625,41.7109393125,24.858400625,41.7109393125,25.509183625L41.7109393125,27.893161625C41.7109393125,28.543947625,41.1830103125,29.071872625,40.532228312499996,29.071872625L35.790823312499995,29.071872625L35.790823312499995,30.483011625C35.790823312499995,31.469142625,34.6519513125,32.020316625,33.8783243125,31.409372625L29.0505873125,27.587697625C28.4496093125,27.112893625,28.4529313125,26.203126625,29.0572293125,25.731641625L33.8849623125,21.963086625C34.658598312500004,21.358793625,35.790823312499995,21.909965625,35.790823312499995,22.892774625L35.790823312499995,24.330472625ZM27.028485312500003,5.268882525L17.2591470125,13.108853325C16.3131175025,13.868049625,15.7626953125,15.015515625,15.7626953125,16.228507625L15.7626953125,26.801757625C15.7626953125,29.010896625,17.5535564125,30.801757625,19.7626958125,30.801757625L29.9935593125,30.801757625L27.8519553125,29.105081625C27.0982433125,28.507425625,26.6666033125,27.614259625,26.6699233125,26.651368625C26.6732453125,25.688478625,27.1115253125,24.798635625,27.868557312500002,24.207618625L32.6962933125,20.439060625C33.250789312500004,20.004102625,33.9115273125,19.778322625,34.6087933125,19.778322625C36.159378312499996,19.778322625,37.4476603125,20.913871625,37.6867213125,22.394727625L42.5277363125,22.394727625C42.796682312499996,22.394727625,43.052347312500004,22.441215625,43.3013703125,22.504300625L43.3013703125,16.228507625C43.3013703125,15.015515625,42.7509483125,13.868049625,41.8049183125,13.108853325L32.0355813125,5.268882725C30.5729253125,4.095089075,28.4911423125,4.095089075,27.028485312500003,5.268882525M23.8476562125,28.381252625L18.4587896125,28.381252625L18.4587896125,22.989066625L23.8509788125,22.989066625L23.8509788125,28.381252625L23.8476562125,28.381252625ZM23.8476562125,20.422456625L18.4587896125,20.422456625L18.4587896125,15.030274625L23.8509788125,15.030274625L23.8509788125,20.422456625L23.8476562125,20.422456625Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/shengchandingdan.svg b/src/assets/system/shengchandingdan.svg
new file mode 100644
index 0000000..8e3ff7f
--- /dev/null
+++ b/src/assets/system/shengchandingdan.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="62.90625" viewBox="0 0 59.5 62.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35796"><rect x="15" y="0" width="31" height="31" rx="0"/></clipPath></defs><path d="M1.204819142818451,26.096379L28.69276814281845,42.307213000000004L58.29516614281845,26.096379L28.69276814281845,12L1.204819142818451,26.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,26.065809L28.43877614281845,42.737896L28.68361514281845,42.882288L59.39288714281845,26.065309L28.684561142818453,11.44229615L0.16870074281845082,26.065809ZM28.70192014281845,41.732138L2.240937742818451,26.12695L28.70097614281845,12.55770427L57.19744514281845,26.127449L28.70192014281845,41.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,26.80120277404785L0.5,45.83131777404785L28.692764,62.042150774047855L28.692764,43.01204077404785L0.5,26.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,62.906411774047854L29.192764,42.722777774047856L28.941999,42.578587774047854L-5.999999996841865e-8,25.93693918404785L0,46.12058077404785L29.192764,62.906411774047854ZM28.192764,43.30130377404785L28.192764,61.17788877404785L1,45.542054774047855L1,27.66546636404785L28.192764,43.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,26.80120277404785L59,45.12649377404785L88.5,62.00042177404785L88.5,42.26604677404785L59,26.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,62.86243677404785L89,41.96362277404785L88.732151,41.82320777404785L58.50000003,25.97454732404785L58.50000003,45.41651177404785L89,62.86243677404785ZM88,42.568469774047855L88,61.13840677404785L59.5,44.836475774047855L59.5,27.627858224047852L88,42.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35796)"><path d="M41.009501,2.634513605C38.250498,2.634513605,36.018496999999996,4.122513425,36.018496999999996,5.9515133250000005C36.018496999999996,7.191513025,37.0105,8.245513425,38.498497,8.834512725C38.436499,9.237513025,38.281496000000004,9.671513125,38.033497,10.136512725C38.033497,10.136512725,39.428499,10.012512725,40.141498999999996,9.237512625C40.420497999999995,9.268512225,40.699499,9.299512825,41.009501,9.299512825C43.768496999999996,9.299512825,46.0005,7.811512425,46.0005,5.982512724999999C46.0005,4.122513025,43.768496999999996,2.634513143,41.009501,2.634513605ZM38.994499000000005,6.416513425C38.591497000000004,6.416513425,38.281498,6.106513525,38.281498,5.703513425000001C38.281498,5.3005135249999995,38.591497000000004,4.990513325,38.994499000000005,4.990513325C39.397501,4.990513325,39.707499,5.3005135249999995,39.707499,5.703513425000001C39.707499,6.0755131250000005,39.366499000000005,6.416513425,38.994499000000005,6.416513425ZM41.133500999999995,6.416513425C40.730498999999995,6.416513425,40.420497999999995,6.106513525,40.420497999999995,5.703513425000001C40.420497999999995,5.3005135249999995,40.730498999999995,4.990513325,41.133500999999995,4.990513325C41.536499,4.990513325,41.846498,5.3005135249999995,41.846498,5.703513425000001C41.846498,6.0755131250000005,41.505499,6.416513425,41.133500999999995,6.416513425ZM43.272501,6.416513425C42.869499000000005,6.416513425,42.5595,6.106513525,42.5595,5.703513425000001C42.5595,5.3005135249999995,42.869499000000005,4.990513325,43.272501,4.990513325C43.675499,4.990513325,43.985498,5.3005135249999995,43.985498,5.703513425000001C43.985498,6.0755131250000005,43.644498999999996,6.416513425,43.272501,6.416513425ZM24.9825001,20.335512625C25.478499,20.180513625,25.9745,19.932514625,26.408499,19.684512625C26.594501,19.560512625,26.718499,19.467510625,26.780499,19.343513625C26.842501,19.250511625,26.8735,19.095512625,26.904501,18.909513625C26.873500999999997,18.754514625,26.842501,18.599513625,26.842501,18.506513625C26.842501,18.413512625,26.811501,18.320512625,26.780499,18.258511625C26.749499999999998,18.196513625,26.6875,18.134511625000002,26.625500000000002,18.072512625C26.563499,18.010514625,26.4705,17.917513624999998,26.346499,17.824512625C26.2225,17.731510625,26.098501,17.576512625,26.005499999999998,17.359513624999998C25.912499,17.142513625,25.819499999999998,16.925514624999998,25.7575,16.739514624999998C25.695498999999998,16.491513625,25.633499,16.243514625,25.5405,15.964514625C25.447499999999998,15.933514625,25.3235,15.871514625,25.2305,15.747513625C25.1375,15.654513625,25.0445004,15.530512625,24.9514999,15.375512625C24.8585014,15.220513625,24.7655001,15.003514625,24.6724997,14.724513625C24.5795012,14.445513625,24.5485001,14.197513625,24.5795012,13.980514625C24.610499400000002,13.763513625,24.6415005,13.546514625,24.7035007,13.391513625C24.765501,13.205513625,24.8585014,13.019513625,25.0135012,12.895513625C25.0135012,12.306513825,25.0445004,11.717514025,25.1375,11.097515125C25.2305,10.601513825,25.354501,10.074514425,25.509501,9.485514625C25.6645,8.896514925,25.943500999999998,8.369514425,26.2845,7.904515225C26.563499999999998,7.532515525,26.873500999999997,7.160514825,27.2455,6.788515125C27.6175,6.416515125,27.958501,6.137515325,28.268499,5.951514925C28.1755,5.641515025,28.0825,5.331515325,28.020501,5.083515425C27.958501,4.835515525,27.8345,4.5565153249999995,27.5865,4.2775156249999995C27.2455,3.874515725,26.749499999999998,3.5025157350000002,26.067500000000003,3.130515695C25.385502000000002,2.758515705,24.6105013,2.603515625,23.7735014,2.603515625C23.4325008,2.603515625,23.0915012,2.634515684,22.7195001,2.665515512C22.3475003,2.727515395,22.0065007,2.820515585,21.665499699999998,2.944515375C21.3244996,3.099515435,20.983500499999998,3.285515305,20.6424999,3.533515335C20.301499800000002,3.781515525,19.9915004,4.122515325,19.7125006,4.525515325C19.4025002,4.959515325,19.1855001,5.424515025,19.0304999,5.951514925C18.8755002,6.4785151249999995,18.7825,6.974514925,18.6894999,7.439515125C18.6275001,7.997515725,18.5964999,8.555515725,18.6275001,9.082515225C18.5035,9.206515325,18.4105,9.361515525,18.3485,9.547515425C18.2865002,9.702514625,18.2245002,9.888515025,18.2245002,10.105515024999999C18.1934998,10.322515025000001,18.2555001,10.539514525000001,18.3175001,10.787514725C18.4104998,11.035512925,18.5034997,11.221514725,18.5964999,11.345515225C18.6894999,11.469514825,18.7825,11.593514425,18.8755002,11.655514725C18.9685004,11.717514025,19.0925002,11.779515225,19.1855001,11.810515425C19.2475004,12.058512725,19.3095007,12.306513825,19.4025006,12.492514625C19.4645004,12.678514625,19.557500400000002,12.864513625,19.6505008,13.050515625C19.7435007,13.236513625,19.8675003,13.360515625,19.9915004,13.453514625C20.2395,13.670513625,20.4565005,13.856515625,20.6424999,14.042514625C20.8285003,14.228514625,20.9525008,14.507514625,20.983501,14.848514625C21.0145001,15.065514625,21.0145001,15.282513625,21.0145001,15.468516625C21.0145001,15.654515625,20.983501,15.840515625,20.9215002,16.026515625000002C20.8595004,16.212514625,20.7355008,16.367514625,20.5805006,16.553516625C20.4255004,16.708515625,20.1775002,16.925516625,19.8674998,17.111516625C19.4645,17.359516624999998,19.0304999,17.545515625,18.5345001,17.669515625000003C18.0384998,17.793516625000002,17.5424998,17.948516625,17.0775001,18.103517625000002C16.6124998,18.258515625,16.1785001,18.475516624999997,15.837499919999999,18.754516625C15.49650002,19.033515625,15.27950002,19.436517625,15.18649999,19.963516625C15.062499985564498,20.924516625,15.031499993,21.699516625,15.09349999,22.288516625C15.155499987,22.877515625,15.27950002,23.249513625,15.43449998,23.373515625C15.5275,23.466518625,15.77549994,23.528514625,16.1785001,23.621517625C16.5814999,23.714517625,17.0465,23.776515625,17.6045001,23.869516625C18.1624997,23.962518625,18.7825,24.024518625,19.4645,24.086519625C20.1465001,24.148517625,20.8285003,24.210517625,21.479500299999998,24.272518625C21.510500399999998,24.241519625,21.510500399999998,24.210517625,21.5415006,24.179517625C21.5725002,24.148517625,21.5725002,24.117519625,21.6035004,24.086515625C21.6345005,23.931516625,21.6345005,23.776515625,21.6345005,23.590516625C21.6345005,23.404518625,21.6655006,23.218515625,21.6965003,23.032514625C21.7895012,22.412517625,22.0065007,21.947515625,22.3475003,21.606515625C22.6885009,21.265518625,23.091499300000002,21.017516625,23.556501400000002,20.800517625C23.9905005,20.707515625,24.4865007,20.521516625,24.9825001,20.335512625Z" fill="#3BB078" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M40.48196953125,23.59297175C40.35796753125,23.22097175,40.109968531250004,22.91097275,39.79996853125,22.66297375C39.48996953125,22.41497375,39.11797053125,22.22897475,38.71496853125,22.07397375C38.31196653125,21.91897375,37.90896753125,21.79497375,37.47496753125,21.67097375C37.040967531250004,21.546972750000002,36.63796753125,21.42297375,36.296967531250004,21.26797275C35.893968531249996,21.11297275,35.58396853125,20.92697475,35.33596753125,20.74097175C35.11896653125,20.52397175,34.93296753125,20.33797275,34.83996853125,20.08997175C34.74696753125,19.87297075,34.68496753125,19.65597175,34.68496753125,19.40797175C34.68496753125,19.19097175,34.68496753125,18.94297075,34.71596853125,18.725970750000002C34.74696753125,18.57097075,34.80896953125,18.41597075,34.87096853125,18.29197075C34.93296753125,18.16797175,34.99496853125,18.07496975,35.08796853125,17.98197175L35.36696953125,17.70297175C35.49096853125,17.609969749999998,35.61497053125,17.51697175,35.73896953125,17.39297075C35.86296953125,17.29997075,35.95597053125,17.175970749999998,36.07996853125,16.989970749999998C36.172969531250004,16.803971750000002,36.265968531249996,16.617970749999998,36.32796953125,16.43197155C36.38996853125,16.21496965,36.45197053125,15.99797055,36.54497053125,15.74997045C36.69997053125,15.71897025,36.82397053125,15.62597085,36.94797053125,15.53296945C37.04097153125,15.43996905,37.16497253125,15.28496935,37.25797053125,15.09896945C37.350971531249996,14.91296765,37.41297053125,14.66496945,37.47497053125,14.35496955C37.50597053125,14.106969849999999,37.50597053125,13.920969450000001,37.47497053125,13.76596975C37.44397153125,13.61096955,37.38197153125,13.48696945,37.31997153125,13.36296935C37.25797153125,13.23896885,37.16497253125,13.14596935,37.10297153125,13.08396915C37.13397053125,12.49496885,37.07197153125,11.93696925,37.00996953125,11.34796905C36.916969531250004,10.85196925,36.79296953125,10.324969750000001,36.60696953125,9.766969249999999C36.42097053125,9.20896915,36.14196953125,8.68196945,35.76996953125,8.21696885C35.45997053125,7.81396865,34.93296853125,7.44196874,34.28196953125,7.06996888C33.59996953125,6.69796906,32.82497023125,6.54296875,31.95697023125,6.54296875C31.64697073125,6.54296875,31.30596923125,6.573968815,30.93396993125,6.604968879C30.56197023125,6.66696901,30.22097063125,6.75996874,29.84897093125,6.88396898C29.47697063125,7.03896886,29.13597063125,7.22496873,28.79497053125,7.47296876C28.45396993125,7.72096885,28.143970531249998,8.06196915,27.86497073125,8.46496855C27.554970731250002,8.89896845,27.33797073125,9.39496855,27.182970731250002,9.89096855C27.02797103125,10.417968049999999,26.934971131250002,10.913968050000001,26.87297103125,11.37896875C26.81097103125,11.93696925,26.77997133125,12.49496885,26.81097103125,13.021969349999999C26.68697073125,13.14596935,26.59397073125,13.30096915,26.53197073125,13.48696895C26.46997073125,13.610968549999999,26.40797063125,13.796967949999999,26.40797063125,14.01396845C26.37697103125,14.23096795,26.43897013125,14.447968450000001,26.50097013125,14.69596955C26.59397003125,14.94396785,26.68697073125,15.12996865,26.77997043125,15.25397015C26.87297033125,15.37796975,26.96597103125,15.50196835,27.05897043125,15.56396865C27.15197013125,15.62596795,27.275970431250002,15.68797015,27.36897043125,15.71896835C27.43097023125,15.96696945,27.49297043125,16.21496775,27.58596993125,16.40096955C27.64797063125,16.58696975,27.740970131250002,16.77296975,27.83396963125,16.95896875C27.926969531250002,17.14496875,28.01996993125,17.299969750000002,28.14396953125,17.39296975C28.39196873125,17.57896975,28.60896923125,17.76496975,28.79496913125,17.95096975C29.01196953125,18.13696975,29.10496953125,18.415969750000002,29.16696933125,18.75697075C29.19796893125,19.00497175,29.19796893125,19.22197075,29.19796893125,19.40797175C29.19796893125,19.59397075,29.16696933125,19.77997275,29.07396843125,19.934971750000003C29.01196813125,20.08997175,28.88796803125,20.27597175,28.70196913125,20.43097075C28.54696893125,20.58597175,28.29896883125,20.802972750000002,27.98896883125,20.98897075C27.58596853125,21.236971750000002,27.15196823125,21.422970749999998,26.65596843125,21.54697175C26.15996813125,21.67097275,25.66396833125,21.82597275,25.19896863125,21.980970749999997C24.73396893125,22.13597075,24.29996903125,22.38397175,23.95896882125,22.63197375C23.61796862125,22.91097275,23.40096862125,23.31397475,23.30796889125,23.84097075C23.18396863345,24.77097175,23.15296903225,25.54597075,23.24596876325,26.13497175C23.33896848125,26.72397075,23.43196915125,27.09597175,23.58696902125,27.21997275C23.67996874125,27.28197075,23.86596912125,27.37497175,24.20696933125,27.43697375C24.54796953125,27.49897175,24.950969131249998,27.59197475,25.41596933125,27.65397275C25.91196943125,27.71597275,26.43896933125,27.80897375,26.99696943125,27.87097575C27.58596943125,27.93297175,28.17496923125,27.99497375,28.76396993125,28.02597475C29.352969631249998,28.08797475,29.94196983125,28.11897475,30.46897033125,28.14997675C31.026969431250002,28.18097475,31.52297023125,28.21197275,31.92597003125,28.21197275C32.32897093125,28.21197275,32.85596943125,28.18097475,33.41397053125,28.14997675C33.97196953125,28.11897475,34.56097053125,28.08797675,35.14997053125,28.02597475C35.73896953125,27.96397575,36.35896853125,27.90197375,36.94797053125,27.83997575C37.53697053125,27.77797475,38.094971531249996,27.68497475,38.59097053125,27.59197475C39.08696753125,27.49897375,39.48996953125,27.40597575,39.83096853125,27.31297675C40.17197253125,27.21997475,40.35797153125,27.09597575,40.41997153125,27.00297575C40.51297153125,26.84797475,40.60597053125,26.63097375,40.63697053125,26.32097675C40.69896853125,26.01097475,40.69896853125,25.70097575,40.69896853125,25.32897375C40.69896853125,24.98797375,40.66797253125,24.64697475,40.63697053125,24.30597475C40.60597453125,24.11997375,40.54397053125,23.84097675,40.48196953125,23.59297175Z" fill="#3BB078" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/shengchanheduan.svg b/src/assets/system/shengchanheduan.svg
new file mode 100644
index 0000000..55d6f9e
--- /dev/null
+++ b/src/assets/system/shengchanheduan.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="63.90625" viewBox="0 0 59.5 63.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35834"><rect x="14" y="0" width="31" height="31" rx="0"/></clipPath></defs><path d="M1.204819142818451,27.096379L28.69276814281845,43.307213000000004L58.29516614281845,27.096379L28.69276814281845,13L1.204819142818451,27.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,27.065809L28.43877614281845,43.737896L28.68361514281845,43.882288L59.39288714281845,27.065309L28.684561142818453,12.44229615L0.16870074281845082,27.065809ZM28.70192014281845,42.732138L2.240937742818451,27.12695L28.70097614281845,13.55770427L57.19744514281845,27.127449L28.70192014281845,42.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,27.80120277404785L0.5,46.83131777404785L28.692764,63.042150774047855L28.692764,44.01204077404785L0.5,27.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,63.906411774047854L29.192764,43.722777774047856L28.941999,43.578587774047854L-5.999999996841865e-8,26.93693918404785L0,47.12058077404785L29.192764,63.906411774047854ZM28.192764,44.30130377404785L28.192764,62.17788877404785L1,46.542054774047855L1,28.66546636404785L28.192764,44.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,27.80120277404785L59,46.12649377404785L88.5,63.00042177404785L88.5,43.26604677404785L59,27.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,63.86243677404785L89,42.96362277404785L88.732151,42.82320777404785L58.50000003,26.97454732404785L58.50000003,46.41651177404785L89,63.86243677404785ZM88,43.568469774047855L88,62.13840677404785L59.5,45.836475774047855L59.5,28.627858224047852L88,43.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35834)"><path d="M38.21875,2.90625L20.78125,2.90625C19.71562505,2.90625,18.84375,3.77812505,18.84375,4.84375L18.84375,6.78125L20.78125,6.78125C21.8468752,6.78125,22.71875,7.6531253,22.71875,8.71875C22.71875,9.7843752,21.8468752,10.65625,20.78125,10.65625L18.84375,10.65625L18.84375,13.5625L20.78125,13.5625C21.8468752,13.5625,22.71875,14.434375,22.71875,15.5C22.71875,16.565625,21.8468752,17.4375,20.78125,17.4375L18.84375,17.4375L18.84375,20.34375L20.78125,20.34375C21.8468752,20.34375,22.71875,21.215626,22.71875,22.28125C22.71875,23.346876,21.8468752,24.21875,20.78125,24.21875L18.84375,24.21875L18.84375,26.15625C18.84375,27.221876,19.71562505,28.09375,20.78125,28.09375L38.21875,28.09375C39.284376,28.09375,40.15625,27.221876,40.15625,26.15625L40.15625,4.84375C40.15625,3.77812505,39.284376,2.90625,38.21875,2.90625Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M33.12253475625,13.77256255L34.31409645625,13.77256255L34.31409645625,15.38262465L32.30103305625,15.38262465L31.88446995625,16.18668745L31.88446995625,17.00818685L34.31409455625,17.00818685L34.31409455625,18.616312049999998L31.88350005625,18.616312049999998L31.88350005625,20.88803025L29.66215705625,20.88803025L29.66215705625,18.617280049999998L27.21509462625,18.617280049999998L27.21509462625,17.00818685L29.66215705625,17.00818685L29.66215705625,16.18668745L29.24268885625,15.38262465L27.21509557625,15.38262465L27.21509557625,13.77256255L28.42215825625,13.77256255L26.21728515625,9.42578125L28.64884805625,9.42578125L30.77234835625,14.06124975L32.89778615625,9.42578125L35.31190965625,9.42578125L33.12253475625,13.77256255Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M20.78125,9.6875L16.90625,9.6875C16.37343752,9.6875,15.9375,9.2515626,15.9375,8.71875C15.9375,8.18593732,16.37343752,7.75,16.90625,7.75L20.78125,7.75C21.3140626,7.75,21.75,8.18593732,21.75,8.71875C21.75,9.2515626,21.3140626,9.6875,20.78125,9.6875ZM20.78125,16.46875L16.90625,16.46875C16.37343752,16.46875,15.9375,16.0328121,15.9375,15.5C15.9375,14.967187899999999,16.37343752,14.53125,16.90625,14.53125L20.78125,14.53125C21.3140626,14.53125,21.75,14.9671874,21.75,15.5C21.75,16.0328121,21.3140626,16.46875,20.78125,16.46875ZM20.78125,23.25L16.90625,23.25C16.37343752,23.25,15.9375,22.814062,15.9375,22.28125C15.9375,21.748438,16.37343752,21.3125,16.90625,21.3125L20.78125,21.3125C21.3140626,21.3125,21.75,21.748438,21.75,22.28125C21.75,22.814062,21.3140626,23.25,20.78125,23.25Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/shengchanpaichan.svg b/src/assets/system/shengchanpaichan.svg
new file mode 100644
index 0000000..0165a7b
--- /dev/null
+++ b/src/assets/system/shengchanpaichan.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35806"><rect x="14.5" y="0" width="32" height="32" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35806)"><path d="M25.2873048875,20.756252C25.2873048875,19.415625,25.5498046875,18.115626,26.0685548875,16.890625999999997C26.5685548875,15.706251,27.284178687500003,14.646876,28.1966796875,13.734375C29.1091806875,12.8218746,30.1685546875,12.1062508,31.3529306875,11.6062508C32.5779306875,11.0875001,33.8779296875,10.8250008,35.2185556875,10.8250008C36.5591816875,10.8250008,37.8591806875,11.0875001,39.0841806875,11.6062508C39.4623066875,11.765625,39.8248066875,11.9468746,40.1779306875,12.1499996L40.1779306875,3.90000015C40.1779306875,3.47187522,39.831058687500004,3.125,39.4029316875,3.125L31.9779286875,3.125C31.9935536875,3.196875095,31.9998046875,3.26874995,31.9998046875,3.34375001L31.9998046875,7.5062499C31.9998046875,8.1062503,31.5123046875,8.593749500000001,30.9123046875,8.593749500000001L26.846678687500003,8.593749500000001C26.2466792875,8.593749500000001,25.7591800875,8.1062493,25.7591800875,7.5062499L25.7591800875,3.34687544C25.7591800875,3.27187538,25.765430487499998,3.200000525,25.781055487499998,3.1281254294L18.3560545475,3.1281254294C17.9279296075,3.1281254294,17.5810546875,3.47500041,17.5810546875,3.90312535L17.5810546875,25.046877C17.5810546875,25.475,17.9279296075,25.821877,18.3560547275,25.821877L26.674805687499997,25.821877C26.446680987500002,25.437502,26.243555987500002,25.0375,26.0685557875,24.625002C25.5498056875,23.396875,25.2873057875,22.096874,25.2873048875,20.756252ZM35.2185556875,12.7000017C30.768552687499998,12.7000017,27.1623048875,16.30625,27.1623048875,20.756248C27.1623048875,25.206247,30.768552687499998,28.812502,35.2185556875,28.812502C39.6685566875,28.812502,43.2748026875,25.206249,43.2748026875,20.756252C43.2748026875,16.306252,39.6685566875,12.7000017,35.2185556875,12.7000017ZM38.7248036875,21.868752C37.8185536875,22.775002,36.5091776875,23.0375,35.3716816875,22.65625L33.2310546875,24.796877C32.6654306875,25.362499,31.7435556875,25.362499,31.1779296875,24.796877C30.612302687499998,24.231253,30.612305687499997,23.309378,31.1779296875,22.743752L33.3185536875,20.603125C32.9373046875,19.465628,33.1966786875,18.156250999999997,34.1060566875,17.250000999999997C35.0841786875,16.271876,36.5248066875,16.043751999999998,37.7185556875,16.562500999999997L35.6216816875,18.659374L35.9623066875,20L37.315427687500005,20.353125L39.4123036875,18.256251C39.9310526875,19.453125,39.6998066875,20.893751,38.7248036875,21.868752ZM31.846677687499998,23.475C31.846179687499998,23.836065,32.1387386875,24.129026,32.4998026875,24.129026C32.8608656875,24.129026,33.153425687500004,23.836065,33.1529276875,23.475C33.153425687500004,23.113937,32.8608656875,22.820976,32.4998026875,22.820976C32.1387386875,22.820976,31.8461786875,23.113937,31.846677687499998,23.475Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/shengchanpeizhi.svg b/src/assets/system/shengchanpeizhi.svg
new file mode 100644
index 0000000..ea6690b
--- /dev/null
+++ b/src/assets/system/shengchanpeizhi.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="89.5693359375" height="96" viewBox="0 0 89.5693359375 96"><defs><filter id="master_svg0_143_35998" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="-0.6666666666666666" y="-0.6666666666666666" width="2.3333333333333335" height="2.3333333333333335"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="0" dx="0"/><feGaussianBlur stdDeviation="8"/><feColorMatrix type="matrix" values="0 0 0 0 0.12895070016384125 0 0 0 0 0.29307788610458374 0 0 0 0 0.9107142686843872 0 0 0 0.5299999713897705 0"/><feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><clipPath id="master_svg1_143_36001"><rect x="33.78466796875" y="35" width="24" height="24" rx="0"/></clipPath></defs><path d="M44.78466796875,24.000000000000004L65.56927496875,36L65.56927496875,60L44.78466796875,72L24.00005836875,60L24.00005796875,36.000001L44.78466796875,24.000000000000004Z" fill="#496FFE" fill-opacity="1" filter="url(#master_svg0_143_35998)"/><g clip-path="url(#master_svg1_143_36001)"><path d="M47.28466896875,59.000001999999995L36.49966816875,59.000001999999995C35.83063894875,59.000834999999995,35.28714856525,58.46003,35.28466796875,57.791002L35.28466796875,39.9020004C35.28796181125,39.2333269,35.83096992875,38.6930003,36.49966816875,38.6930003L38.24566816875,38.6930003L38.24566816875,43.6130009L51.271669968750004,43.6130009L51.271669968750004,38.6930003L53.01767196875,38.6930003C53.68817096875,38.6930003,54.23267196875,39.2359996,54.23267196875,39.902L54.23267196875,45.908001C50.739634968749996,44.6980333,46.885882968749996,46.213699,45.15295886875,49.479017999999996C43.420036268749996,52.744337,44.32480906875,56.785379,47.28466896875,59.000001999999995ZM50.08666996875,42.3755007L39.42916826875,42.3755007L39.42916826875,38.3915005C39.42916826875,37.5455,40.02766896875,36.8585002,40.76266856875,36.8585002L42.13816836875,36.8585002C42.63016936875,35.73050004,43.63966936875,35,44.75866886875,35C45.87616896875,35,46.88566996875,35.73050004,47.37766896875,36.8585002L48.75466996875,36.8585002C49.489668968749996,36.8585002,50.08666996875,37.5455003,50.08666996875,38.3915005L50.08666996875,42.3755007ZM38.24566816875,47.9075C38.24566816875,48.237501,38.51566836875,48.522501,38.84566856875,48.522501L44.15716836875,48.522501C44.49682516875,48.522501,44.77217006875,48.247156000000004,44.77217006875,47.9075C44.77217006875,47.567845,44.49682516875,47.292500000000004,44.15716836875,47.292500000000004L38.84716846875,47.292500000000004C38.51279706875,47.299842,38.24558806875,47.573049,38.24566816875,47.9075ZM38.24566816875,52.824503C38.24566816875,53.154503,38.51866816875,53.439501,38.85616846875,53.439501L42.96466876875,53.439501C43.30120946875,53.433825999999996,43.57196616875,53.161074,43.57516856875,52.824503C43.57516856875,52.494501,43.30216886875,52.209501,42.96466876875,52.209501L38.85466856875,52.209501C38.51812866875,52.215178,38.24737286875,52.48793,38.24416856875,52.824503L38.24566816875,52.824503ZM42.09316876875,40.5320001C42.59357406875,40.5229702,42.99186656875,40.1099033,42.98266936875,39.6095004C42.99102686875,39.1096783,42.59297896875,38.6975336,42.09316876875,38.6884999C41.59394886875,38.6983497,41.19680456875,39.1102533,41.20516876875,39.6095004C41.20516876875,40.1195002,41.60266826875,40.5320001,42.09316876875,40.5320001ZM47.42266896875,40.5320001C47.922485968749996,40.5221539,48.31987196875,40.1093283,48.31066996875,39.6095004C48.31903496875,39.1102524,47.92188996875,38.6983497,47.42266896875,38.6884999C46.923450968750004,38.6983497,46.52630596875,39.1102533,46.53466896875,39.6095004C46.53466896875,40.1195002,46.93217096875,40.5320001,47.42266896875,40.5320001ZM51.784669968749995,59.000001999999995C48.470961968750004,59.000001999999995,45.78466896875,56.313713,45.78466896875,53.000001999999995C45.78466896875,49.686294000000004,48.470961968750004,47.000001,51.784669968749995,47.000001C55.09838096875,47.000001,57.784669968749995,49.686294000000004,57.784669968749995,53.000001999999995C57.784669968749995,56.313713,55.09838096875,59.000001999999995,51.784669968749995,59.000001999999995ZM55.41616996875,51.002003L55.41616996875,48.539001L52.099668968749995,48.539001L52.099668968749995,49.355001L50.64466996875,49.355001L50.64466996875,55.919001L52.09216896875,55.919001L52.09216896875,57.153503L55.402669968750004,57.153503L55.402669968750004,54.630500999999995L52.09216896875,54.630500999999995L52.09216896875,55.095501L51.379668968749996,55.095501L51.379668968749996,50.153001L52.099668968749995,50.153001L52.099668968749995,51.002001L55.41767096875,51.002001L55.41616996875,51.002003ZM50.259168968750004,52.160002C50.00266996875,51.680004,50.005670968749996,51.672504,50.005670968749996,51.672504C50.005670968749996,51.672504,49.12067096875,51.950002999999995,48.95566996875,51.000502L48.442669968749996,51.000502C48.442669968749996,51.000502,48.30166996875,51.951504,47.39716996875,51.669502L47.12717096875,52.173504C47.12717096875,52.173504,47.83517096875,52.728504,47.12717096875,53.478504L47.40166996875,53.985506C47.40166996875,53.985506,48.18316996875,53.607506,48.43967096875,54.639505L48.95866996875,54.639505C48.95866996875,54.639505,49.12067096875,53.691505,49.99966996875,53.972006C50.25016996875,53.492004,50.25467096875,53.489004,50.25467096875,53.489004C50.25467096875,53.489004,49.59017096875,52.847006,50.259168968750004,52.160002Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/shenpiguanli.svg b/src/assets/system/shenpiguanli.svg
new file mode 100644
index 0000000..16ba84b
--- /dev/null
+++ b/src/assets/system/shenpiguanli.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35558"><rect x="12.5" y="0" width="34.000003814697266" height="34" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35558)"><path d="M30.364756937499997,25.1723935L31.5122539375,23.7415655C30.7614219375,22.8348995,30.3080869375,21.6732315,30.3080869375,20.4265635C30.3080869375,17.5648925,32.6455929375,15.2273945,35.5214249375,15.2273945C37.0655859375,15.2273945,38.4680879375,15.9073935,39.417254937500005,16.969893499999998L39.417254937500005,4.4890625C39.417254937500005,3.55406219,38.652257937499996,2.7890625,37.7172569375,2.7890625L19.3005861375,2.7890625C18.3655856875,2.7890625,17.6005859375,3.55406243,17.6005859375,4.4890625L17.6005859375,26.5890575C17.6005859375,27.5240575,18.3655862175,28.2890625,19.3005861375,28.2890625L27.4747514375,28.2890625C27.8289189375,26.8015635,28.933920937499998,25.6115625,30.364756937499997,25.1723935ZM23.706419037499998,6.7982302L33.339754937500004,6.7982302C33.963088937500004,6.7982302,34.4730839375,7.3082304,34.4730839375,7.9315624C34.4730839375,8.5548954,33.963088937500004,9.0648956,33.339754937500004,9.0648956L23.7064218375,9.0648956C23.083087437499998,9.0648956,22.5730877375,8.5548968,22.5730877375,7.9315639C22.5730877375,7.3082304,23.0689206375,6.7982302,23.706419037499998,6.7982302ZM23.706419037499998,11.8982306L33.339754937500004,11.8982306C33.963088937500004,11.8982306,34.4730839375,12.4082298,34.4730839375,13.0315625C34.4730839375,13.6548975,33.963088937500004,14.1648965,33.339754937500004,14.1648965L23.7064218375,14.1648965C23.083087437499998,14.1648965,22.5730877375,13.6548975,22.5730877375,13.0315625C22.5730877375,12.4082298,23.0689206375,11.8982306,23.706419037499998,11.8982306ZM22.5730872375,18.1315635C22.5730872375,17.5082325,23.0830865375,16.9982295,23.706419037499998,16.9982295L27.6730879375,16.9982295C28.296420937500002,16.9982295,28.8064209375,17.5082265,28.8064209375,18.1315575C28.8064209375,18.754890500000002,28.296420937500002,19.2648965,27.6730879375,19.2648965L23.706419037499998,19.2648965C23.0689187375,19.2648965,22.5730872375,18.7548925,22.5730872375,18.1315635Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/><path d="M39.43028168125,31.168883875L31.596113881249998,31.168883875C30.51944607125,31.168883875,29.64111328125,30.290549875,29.64111328125,29.213882875C29.64111328125,28.137214874999998,30.51944607125,27.258882475,31.596113881249998,27.258882475L34.81194638125,23.263881675C33.52277968125,22.952215175,32.57361388125,21.804714675,32.57361388125,20.430547675C32.57361388125,18.815546775,33.89111378125,17.498046875,35.52027988125,17.498046875C37.14944748125,17.498046875,38.46694468125,18.815546775,38.46694468125,20.430547675C38.46694468125,21.804714675,37.51777978125,22.952215175,36.22861288125,23.263881675L39.44444748125,27.258882475C40.52111428125,27.258882475,41.39944628125,28.137214874999998,41.39944628125,29.213882875C41.39944628125,30.290549875,40.52111428125,31.168883875,39.43028168125,31.168883875Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/xiaoshoubaojia.svg b/src/assets/system/xiaoshoubaojia.svg
new file mode 100644
index 0000000..13a84dd
--- /dev/null
+++ b/src/assets/system/xiaoshoubaojia.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="59.90625" viewBox="0 0 59.5 59.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35608"><rect x="18" y="0" width="24" height="24" rx="0"/></clipPath></defs><path d="M1.204819142818451,23.096379L28.69276814281845,39.307213000000004L58.29516614281845,23.096379L28.69276814281845,9L1.204819142818451,23.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,23.065809L28.43877614281845,39.737896L28.68361514281845,39.882288L59.39288714281845,23.065309L28.684561142818453,8.44229615L0.16870074281845082,23.065809ZM28.70192014281845,38.732138L2.240937742818451,23.12695L28.70097614281845,9.55770427L57.19744514281845,23.127449L28.70192014281845,38.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,23.80120277404785L0.5,42.83131777404785L28.692764,59.042150774047855L28.692764,40.01204077404785L0.5,23.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,59.906411774047854L29.192764,39.722777774047856L28.941999,39.578587774047854L-5.999999996841865e-8,22.93693918404785L0,43.12058077404785L29.192764,59.906411774047854ZM28.192764,40.30130377404785L28.192764,58.17788877404785L1,42.542054774047855L1,24.66546636404785L28.192764,40.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,23.80120277404785L59,42.12649377404785L88.5,59.00042177404785L88.5,39.26604677404785L59,23.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,59.86243677404785L89,38.96362277404785L88.732151,38.82320777404785L58.50000003,22.97454732404785L58.50000003,42.41651177404785L89,59.86243677404785ZM88,39.568469774047855L88,58.13840677404785L59.5,41.836475774047855L59.5,24.627858224047852L88,39.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35608)"><path d="M20.17195003125,2.664L37.21195053125,2.664C37.94394853125,2.664,38.531948531249995,3.2640002,38.51994853125,3.9960001L38.51994853125,22.667999C38.531948531249995,23.4,37.94394853125,24,37.21195053125,24L20.17195003125,24C19.43994993125,24,18.85195001925,23.400002,18.86395004392,22.667999L18.86395004392,3.9960001C18.85195001925,3.2640002,19.43995005125,2.6759999,20.17195003125,2.664ZM22.78794983125,15.324L22.78794983125,19.320002C22.78794983125,19.691999,23.087950231249998,19.991999,23.45994993125,19.991999C23.80795003125,19.991999,24.09594963125,19.704,24.09594963125,19.356001L24.09594963125,15.312C24.09594963125,14.952001,23.80795003125,14.664,23.44794993125,14.664C23.087950231249998,14.664,22.78794983125,14.964,22.78794983125,15.324ZM28.03195003125,16.68L28.03195003125,19.308001C28.03195003125,19.68,28.331950231249998,19.991999,28.71595003125,19.991999C29.06395053125,19.991999,29.33994953125,19.716,29.33994953125,19.368L29.33994953125,16.620001C29.33994953125,16.271999,29.06395053125,15.995999,28.71595003125,15.995999C28.34395023125,15.995999,28.03195003125,16.308001,28.03195003125,16.68ZM33.275950531250004,12.683999L33.275950531250004,19.296C33.275950531250004,19.679998,33.587949531250004,20.004,33.98394953125,20.004C34.31995053125,20.004,34.58394953125,19.727999,34.58394953125,19.404001L34.58394953125,12.624001C34.58394953125,12.276,34.30794953125,12,33.959949531250004,12C33.58794853125,12,33.27594853125,12.312,33.275950531250004,12.683999ZM28.96795053125,12.084L34.58394953125,8.6999998C34.883949531249996,8.5200005,34.97994853125,8.1359997,34.799948531249996,7.8360004C34.60794953125,7.5120001,34.17594953125,7.4040003,33.85194853125,7.5959997L29.14795053125,10.44C29.02795153125,10.512,28.85995103125,10.5,28.76395033125,10.392L26.25594993125,7.7879996C26.12395053125,7.6560001,25.91995093125,7.6319995,25.76395033125,7.7399998L22.60794993125,9.8640003C22.283950131250002,10.08,22.19995023125,10.512,22.41595003125,10.836C22.60794993125,11.124,23.00395063125,11.208,23.29194973125,11.016L25.61995033125,9.4320002C25.751949831250002,9.3479996,25.91995003125,9.3600006,26.03994993125,9.4800005L28.51195143125,12.048001C28.63195033125,12.156,28.82395073125,12.180001,28.96795053125,12.084ZM40.487951531250005,21.323999C40.12795053125,21.323999,39.82795153125,21.024,39.82795153125,20.664L39.82795153125,2.664C39.83995253125,1.932,39.25195153125,1.332,38.51995253125,1.332L22.10395023125,1.332C21.75595043125,1.332,21.47995043125,1.056,21.47995043125,0.708C21.47995023125,0.31200001,21.79195043125,0,22.18795033125,0L38.519950531250004,0C39.983949531250005,0.012,41.159950531250004,1.2,41.14794953125,2.664L41.14794953125,20.676001C41.14794953125,21.036001,40.847949531249995,21.336,40.487951531250005,21.323999Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/xiaoshoupeizhi.svg b/src/assets/system/xiaoshoupeizhi.svg
new file mode 100644
index 0000000..7191560
--- /dev/null
+++ b/src/assets/system/xiaoshoupeizhi.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="89.5693359375" height="96" viewBox="0 0 89.5693359375 96"><defs><filter id="master_svg0_143_35978" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="-0.6666666666666666" y="-0.6666666666666666" width="2.3333333333333335" height="2.3333333333333335"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="0" dx="0"/><feGaussianBlur stdDeviation="8"/><feColorMatrix type="matrix" values="0 0 0 0 0.12895070016384125 0 0 0 0 0.29307788610458374 0 0 0 0 0.9107142686843872 0 0 0 0.5299999713897705 0"/><feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/><feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/></filter><clipPath id="master_svg1_143_35983"><rect x="32.78466796875" y="36" width="23" height="23" rx="0"/></clipPath></defs><path d="M44.78466796875,24.000000000000004L65.56927496875,36L65.56927496875,60L44.78466796875,72L24.00005836875,60L24.00005796875,36.000001L44.78466796875,24.000000000000004Z" fill="#496FFE" fill-opacity="1" filter="url(#master_svg0_143_35978)"/><g clip-path="url(#master_svg1_143_35983)"><path d="M44.950077965625,36Q45.615746465625,36,46.269937765625,36.14920157Q46.924129765625,36.29840314,47.497981765625,36.55089813Q48.071835765624996,36.80339313,48.519438765625,37.124750399999996Q48.967043765625,37.4461077,49.219538765625,37.7674649Q49.816345765625,38.5019956,50.091794765624996,39.3857281Q50.367244765625,40.269460699999996,50.482013765625,41.0728536Q50.596784765625,41.9910169,50.596784765625,42.9321346Q50.757463765625,43.046905,50.849280765625,43.2305379Q50.941096765625,43.391216299999996,50.998480765625004,43.6437116Q51.055866765625,43.8962064,51.009958765625,44.2634716Q50.964050765625004,44.7455082,50.814847765625004,45.032433499999996Q50.665645765625,45.3193598,50.482013765625,45.4800377Q50.275426765625,45.6636715,50.045885765625,45.7325335Q49.931114765625,46.122753,49.816345765625,46.467065Q49.701575765625,46.765468,49.552372765625,47.052393Q49.403172765625,47.339319,49.219538765625,47.499997Q48.783411765625004,47.844309,48.507961765625,48.085328000000004Q48.232512765625,48.326347,48.140695765625,48.900198Q48.071834765625,49.244509,48.094788765625,49.600298Q48.117743765625,49.956086,48.289897765625,50.311875Q48.462053765625,50.667664,48.817842765625,50.989021Q49.173630765625,51.310377,49.816345765625,51.562872999999996Q50.390198765625,51.792412999999996,51.067343765625,51.976046Q51.744489765625005,52.159679,52.387202765625,52.400695999999996Q53.029916765625,52.641714,53.523429765624996,52.997502999999995Q54.016944765625,53.353291,54.223531765625,53.973051Q54.338302765625,54.340319,54.395686765625,54.879736Q54.453071765625,55.419159,54.453071765625,55.970057Q54.453071765625,56.520954,54.372731765625005,57.002989Q54.292394765625005,57.485027,54.131713765625,57.73752Q54.016944765625,57.898201,53.477523765625,58.058878Q52.938104765625,58.219556999999995,52.146186765625,58.368757Q51.354269765625,58.51796,50.378720765625,58.632729999999995Q49.403173765625,58.747501,48.416146765625,58.827839Q47.429119765625,58.908178,46.522433765624996,58.954088Q45.615747465625,58.999995999999996,44.950078965624996,58.999994Q44.284410465625,58.999994,43.400678165625,58.954088Q42.516944865625,58.908182,41.575827565625,58.827841Q40.634709865625,58.747501,39.705069065625,58.644209000000004Q38.775428565625,58.540915999999996,38.017943365625,58.426144Q37.260458465625,58.311375,36.732514365625,58.196604Q36.204570295625,58.081837,36.066845565625,57.967064Q35.837304725625,57.783429999999996,35.711057230625,56.842314Q35.584809735625,55.901196,35.814350605625,54.40918Q35.929121195625,53.559877,36.491496265625,53.112272000000004Q37.053871265625,52.664669,37.799879565625,52.400695999999996Q38.545887665625,52.136724,39.349280365625,51.930138Q40.152672765625,51.723553,40.772433265625,51.333332Q41.254469865625,51.03493,41.506964665625,50.759479999999996Q41.759460465625,50.484030000000004,41.874229865625,50.208582Q41.989000365625,49.933134,41.989000365625,49.63473Q41.989000365625,49.336327,41.966046765625,48.969062Q41.920138365625,48.441118,41.598781565625,48.131239Q41.277424365625,47.821359,40.887204665625,47.5Q40.703571765625,47.339321,40.565847865625,47.052395000000004Q40.428123965625,46.765468999999996,40.313353065625,46.467067Q40.198582165625,46.122755,40.083811765625,45.7325354Q39.923133365625,45.6866264,39.762454465625,45.5718565Q39.624729865625,45.4570866,39.464051465625,45.2504997Q39.303372865625,45.0439129,39.188602665625,44.653694200000004Q39.050877765625,44.2634735,39.085309065625,43.9421172Q39.119739965625,43.62076,39.211556165625,43.391218699999996Q39.303372865625,43.1387234,39.509959465625,42.9091825Q39.487005965625,42.0369272,39.601776165625,41.1646714Q39.693592565624996,40.4301405,39.934610365625,39.5808394Q40.175627665625,38.7315381,40.657664265625,38.0658693Q41.093792465625,37.423155,41.633213065625,37.0214585Q42.172633665625,36.61976188,42.735009665625,36.390221Q43.297384765625,36.16068012,43.859759365625,36.080340803Q44.422134365625,36.0000014994291,44.950077965625,36Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/xiaoshoutaizhang.svg b/src/assets/system/xiaoshoutaizhang.svg
new file mode 100644
index 0000000..9880541
--- /dev/null
+++ b/src/assets/system/xiaoshoutaizhang.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="63.90625" viewBox="0 0 59.5 63.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35617"><rect x="13.5" y="0" width="32" height="32" rx="0"/></clipPath></defs><path d="M1.204819142818451,27.096379L28.69276814281845,43.307213000000004L58.29516614281845,27.096379L28.69276814281845,13L1.204819142818451,27.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,27.065809L28.43877614281845,43.737896L28.68361514281845,43.882288L59.39288714281845,27.065309L28.684561142818453,12.44229615L0.16870074281845082,27.065809ZM28.70192014281845,42.732138L2.240937742818451,27.12695L28.70097614281845,13.55770427L57.19744514281845,27.127449L28.70192014281845,42.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,27.80120277404785L0.5,46.83131777404785L28.692764,63.042150774047855L28.692764,44.01204077404785L0.5,27.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,63.906411774047854L29.192764,43.722777774047856L28.941999,43.578587774047854L-5.999999996841865e-8,26.93693918404785L0,47.12058077404785L29.192764,63.906411774047854ZM28.192764,44.30130377404785L28.192764,62.17788877404785L1,46.542054774047855L1,28.66546636404785L28.192764,44.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,27.80120277404785L59,46.12649377404785L88.5,63.00042177404785L88.5,43.26604677404785L59,27.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,63.86243677404785L89,42.96362277404785L88.732151,42.82320777404785L58.50000003,26.97454732404785L58.50000003,46.41651177404785L89,63.86243677404785ZM88,43.568469774047855L88,62.13840677404785L59.5,45.836475774047855L59.5,28.627858224047852L88,43.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35617)"><path d="M36.903126,3.015625L22.0968752,3.015625C20.6062503,3.015625,19.4000001,4.2249999,19.4000001,5.7125001L19.4000001,17.44375L39.6,17.44375L39.6,5.7125001C39.6,4.2218751999999995,38.390625,3.015625,36.903126,3.015625ZM26.615625,14.556249L22.2843752,14.556249C21.4875002,14.556249,20.8406253,13.909374,20.8406253,13.112499C20.8406253,12.3156242,21.4875002,11.6687489,22.2843752,11.6687489L26.6125,11.6687489C27.409375,11.6687489,28.056251,12.3156242,28.056251,13.112499C28.056251,13.912499,27.4125,14.556249,26.615625,14.556249ZM32.384377,7.4312496C32.384377,8.181249600000001,31.778126,8.7874994,31.028126,8.7874994L22.1999993,8.7874994C21.4499993,8.7874994,20.84375,8.181249600000001,20.84375,7.4312496L20.84375,7.2593746C20.84375,6.5093746,21.4499993,5.9031248000000005,22.1999993,5.9031248000000005L31.03125,5.9031248000000005C31.78125,5.9031248000000005,32.387501,6.5093746,32.387501,7.2593746L32.387501,7.4312496L32.384377,7.4312496ZM39.600002,20.328125L19.4000001,20.328125C17.8062501,20.328125,16.515625,21.61875,16.515625,23.2125L16.515625,26.096872C16.515625,26.862497,16.81874993,27.596872,17.359375,28.137499C17.9000001,28.678123,18.6343751,28.981249,19.4000001,28.981249L39.6,28.981249C40.365625,28.981249,41.1,28.678123,41.640625,28.137499C42.18125,27.596872,42.484375,26.862497,42.484375,26.096872L42.484375,23.2125C42.484375,21.621874,41.19375,20.328125,39.600002,20.328125ZM20.84375,26.1C20.2593751,26.1,19.734375,25.746876,19.5093751,25.209375C19.2874997,24.668751,19.4093752,24.050001,19.8218751,23.637501C20.234375,23.225,20.8562498,23.1,21.3937502,23.325001C21.9343743,23.546875,22.2843752,24.075001,22.2843752,24.659376C22.2843752,25.453127,21.640625,26.1,20.84375,26.1ZM26.615625,26.1C26.03125,26.1,25.5062504,25.746876,25.28125,25.209375C25.0593748,24.668751,25.1812496,24.050001,25.59375,23.637501C26.0062504,23.225,26.628125,23.1,27.165624,23.325001C27.706249,23.546875,28.056249,24.075001,28.056249,24.659376C28.056249,25.453127,27.412499,26.1,26.615625,26.1Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/xiaoshoutuihuo.svg b/src/assets/system/xiaoshoutuihuo.svg
new file mode 100644
index 0000000..bcacee2
--- /dev/null
+++ b/src/assets/system/xiaoshoutuihuo.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35635"><rect x="12.5" y="0" width="34.000003814697266" height="34" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35635)"><path d="M16.5,17.5C16.5,10.0479994,22.547999400000002,4,30,4C37.452,4,43.5,10.0479999,43.5,17.5C43.5,24.952,37.452,31,30,31C22.547999400000002,31,16.5,24.952,16.5,17.5ZM25.2099543,11.2335448C25.056938199999998,11.1590481,24.889226,11.1196365,24.719044699999998,11.118180800000001C24.4576359,11.118180800000001,24.2600451,11.2102261,24.1250448,11.3930907C23.965045,11.566371,23.8772473,11.7942061,23.8795905,12.0300455C23.8795905,12.2902269,23.9716368,12.4779997,24.1545,12.5945911C24.1946921,12.6422205,24.2439098,12.681428,24.2993183,12.7099552C24.812317800000002,13.0376368,25.309363400000002,13.3910923,25.789226499999998,13.7654095C25.875135399999998,13.8550005,25.9782276,13.9249544,26.0935907,13.9691372C26.1991358,14.026819,26.3292265,14.055046,26.4838629,14.055046C26.763681,14.046455,26.98459,13.9114552,27.149045,13.6500463C27.266969,13.4697084,27.327709,13.2579737,27.323318,13.0425463C27.319848,12.8229294,27.219160000000002,12.6161594,27.048409,12.4780006C26.492164600000002,11.9851937,25.874157,11.5668635,25.2099543,11.2335448ZM34.731136,11.2924538L29.478408,11.2924538C28.610726,11.2924538,28.177500000000002,11.648363100000001,28.177500000000002,12.3626356L28.177500000000002,19.944725C28.176272,20.042908,28.18609,20.138634,28.205727,20.234362C28.070726,20.349726,28.003225999999998,20.553452,28.003225999999998,20.841862C28.013044999999998,21.11186,28.070726,21.309452,28.176271,21.434633C28.292863,21.569633,28.500272000000002,21.637133,28.798499,21.637133C29.464908,21.637133,30.404999,21.487406,31.621223999999998,21.189178C31.861770999999997,21.140087,32.026225,21.059088,32.112133,20.943726C32.243669,20.79126,32.310976,20.593739,32.299906,20.392679C32.299906,20.17177,32.252043,19.997498,32.156316000000004,19.872315999999998C32.033533,19.737026,31.860347,19.658427,31.677678999999998,19.655088C31.157317,19.732407000000002,30.632043,19.804814999999998,30.100635,19.872315999999998L30.100635,17.455816L34.673452,17.455816C34.759361,17.455816,34.837906000000004,17.450908,34.905409,17.441088999999998C34.893873,17.462564,34.878954,17.482039999999998,34.861225000000005,17.498772000000002C34.521141,17.859035,34.158792,18.197606999999998,33.776316,18.512499C33.275587,18.193407999999998,32.749089999999995,17.895182,32.199270999999996,17.615363000000002C32.035903,17.54202,31.857872,17.507168,31.678905999999998,17.513499C31.417496999999997,17.513499,31.21009,17.590817,31.056679000000003,17.745455C30.902043,17.880454999999998,30.823497,18.082954,30.823497,18.352954C30.828218,18.505149,30.890499,18.649888,30.997768,18.757953999999998C31.051738999999998,18.809553,31.116205,18.848902000000002,31.186768999999998,18.873317999999998C32.266769,19.520091999999998,33.48177,20.369364,34.831768,21.419909C35.01586,21.604,35.246586,21.694817,35.527632,21.694817C35.766716,21.695692,35.992073000000005,21.583241,36.135132,21.39168C36.289076,21.227486,36.371994,21.009171,36.36586,20.78418C36.362389,20.564564,36.261703,20.357796,36.090952,20.219635C35.802544,19.968045,35.503088000000005,19.728727,35.195042,19.495544000000002C35.705585,19.197316999999998,36.115498,18.873317,36.424769999999995,18.526C36.533014,18.357194,36.592867,18.161924,36.597816,17.961454C36.611883,17.651581,36.456854,17.358437000000002,36.192816,17.195636999999998C36.041086,17.073852000000002,35.852282,17.007597,35.657722,17.007863999999998C35.753451999999996,16.853229,35.802544,16.645819,35.802544,16.385637L35.802544,12.3626366C35.802544,11.6483641,35.445406,11.2924547,34.731136,11.2924538ZM33.878181,13.664773L30.100636,13.664773L30.100636,13.1002264C30.100636,12.9468174,30.192681999999998,12.8695002,30.375545000000002,12.8695002L33.603271,12.8695002C33.786135,12.8695002,33.87818,12.9468174,33.87818,13.1002264L33.878181,13.664773ZM33.603271,15.864044L30.100636,15.864044L30.100636,15.02459L33.878181,15.02459L33.878181,15.646818C33.878181,15.791636,33.786135,15.864044,33.603271,15.864044ZM25.6296825,15.473772L24.2698641,15.473772C23.9507732,15.473772,23.724954099999998,15.546182,23.5899544,15.690999C23.4451365,15.844409,23.3727274,16.076363999999998,23.3727274,16.385635C23.3727274,16.723136,23.4402275,16.950181999999998,23.5752277,17.065544C23.6905913,17.248407,23.9225464,17.340454,24.2698641,17.340454L24.834409700000002,17.340454C24.9497738,17.340454,25.0074549,17.398136,25.0074549,17.513499L25.0074549,21.637135C25.0074549,21.714453,24.9546824,21.786861,24.847909899999998,21.854361C24.4527292,22.139252,24.0315437,22.386209,23.5899544,22.591951C23.4451365,22.698725,23.3727274,22.814087,23.3727274,22.939268C23.3771172,23.0942,23.4117188,23.246782,23.4745903,23.388451C23.6476359,23.697725,23.835408700000002,23.943178,24.0391369,24.126041C24.1385455,24.200905,24.260046,24.242634,24.3852277,24.242634C24.5752201,24.217705,24.7579012,24.153328,24.921546,24.053633C25.228364,23.907587,25.5204544,23.728407,25.7892284,23.518543C25.8849545,23.432632,25.9622736,23.388451,26.0211821,23.388451C26.132575,23.390455,26.2397785,23.431255,26.3243189,23.503817C27.153955,23.842543,28.572682999999998,24.010681,30.578046,24.010681L35.97559,24.010681C36.313091,23.991043,36.545048,23.900225,36.670227,23.735771C36.805227,23.61059,36.872726,23.363907,36.872726,22.99818C36.872726,22.67909,36.790501,22.453272,36.627274,22.317045C36.492271,22.201681,36.294682,22.144001,36.033272,22.144001C35.368092000000004,22.144001,34.566679,22.163635,33.6315,22.201681C32.551497999999995,22.239727,31.379454000000003,22.259361,30.115364,22.259361C28.996092,22.259361,28.114910000000002,22.191862,27.468138,22.056862C27.071728999999998,21.979544,26.874138000000002,21.8605,26.874138000000002,21.694817L26.874138000000002,16.601637C26.874138000000002,15.849319,26.4593201,15.472546,25.6296825,15.472546L25.6296825,15.473772Z" fill="#BC49FE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/yonghuguanli.svg b/src/assets/system/yonghuguanli.svg
new file mode 100644
index 0000000..a8365a7
--- /dev/null
+++ b/src/assets/system/yonghuguanli.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35539"><rect x="12.5" y="0" width="34.000003814697266" height="34" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35539)"><path d="M31.6272783125,19.833336L31.6272783125,19.125002C31.6272783125,18.735416,31.3085343125,18.416668,30.9189493125,18.416668L28.0856153125,18.416668C27.696029312500002,18.416668,27.3772793125,18.735416,27.3772793125,19.125002L27.3772793125,19.833336C27.3772793125,20.222919,27.696029312500002,20.541668,28.0856153125,20.541668L28.5106133125,20.541668L27.4056153125,24.664169C27.3914463125,24.742083,27.4056153125,24.827087,27.455197312499998,24.890835L29.162277312500002,27.171669C29.3322813125,27.398335,29.672281312499997,27.398335,29.8422813125,27.171669L31.5493633125,24.890835C31.598944312500002,24.827087,31.613113312499998,24.742083,31.598944312500002,24.664169L30.493948312500002,20.541674L30.918943312499998,20.541674C31.3085323125,20.541674,31.6272763125,20.222921,31.6272783125,19.833336ZM29.5022783125,17.708334999999998C25.9960270125,17.708334999999998,23.1272793125,14.839586,23.1272793125,11.3333368L23.1272793125,8.5C23.1272793125,4.9937501,25.9960270125,2.125,29.5022783125,2.125C33.008526312499995,2.125,35.8772793125,4.9937501,35.8772793125,8.5L35.8772793125,11.3333368C35.8772793125,14.839586,33.008526312499995,17.708334999999998,29.5022783125,17.708334999999998ZM38.172279312499995,19.125002L36.557281312499995,18.770834C36.2597753125,18.707085,35.9481063125,18.841665,35.7993643125,19.110832L29.9414463125,29.601257C29.7501973125,29.941248,29.2543643125,29.941248,29.0631123125,29.601257L23.0493646125,18.834585C22.9010763125,18.564627,22.5916772125,18.425833,22.2914457125,18.494585L19.4156120125,19.125002C17.4497964125,19.53912,16.04301562917,21.273962,16.0439453125,23.282919L16.0439453125,28.333334C16.0439453125,29.898754,17.3118622125,31.166664,18.877278812500002,31.166664L38.7106133125,31.166664C40.2760293125,31.166664,41.543947312499995,29.898754,41.543947312499995,28.333334L41.543947312499995,23.282919C41.543947312499995,21.27125,40.134359312499996,19.535837,38.172279312499995,19.125002Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/zhibiaotongji.svg b/src/assets/system/zhibiaotongji.svg
new file mode 100644
index 0000000..00e97bb
--- /dev/null
+++ b/src/assets/system/zhibiaotongji.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35654"><rect x="14.5" y="0" width="30" height="30" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35654)"><path d="M27.329689375,4.0806096499999995C21.384180075,4.72396945,16.755859375,9.759809449999999,16.755859375,15.87641125C16.755859375,22.42924525,22.068262575,27.74164625,28.621094375,27.74164625C34.737697374999996,27.74164625,39.773244375000004,23.11332725,40.416896375,17.16781625C40.491603375,16.47728925,39.945509375,15.87641025,39.251175375,15.87641025L29.792969375,15.87641025C29.145801374999998,15.87641025,28.621094375,15.35170425,28.621094375,14.70453425L28.621094375,5.246332649999999C28.621094375,4.55199675,28.020215375,4.00590305,27.329689375,4.0806096499999995ZM30.378907375,3.48881295L30.378907375,12.94672425C30.378907375,13.59389225,30.903614375,14.11859925,31.550782375,14.11859925L41.008691375,14.11859925C41.705665374999995,14.11859925,42.249416374999996,13.51391025,42.174123375,12.82104025C41.573829375,7.30473135,37.192775375,2.92367607,31.676466375,2.3233831231C30.983595375,2.248090155,30.378907375,2.79184017,30.378907375,3.48881295Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/assets/system/zhushengchanjihua.svg b/src/assets/system/zhushengchanjihua.svg
new file mode 100644
index 0000000..8573eac
--- /dev/null
+++ b/src/assets/system/zhushengchanjihua.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_36341"><rect x="14.5" y="0" width="32" height="32" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_36341)"><path d="M32.56859821875,27.56376125L32.42002721875,27.42661825C32.09464421875,27.10965125,31.90252121875,26.68043925,31.882883218750003,26.22661825L30.74002621875,26.22661825L30.74002621875,3.88376141C30.73742821875,3.43834615,30.27823221875,3.14228559,29.87145421875,3.323761463L19.80288311875,7.52947525C19.35276551875,7.73022935,19.06522271875,8.17951485,19.07145451875,8.672332749999999L19.07145451875,26.21518925L18.10002588875,26.21518925C17.62617706875,26.21453525,17.24169921875,26.59848025,17.24169921875,27.07232825C17.24169921875,27.54617925,17.62617683875,27.93012825,18.10002588875,27.92947425L33.17431221875,27.92947425L32.78574221875,27.66661625L32.56859821875,27.56376125ZM37.35717021875,16.84376125C37.73498121875,16.60642825,38.168478218749996,16.47243925,38.61431321875,16.45519025C38.94686521875,16.46270525,39.27405121875,16.54060725,39.574312218749995,16.68376125L41.860027218750005,17.66661825L41.860027218750005,12.44376185C41.86428221875,11.94822695,41.57176021875,11.49819085,41.117170218750005,11.30090525L32.47716921875,7.99804685L32.47716921875,19.083761250000002C32.64974421875,18.88615425,32.86457421875,18.72991325,33.10573921875,18.626617250000002L37.35717021875,16.84376125ZM43.551454218749996,20.45519025C43.59511021875,20.43103825,43.62220421875,20.38508225,43.62220421875,20.33519125C43.62220421875,20.28530125,43.59511021875,20.23934525,43.551454218749996,20.21519125L41.92859621875,19.52947625L38.91145521875,18.283762250000002C38.82957221875,18.240982250000002,38.740429218749995,18.213852250000002,38.64859721875,18.20376225C38.464931218749996,18.25888025,38.28845821875,18.335607250000002,38.122883218750005,18.43233325L33.74573921875,20.20376225C33.70786821875,20.20376225,33.67716821875,20.23446225,33.67716821875,20.27233325C33.67716821875,20.31020325,33.70786821875,20.34090425,33.74573921875,20.34090425L38.591453218750004,23.06090325L38.86574021875,23.06090325L41.92859621875,21.34661825L43.551454218749996,20.45519025ZM43.82574121875,21.01519025L41.92859821875,22.04376225L39.06002621875,23.62090525C39.04922821875,23.64647825,39.04922821875,23.67533125,39.06002621875,23.70090525L39.06002621875,28.92376125C39.053015218750005,28.97232025,39.09096521875,29.01569325,39.140026218749995,29.01519025L40.945740218750004,27.94090425L43.72288321875,26.28376225L43.87145421875,26.19233325L43.87145421875,21.10661925C43.88021121875,21.06911125,43.86100021875,21.03068925,43.82574121875,21.01519025ZM33.72288321875,21.04947425C33.673822218750004,21.04897125,33.635872218749995,21.09234425,33.64288321875,21.14090325L33.64288321875,26.13518925C33.632086218750004,26.16076325,33.632086218750004,26.18961525,33.64288321875,26.21518925L36.52288421875,27.94090225L38.351455218750004,29.08375925C38.40051621875,29.08426325,38.43846721875,29.04089125,38.43145521875,28.99233025L38.43145521875,23.72375825C38.44225121875,23.69818325,38.44225121875,23.66933225,38.43145521875,23.64375925L33.72288321875,21.04947425ZM35.15145521875,23.52947425C34.991022218750004,23.45744525,34.94520021875,23.25124325,35.06002621875,23.11804625C35.11695121875,23.02876325,35.217087218749995,22.97651625,35.32288321875,22.98090325C35.37916521875,22.96686925,35.43803021875,22.96686925,35.49431221875,22.98090325L37.78002721875,24.23804625C37.919319218750005,24.32610925,37.960340218750005,24.51070625,37.87145621875,24.64947525C37.81297721875,24.73704525,37.71387821875,24.78874825,37.608598218750004,24.78661725C37.55167421875,24.79367025,37.49409721875,24.79367025,37.43717021875,24.78661725L35.15145521875,23.52947425Z" fill="#496FFE" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git "a/src/assets/system/\347\273\204 210683.svg" "b/src/assets/system/\347\273\204 210683.svg"
new file mode 100644
index 0000000..bea3701
--- /dev/null
+++ "b/src/assets/system/\347\273\204 210683.svg"
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="59.5" height="64.90625" viewBox="0 0 59.5 64.90625"><defs><linearGradient x1="0" y1="0.16914062201976776" x2="0.8045321262753937" y2="1.0460527890370677" id="master_svg0_141_37616"><stop offset="48.549023270606995%" stop-color="#F7F7F7" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="-0.03565644100308418" y1="0" x2="0.8226521556701855" y2="0.9991461352834076" id="master_svg1_141_37562"><stop offset="46.036821603775024%" stop-color="#F3F3F3" stop-opacity="1"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><clipPath id="master_svg2_143_35787"><rect x="12.5" y="0" width="34.000003814697266" height="34" rx="0"/></clipPath></defs><path d="M1.204819142818451,28.096379L28.69276814281845,44.307213000000004L58.29516614281845,28.096379L28.69276814281845,14L1.204819142818451,28.096379Z" fill="#FFFFFF" fill-opacity="1"/><path d="M0.16870074281845082,28.065809L28.43877614281845,44.737896L28.68361514281845,44.882288L59.39288714281845,28.065309L28.684561142818453,13.44229615L0.16870074281845082,28.065809ZM28.70192014281845,43.732138L2.240937742818451,28.12695L28.70097614281845,14.55770427L57.19744514281845,28.127449L28.70192014281845,43.732138Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><path d="M0.5,28.80120277404785L0.5,47.83131777404785L28.692764,64.04215077404785L28.692764,45.01204077404785L0.5,28.80120277404785Z" fill="url(#master_svg0_141_37616)" fill-opacity="1"/><path d="M29.192764,64.90641177404785L29.192764,44.722777774047856L28.941999,44.578587774047854L-5.999999996841865e-8,27.93693918404785L0,48.12058077404785L29.192764,64.90641177404785ZM28.192764,45.30130377404785L28.192764,63.17788877404785L1,47.542054774047855L1,29.66546636404785L28.192764,45.30130377404785Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/><g transform="matrix(-1,0,0,1,118,0)"><path d="M59,28.80120277404785L59,47.12649377404785L88.5,64.00042177404785L88.5,44.26604677404785L59,28.80120277404785Z" fill="url(#master_svg1_141_37562)" fill-opacity="1"/><path d="M89,64.86243677404785L89,43.96362277404785L88.732151,43.82320777404785L58.50000003,27.97454732404785L58.50000003,47.41651177404785L89,64.86243677404785ZM88,44.568469774047855L88,63.13840677404785L59.5,46.836475774047855L59.5,29.627858224047852L88,44.568469774047855Z" fill-rule="evenodd" fill="#ECECEC" fill-opacity="1"/></g><g clip-path="url(#master_svg2_143_35787)"><path d="M16.5,17.5C16.5,10.0479994,22.547999400000002,4,30,4C37.452,4,43.5,10.0479999,43.5,17.5C43.5,24.952,37.452,31,30,31C22.547999400000002,31,16.5,24.952,16.5,17.5ZM25.2099543,11.2335448C25.056938199999998,11.1590481,24.889226,11.1196365,24.719044699999998,11.118180800000001C24.4576359,11.118180800000001,24.2600451,11.2102261,24.1250448,11.3930907C23.965045,11.566371,23.8772473,11.7942061,23.8795905,12.0300455C23.8795905,12.2902269,23.9716368,12.4779997,24.1545,12.5945911C24.1946921,12.6422205,24.2439098,12.681428,24.2993183,12.7099552C24.812317800000002,13.0376368,25.309363400000002,13.3910923,25.789226499999998,13.7654095C25.875135399999998,13.8550005,25.9782276,13.9249544,26.0935907,13.9691372C26.1991358,14.026819,26.3292265,14.055046,26.4838629,14.055046C26.763681,14.046455,26.98459,13.9114552,27.149045,13.6500463C27.266969,13.4697084,27.327709,13.2579737,27.323318,13.0425463C27.319848,12.8229294,27.219160000000002,12.6161594,27.048409,12.4780006C26.492164600000002,11.9851937,25.874157,11.5668635,25.2099543,11.2335448ZM34.731136,11.2924538L29.478408,11.2924538C28.610726,11.2924538,28.177500000000002,11.648363100000001,28.177500000000002,12.3626356L28.177500000000002,19.944725C28.176272,20.042908,28.18609,20.138634,28.205727,20.234362C28.070726,20.349726,28.003225999999998,20.553452,28.003225999999998,20.841862C28.013044999999998,21.11186,28.070726,21.309452,28.176271,21.434633C28.292863,21.569633,28.500272000000002,21.637133,28.798499,21.637133C29.464908,21.637133,30.404999,21.487406,31.621223999999998,21.189178C31.861770999999997,21.140087,32.026225,21.059088,32.112133,20.943726C32.243669,20.79126,32.310976,20.593739,32.299906,20.392679C32.299906,20.17177,32.252043,19.997498,32.156316000000004,19.872315999999998C32.033533,19.737026,31.860347,19.658427,31.677678999999998,19.655088C31.157317,19.732407000000002,30.632043,19.804814999999998,30.100635,19.872315999999998L30.100635,17.455816L34.673452,17.455816C34.759361,17.455816,34.837906000000004,17.450908,34.905409,17.441088999999998C34.893873,17.462564,34.878954,17.482039999999998,34.861225000000005,17.498772000000002C34.521141,17.859035,34.158792,18.197606999999998,33.776316,18.512499C33.275587,18.193407999999998,32.749089999999995,17.895182,32.199270999999996,17.615363000000002C32.035903,17.54202,31.857872,17.507168,31.678905999999998,17.513499C31.417496999999997,17.513499,31.21009,17.590817,31.056679000000003,17.745455C30.902043,17.880454999999998,30.823497,18.082954,30.823497,18.352954C30.828218,18.505149,30.890499,18.649888,30.997768,18.757953999999998C31.051738999999998,18.809553,31.116205,18.848902000000002,31.186768999999998,18.873317999999998C32.266769,19.520091999999998,33.48177,20.369364,34.831768,21.419909C35.01586,21.604,35.246586,21.694817,35.527632,21.694817C35.766716,21.695692,35.992073000000005,21.583241,36.135132,21.39168C36.289076,21.227486,36.371994,21.009171,36.36586,20.78418C36.362389,20.564564,36.261703,20.357796,36.090952,20.219635C35.802544,19.968045,35.503088000000005,19.728727,35.195042,19.495544000000002C35.705585,19.197316999999998,36.115498,18.873317,36.424769999999995,18.526C36.533014,18.357194,36.592867,18.161924,36.597816,17.961454C36.611883,17.651581,36.456854,17.358437000000002,36.192816,17.195636999999998C36.041086,17.073852000000002,35.852282,17.007597,35.657722,17.007863999999998C35.753451999999996,16.853229,35.802544,16.645819,35.802544,16.385637L35.802544,12.3626366C35.802544,11.6483641,35.445406,11.2924547,34.731136,11.2924538ZM33.878181,13.664773L30.100636,13.664773L30.100636,13.1002264C30.100636,12.9468174,30.192681999999998,12.8695002,30.375545000000002,12.8695002L33.603271,12.8695002C33.786135,12.8695002,33.87818,12.9468174,33.87818,13.1002264L33.878181,13.664773ZM33.603271,15.864044L30.100636,15.864044L30.100636,15.02459L33.878181,15.02459L33.878181,15.646818C33.878181,15.791636,33.786135,15.864044,33.603271,15.864044ZM25.6296825,15.473772L24.2698641,15.473772C23.9507732,15.473772,23.724954099999998,15.546182,23.5899544,15.690999C23.4451365,15.844409,23.3727274,16.076363999999998,23.3727274,16.385635C23.3727274,16.723136,23.4402275,16.950181999999998,23.5752277,17.065544C23.6905913,17.248407,23.9225464,17.340454,24.2698641,17.340454L24.834409700000002,17.340454C24.9497738,17.340454,25.0074549,17.398136,25.0074549,17.513499L25.0074549,21.637135C25.0074549,21.714453,24.9546824,21.786861,24.847909899999998,21.854361C24.4527292,22.139252,24.0315437,22.386209,23.5899544,22.591951C23.4451365,22.698725,23.3727274,22.814087,23.3727274,22.939268C23.3771172,23.0942,23.4117188,23.246782,23.4745903,23.388451C23.6476359,23.697725,23.835408700000002,23.943178,24.0391369,24.126041C24.1385455,24.200905,24.260046,24.242634,24.3852277,24.242634C24.5752201,24.217705,24.7579012,24.153328,24.921546,24.053633C25.228364,23.907587,25.5204544,23.728407,25.7892284,23.518543C25.8849545,23.432632,25.9622736,23.388451,26.0211821,23.388451C26.132575,23.390455,26.2397785,23.431255,26.3243189,23.503817C27.153955,23.842543,28.572682999999998,24.010681,30.578046,24.010681L35.97559,24.010681C36.313091,23.991043,36.545048,23.900225,36.670227,23.735771C36.805227,23.61059,36.872726,23.363907,36.872726,22.99818C36.872726,22.67909,36.790501,22.453272,36.627274,22.317045C36.492271,22.201681,36.294682,22.144001,36.033272,22.144001C35.368092000000004,22.144001,34.566679,22.163635,33.6315,22.201681C32.551497999999995,22.239727,31.379454000000003,22.259361,30.115364,22.259361C28.996092,22.259361,28.114910000000002,22.191862,27.468138,22.056862C27.071728999999998,21.979544,26.874138000000002,21.8605,26.874138000000002,21.694817L26.874138000000002,16.601637C26.874138000000002,15.849319,26.4593201,15.472546,25.6296825,15.472546L25.6296825,15.473772Z" fill="#3BB078" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>
\ No newline at end of file
diff --git a/src/components/AIChatSidebar/assistants/financeAssistant.js b/src/components/AIChatSidebar/assistants/financeAssistant.js
index e8df3f4..f5dd7c6 100644
--- a/src/components/AIChatSidebar/assistants/financeAssistant.js
+++ b/src/components/AIChatSidebar/assistants/financeAssistant.js
@@ -14,13 +14,15 @@
allowFileUpload: false,
emptySessionText: '鏆傛棤璐㈠姟浼氳瘽',
quickPrompts: [
+ '鏌ョ湅缁忚惀椹鹃┒鑸�',
+ '鏌ョ湅鏈湀缁忚惀椹鹃┒鑸�',
'鐢熸垚鏈懆缁忚惀鍛ㄦ姤锛堝埄娑︿笌鐜伴噾娴侊級',
'鍒嗘瀽鏈湀鍒╂鼎涓嬮檷鍘熷洜',
- '杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂�',
- '鏌ョ湅鏈湀缁忚惀椹鹃┒鑸�',
'鏌ヨ杩�30澶╀簭鎹熻鍗�',
+ '杩�30澶╁摢涓鎴峰埄娑﹁础鐚渶楂�',
'鍒嗘瀽杩�30澶╁簱瀛樿祫閲戝崰鐢�',
'棰勬祴鏈潵3涓湀鐜伴噾娴�',
+ '鏌ヨ搴旀敹鍥炴椋庨櫓',
'鍝釜宸ュ簭鎴愭湰鏈�楂�'
]
}
diff --git a/src/components/AIChatSidebar/assistants/productionAssistant.js b/src/components/AIChatSidebar/assistants/productionAssistant.js
index fb2d737..d5b4924 100644
--- a/src/components/AIChatSidebar/assistants/productionAssistant.js
+++ b/src/components/AIChatSidebar/assistants/productionAssistant.js
@@ -14,14 +14,15 @@
allowFileUpload: false,
emptySessionText: '鏆傛棤鐢熶骇浼氳瘽',
quickPrompts: [
- '鏌ヨ鏈湀鐢熶骇璁″垝',
- '鏌ョ湅鏈�杩�10鏉″伐鍗�',
- '鏌ヨ澶嘇-01鐨勭淮淇儏鍐�',
- '鏌ヨ川閲忎笉鍚堟牸璁板綍',
- '鏌ヤ綆搴撳瓨鐗╂枡',
- '鏌ヨ繎7澶╁紓甯稿鐞�',
- '鐢熸垚鍒堕�犻璀︾湅鏉�',
- '鍒嗘瀽鏈湀鐢熶骇瀹屾垚鐜囧拰寮傚父鐜�',
- '缁欏嚭宸ュ崟閫炬湡鍜岃澶囧緟淇殑鍔炵悊寤鸿'
+ '鏌ヨ鐢熶骇鐜板満鏁版嵁',
+ '鏌ヨ鐢熶骇璁″垝鎵ц鎯呭喌',
+ '鏌ヨ宸ュ崟鎵ц鎯呭喌',
+ '鏌ヨ璁惧杩愯鎯呭喌',
+ '鏌ヨ璐ㄩ噺寮傚父鏁版嵁',
+ '鏌ヨ鐗╂枡鐩稿叧鏁版嵁',
+ '鏌ョ湅鍒堕�犻璀︾湅鏉�',
+ '鍒嗘瀽鏈湀鍒堕�犵粡钀ユ儏鍐�',
+ '鍒嗘瀽杩�7澶╃敓浜у紓甯�',
+ '鐢熸垚鍒堕�犲姙鐞嗗缓璁�'
]
}
diff --git a/src/components/AIChatSidebar/assistants/purchaseAssistant.js b/src/components/AIChatSidebar/assistants/purchaseAssistant.js
index 4f2e72c..5dd85e7 100644
--- a/src/components/AIChatSidebar/assistants/purchaseAssistant.js
+++ b/src/components/AIChatSidebar/assistants/purchaseAssistant.js
@@ -16,10 +16,15 @@
fileAnalyzeUrl: '/purchase-ai/analyze-files',
emptySessionText: '鏆傛棤閲囪喘浼氳瘽',
quickPrompts: [
- '鏈湀閲囪喘閲戦鎺掑悕鍓嶅崄鐨勭墿鏂欐湁鍝簺锛�',
- '鍝簺閲囪喘璁㈠崟杩樻湭鍏ュ簱锛�',
- '鏈�杩�7澶╀緵搴斿晢鍒拌揣寮傚父鏈夊摢浜涳紵',
- '甯垜缁熻寰呬粯娆鹃噰璐崟锛�',
- '鍒楀嚭鏈湀閲囪喘閫�璐ф儏鍐�'
+ '鏌ヨ閲囪喘鍙拌处鍒楄〃',
+ '鏌ヨ鏈�杩�10鏉¢噰璐彴璐�',
+ '缁熻鏈湀閲囪喘鏁版嵁',
+ '鏌ヨ鏈湀閲囪喘鐗╂枡閲戦鎺掕',
+ '鏌ヨ鏈叆搴撻噰璐鍗�',
+ '鏌ヨ閲囪喘鍒拌揣寮傚父',
+ '鏌ヨ寰呬粯娆鹃噰璐崟',
+ '鏌ヨ鏈湀閲囪喘閫�璐ф儏鍐�',
+ '鏌ヨ鏌愪釜閲囪喘鍙拌处璇︽儏',
+ '鍒嗘瀽渚涘簲鍟嗛噰璐噾棰濇帓鍚�'
]
}
diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue
index 003b489..3712c68 100644
--- a/src/layout/components/Sidebar/SidebarItem.vue
+++ b/src/layout/components/Sidebar/SidebarItem.vue
@@ -102,57 +102,70 @@
</script>
<style lang="scss" scoped>
-.sidebar-item-wrapper {
- :deep(.menu-icon) {
- width: 26px;
- height: 26px;
- margin-right: 12px;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- transition: color 0.2s ease;
- color: var(--sidebar-text);
- opacity: 0.88;
- }
-
- :deep(.el-menu-item:hover .menu-icon),
- :deep(.el-sub-menu__title:hover .menu-icon) {
- color: #ffffff;
- opacity: 1;
- }
+.sidebar-item-wrapper {
+ :deep(.menu-icon) {
+ width: 26px;
+ height: 26px;
+ margin-right: 12px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ transition: color 0.2s ease;
+ color: var(--sidebar-text);
+ opacity: 0.88;
+ }
+
+ :deep(.el-menu-item:hover .menu-icon),
+ :deep(.el-sub-menu__title:hover .menu-icon) {
+ color: #ffffff;
+ opacity: 1;
+ }
:deep(.el-menu-item.is-active .menu-icon) {
color: var(--menu-active-text) !important;
opacity: 1;
}
- :deep(.menu-title) {
- font-weight: 500;
- transition: color 0.2s ease;
- color: var(--sidebar-text);
- opacity: 0.82;
- }
-
- :deep(.el-menu-item:hover .menu-title),
- :deep(.el-sub-menu__title:hover .menu-title) {
- color: #ffffff;
- opacity: 1;
- }
-
- :deep(.el-menu-item.is-active .menu-title) {
- color: var(--menu-active-text) !important;
- opacity: 1;
- }
-
- :deep(.nest-menu) {
- .menu-icon {
- width: 22px;
- height: 22px;
- margin-right: 10px;
- }
-
- .menu-title { font-size: 13px; }
- }
-}
+ :deep(.menu-title) {
+ font-weight: 500;
+ transition: color 0.2s ease;
+ color: var(--sidebar-text);
+ opacity: 0.82;
+ }
+
+ :deep(.el-menu-item:hover .menu-title),
+ :deep(.el-sub-menu__title:hover .menu-title) {
+ color: #ffffff;
+ opacity: 1;
+ }
+
+ :deep(.el-menu-item.is-active .menu-title) {
+ color: var(--menu-active-text) !important;
+ opacity: 1;
+ }
+
+ :deep(.nest-menu) {
+ .menu-icon {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+ opacity: 0.7;
+ }
+
+ .menu-title {
+ font-size: 13px;
+ opacity: 0.85;
+ }
+
+ .el-menu-item.is-active {
+ .menu-icon {
+ opacity: 1;
+ }
+ .menu-title {
+ opacity: 1;
+ }
+ }
+ }
+}
</style>
diff --git a/src/layout/index.vue b/src/layout/index.vue
index 500b2ab..aa1bfb5 100644
--- a/src/layout/index.vue
+++ b/src/layout/index.vue
@@ -11,7 +11,7 @@
class="main-container main-layout">
<div :class="{ 'fixed-header': fixedHeader, 'with-tags': showTagsView }">
<navbar @setLayout="setLayout" />
- <tags-view v-if="showTagsView" />
+ <tags-view />
</div>
<app-main />
<settings ref="settingRef" />
@@ -42,11 +42,15 @@
const sidebar = computed(() => useAppStore().sidebar);
const device = computed(() => useAppStore().device);
const needTagsView = computed(() => settingsStore.tagsView);
- const showTagsView = computed(() => needTagsView.value && tagsViewStore.visitedViews.length > 1);
+ const showTagsView = computed(
+ () => needTagsView.value && tagsViewStore.visitedViews.length > 1
+ );
const fixedHeader = computed(() => settingsStore.fixedHeader);
const aiEnabled = computed(() => Number(userStore.aiEnabled) === 1);
const showGlobalAiChat = computed(() => {
- const isIndustrialBrainRoute = String(route.path || "").startsWith("/ai-industrial-brain");
+ const isIndustrialBrainRoute = String(route.path || "").startsWith(
+ "/ai-industrial-brain"
+ );
return !isIndustrialBrainRoute && aiEnabled.value;
});
@@ -96,9 +100,16 @@
position: relative;
min-height: 100%;
width: 100%;
- background:
- radial-gradient(circle at 14% -8%, rgba(59, 130, 246, 0.14), transparent 36%),
- radial-gradient(circle at 88% -12%, rgba(56, 189, 248, 0.1), transparent 30%),
+ background: radial-gradient(
+ circle at 14% -8%,
+ rgba(59, 130, 246, 0.14),
+ transparent 36%
+ ),
+ radial-gradient(
+ circle at 88% -12%,
+ rgba(56, 189, 248, 0.1),
+ transparent 30%
+ ),
linear-gradient(165deg, #f3f7fc 0%, #eef5ff 56%, #f8fbff 100%);
&.mobile.openSidebar {
diff --git a/src/views/basicData/parameterMaintenance/index.vue b/src/views/basicData/parameterMaintenance/index.vue
index 2dbf5df..38ddd4f 100644
--- a/src/views/basicData/parameterMaintenance/index.vue
+++ b/src/views/basicData/parameterMaintenance/index.vue
@@ -50,7 +50,7 @@
prop="paramCode">
<el-input v-model="formData.paramCode"
disabled
- placeholder="鑷姩鐢熸垚" />
+ placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" />
</el-form-item>
<el-form-item label="鍙傛暟鍚嶇О"
prop="paramName">
@@ -82,6 +82,14 @@
value="2" />
</el-select>
</el-form-item> -->
+ <el-form-item label="鍒涘缓鏃堕棿"
+ prop="createTime">
+ <el-date-picker v-model="formCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%" />
+ </el-form-item>
<el-form-item label="鍗曚綅"
prop="unit">
<el-input v-model="formData.unit"
@@ -207,7 +215,8 @@
</template>
<script setup>
- import { onMounted, ref, reactive } from "vue";
+ import { onMounted, ref, reactive, computed } from "vue";
+ import dayjs from "dayjs";
import {
parameterListPage,
addParameter,
@@ -341,6 +350,7 @@
remark: "",
isRequired: 0,
paramFormat: "",
+ createTime: "",
});
const rules = reactive({
paramName: [{ required: true, message: "璇疯緭鍏ュ弬鏁板悕绉�", trigger: "blur" }],
@@ -360,6 +370,12 @@
},
},
],
+ });
+ const formCreateTimeDate = computed({
+ get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
// const productTypes = ref([]);
const isEdit = ref(false);
@@ -519,6 +535,7 @@
formData.unit = "";
formData.remark = "";
formData.isRequired = 0;
+ formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
dialogVisible.value = true;
};
@@ -537,6 +554,7 @@
formData.remark = row.remark || "";
formData.paramFormat = row.paramFormat || "";
formData.isRequired = row.isRequired || 0;
+ formData.createTime = row.createTime || "";
dialogVisible.value = true;
};
diff --git a/src/views/collaborativeApproval/purchaseApproval/index.vue b/src/views/collaborativeApproval/purchaseApproval/index.vue
index b276bec..d39748f 100644
--- a/src/views/collaborativeApproval/purchaseApproval/index.vue
+++ b/src/views/collaborativeApproval/purchaseApproval/index.vue
@@ -278,7 +278,7 @@
},
rules: {
purchaseContractNumber: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ { required: false, message: "璇疯緭鍏�", trigger: "blur" },
],
projectName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
@@ -448,9 +448,7 @@
productData.value = [];
fileList.value = [];
if (operationType.value == "add") {
- createPurchaseNo().then(res => {
- form.value.purchaseContractNumber = res.data;
- });
+ form.value.purchaseContractNumber = "";
}
userListNoPage().then(res => {
userList.value = res.data;
@@ -521,7 +519,7 @@
}
// 鎻愪氦琛ㄥ崟
const submitForm = n => {
- proxy.$refs["formRef"].validate(valid => {
+ proxy.$refs["formRef"].validate(async valid => {
if (valid) {
if (productData.value.length > 0) {
form.value.productData = proxy.HaveJson(productData.value);
@@ -536,6 +534,21 @@
form.value.tempFileIds = tempFileIds;
form.value.type = 2;
form.value.approvalStatus = n;
+
+ // 濡傛灉閲囪喘鍚堝悓鍙蜂负绌猴紝鍒欐牴鎹綍鍏ユ棩鏈熻嚜鍔ㄧ敓鎴�
+ if (!form.value.purchaseContractNumber) {
+ try {
+ const purchaseNoRes = await createPurchaseNo(form.value.entryDate);
+ if (purchaseNoRes?.data) {
+ form.value.purchaseContractNumber = purchaseNoRes.data;
+ }
+ } catch (error) {
+ console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
+ proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
+ return;
+ }
+ }
+
addOrEditPurchase(form.value).then(res => {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
closeDia();
diff --git a/src/views/customerService/feedbackRegistration/index.vue b/src/views/customerService/feedbackRegistration/index.vue
index bcbb326..9a70ca7 100644
--- a/src/views/customerService/feedbackRegistration/index.vue
+++ b/src/views/customerService/feedbackRegistration/index.vue
@@ -112,7 +112,6 @@
</div>
<form-dia ref="formDia"
@close="handleQuery"></form-dia>
- <view-dia ref="viewDia"></view-dia>
</div>
</template>
@@ -127,7 +126,6 @@
nextTick,
} from "vue";
import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue";
- import ViewDia from "@/views/customerService/components/viewDia.vue";
import { ElMessageBox } from "element-plus";
import {
afterSalesServiceDelete,
@@ -151,14 +149,14 @@
{
icon: markRaw(FolderOpened),
count: 0,
- label: "寰呭鐞�",
+ label: "宸插鐞�",
color: "#ff9a2e",
bgColor: "#fff5e6",
},
{
icon: markRaw(UserFilled),
count: 0,
- label: "宸插鐞�",
+ label: "宸插畬鎴�",
color: "#00b42a",
bgColor: "#e6f7ed",
},
@@ -257,15 +255,6 @@
align: "center",
},
{
- label: "鏁伴噺",
- prop: "productModelQuantities",
- align: "center",
- formatData: params => {
- if (!params) return "0";
- return String(params).split(',').reduce((sum, val) => sum + (Number(val) || 0), 0);
- }
- },
- {
label: "瀹㈡埛璇夋眰",
prop: "proDesc",
width: 300,
@@ -280,16 +269,7 @@
dataType: "action",
label: "鎿嶄綔",
fixed: "right",
- width: 180,
- align: "center",
operation: [
- {
- name: "璇︽儏",
- type: "text",
- clickFun: row => {
- viewDia.value?.openDialog(row);
- },
- },
{
name: "缂栬緫",
type: "text",
@@ -327,10 +307,9 @@
selectedRows.value = selection;
};
const formDia = ref();
- const viewDia = ref();
// 瀛楀吀鑾峰彇
- /*
+ /*
post_sale_waiting_list 鏂板鐨勫敭鍚庡垎绫�
degree_of_urgency 鏂板鐨勭揣鎬ョ▼搴�
work_order_status 涓婚〉鐨勫伐鍗曠姸鎬�
diff --git a/src/views/equipmentManagement/inspectionManagement/index.vue b/src/views/equipmentManagement/inspectionManagement/index.vue
index c6c21d9..76a272c 100644
--- a/src/views/equipmentManagement/inspectionManagement/index.vue
+++ b/src/views/equipmentManagement/inspectionManagement/index.vue
@@ -279,7 +279,7 @@
];
operationsArr.value = ["edit"];
} else if (value === "task") {
- const operationColumn = getOperationColumn(["view", "upload", "viewFile"]);
+ const operationColumn = getOperationColumn(["upload", "viewFile"]);
// 宸℃璁板綍涓嶅睍绀�"鏄惁鍚敤"鍒�
const taskColumns = columns.value.filter(col => col.prop !== "isEnabled");
tableColumns.value = [
diff --git a/src/views/equipmentManagement/repair/Modal/RepairModal.vue b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
index b260d62..4a10071 100644
--- a/src/views/equipmentManagement/repair/Modal/RepairModal.vue
+++ b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -49,9 +49,9 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鎶ヤ慨椤圭洰">
+ <el-form-item label="鎶ヤ慨鎶ヤ慨椤圭洰">
<el-input v-model="form.machineryCategory"
- placeholder="璇疯緭鍏ユ姤淇」鐩�"
+ placeholder="璇疯緭鍏ユ姤淇姤淇」鐩�"
:disabled="operationType === 'view'" />
</el-form-item>
</el-col>
diff --git a/src/views/financialManagement/assets/fixedAssets.vue b/src/views/financialManagement/assets/fixedAssets.vue
index 24b4cc3..95eb017 100644
--- a/src/views/financialManagement/assets/fixedAssets.vue
+++ b/src/views/financialManagement/assets/fixedAssets.vue
@@ -82,7 +82,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="璧勪骇缂栧彿" prop="assetCode">
- <el-input v-model="form.assetCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ <el-input v-model="form.assetCode" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -175,6 +175,13 @@
</el-form-item>
</el-col>
</el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
+ <el-date-picker v-model="createTimeDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-form-item label="澶囨敞" prop="remark">
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉�" />
</el-form-item>
@@ -189,6 +196,7 @@
<script setup>
import { ref, reactive, onMounted, computed } from "vue";
+import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import {
@@ -258,10 +266,17 @@
keeper: "",
status: "in_use",
remark: "",
+ createTime: "",
});
const form = reactive({
...createDefaultForm(),
+});
+const createTimeDate = computed({
+ get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
const rules = {
@@ -356,16 +371,14 @@
getTableData();
};
-const buildAssetCode = () => `GD${Date.now().toString().slice(-10)}`;
-
const add = () => {
isEdit.value = false;
isView.value = false;
currentId.value = null;
dialogTitle.value = "鏂板鍥哄畾璧勪骇";
Object.assign(form, createDefaultForm(), {
- assetCode: buildAssetCode(),
purchaseDate: new Date().toISOString().split('T')[0],
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
dialogVisible.value = true;
};
diff --git a/src/views/financialManagement/assets/intangibleAssets.vue b/src/views/financialManagement/assets/intangibleAssets.vue
index 4642166..9aef2bf 100644
--- a/src/views/financialManagement/assets/intangibleAssets.vue
+++ b/src/views/financialManagement/assets/intangibleAssets.vue
@@ -83,7 +83,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="璧勪骇缂栧彿" prop="assetCode">
- <el-input v-model="form.assetCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ <el-input v-model="form.assetCode" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -165,6 +165,13 @@
</el-form-item>
</el-col>
</el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
+ <el-date-picker v-model="createTimeDate" type="date" placeholder="閫夋嫨鏃ユ湡" value-format="YYYY-MM-DD" style="width: 100%;" />
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-form-item label="璧勪骇鎻忚堪" prop="description">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="璇疯緭鍏ヨ祫浜ф弿杩�" />
</el-form-item>
@@ -182,6 +189,7 @@
<script setup>
import { ref, reactive, onMounted, computed } from "vue";
+import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import {
@@ -250,10 +258,17 @@
status: "in_use",
description: "",
remark: "",
+ createTime: "",
});
const form = reactive({
...createDefaultForm(),
+});
+const createTimeDate = computed({
+ get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
const rules = {
@@ -354,16 +369,14 @@
getTableData();
};
-const buildAssetCode = () => `WX${Date.now().toString().slice(-10)}`;
-
const add = () => {
isEdit.value = false;
isView.value = false;
currentId.value = null;
dialogTitle.value = "鏂板鏃犲舰璧勪骇";
Object.assign(form, createDefaultForm(), {
- assetCode: buildAssetCode(),
acquisitionDate: new Date().toISOString().split('T')[0],
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
dialogVisible.value = true;
};
diff --git a/src/views/financialManagement/payable/paymentApply.vue b/src/views/financialManagement/payable/paymentApply.vue
index 3937e96..e34793f 100644
--- a/src/views/financialManagement/payable/paymentApply.vue
+++ b/src/views/financialManagement/payable/paymentApply.vue
@@ -97,7 +97,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="鐢宠鍗曞彿" prop="invoiceApplicationNo">
- <el-input v-model="form.invoiceApplicationNo" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ <el-input v-model="form.invoiceApplicationNo" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -158,6 +158,18 @@
</el-row>
<el-row :gutter="20">
<el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
+ <el-date-picker
+ v-model="formCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
<el-form-item label="浠樻閲戦" prop="paymentAmount">
<el-input-number
v-model="form.paymentAmount"
@@ -217,7 +229,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="浠樻鍗曞彿" prop="paymentNumber">
- <el-input v-model="paymentForm.paymentNumber" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ <el-input v-model="paymentForm.paymentNumber" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
@@ -245,6 +257,17 @@
</el-col>
</el-row>
<el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
+ <el-date-picker
+ v-model="paymentFormCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ />
+ </el-form-item>
+ </el-col>
<el-col :span="12">
<el-form-item label="浠樻閲戦" prop="paymentAmount">
<el-input-number
@@ -330,6 +353,7 @@
<script setup>
import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance } from "vue";
+import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { getOptions } from "@/api/procurementManagement/procurementLedger.js";
@@ -407,6 +431,7 @@
bankAccount: "",
bankName: "",
remark: "",
+ createTime: "",
});
const paymentRules = {
@@ -429,6 +454,19 @@
stockInRecordIds: [],
inboundBatches: "",
status: 0,
+ createTime: "",
+});
+const formCreateTimeDate = computed({
+ get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
+});
+const paymentFormCreateTimeDate = computed({
+ get: () => (paymentForm.createTime ? String(paymentForm.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ paymentForm.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
const rules = {
@@ -563,6 +601,7 @@
stockInRecordIds,
inboundBatches: formatInboundBatches(row.inboundBatches),
status: normalizeStatus(row.status),
+ createTime: row.createTime ?? "",
});
};
@@ -580,6 +619,7 @@
remark: row.remark ?? "",
status: statusOverride !== undefined ? statusOverride : normalizeStatus(row.status),
paymentAmount: Number(row.paymentAmount ?? row.amount ?? 0),
+ createTime: row.createTime,
});
const buildSubmitPayload = (forUpdate = false) => {
@@ -593,6 +633,7 @@
remark: form.remark || "",
status: 0,
paymentAmount: form.paymentAmount,
+ createTime: form.createTime,
};
if (forUpdate) {
payload.id = currentId.value;
@@ -703,6 +744,7 @@
stockInRecordIds: [],
inboundBatches: "",
status: 0,
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
inboundBatchList.value = [];
inboundBatchOptions.value = [];
@@ -781,6 +823,7 @@
bankAccount: row.bankAccountNum ?? row.bankAccount ?? "",
bankName: row.bankAccountName ?? row.bankName ?? "",
remark: "",
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
paymentDialogVisible.value = true;
nextTick(() => {
@@ -800,6 +843,7 @@
paymentAmount: paymentForm.paymentAmount,
paymentNumber: paymentForm.paymentNumber || "",
remark: paymentForm.remark || "",
+ createTime: paymentForm.createTime,
})
.then((res) => {
if (res.code === 200) {
diff --git a/src/views/financialManagement/payable/purchaseIn.vue b/src/views/financialManagement/payable/purchaseIn.vue
index fcb768f..532bcb4 100644
--- a/src/views/financialManagement/payable/purchaseIn.vue
+++ b/src/views/financialManagement/payable/purchaseIn.vue
@@ -98,7 +98,7 @@
slot: "inboundDate",
},
{ label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
- { label: "浜у搧瑙勬牸", prop: "specificationModel", minWidth: "140" },
+ { label: "瑙勬牸鍨嬪彿", prop: "specificationModel", minWidth: "140" },
{
label: "閲戦",
prop: "inboundAmount",
diff --git a/src/views/financialManagement/receivable/invoiceApply.vue b/src/views/financialManagement/receivable/invoiceApply.vue
index 14fdd67..85f30b2 100644
--- a/src/views/financialManagement/receivable/invoiceApply.vue
+++ b/src/views/financialManagement/receivable/invoiceApply.vue
@@ -98,7 +98,7 @@
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="鐢宠鍗曞彿" prop="applyCode">
- <el-input v-model="form.applyCode" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ <el-input v-model="form.applyCode" placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" disabled />
</el-form-item>
</el-col>
</el-row>
@@ -189,6 +189,20 @@
</el-form-item>
</el-col>
</el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
+ <el-date-picker
+ v-model="formCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
<el-form-item label="鍙戠エ鍐呭" prop="content">
<el-input v-model="form.content" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ彂绁ㄥ唴瀹�" :disabled="isView" />
</el-form-item>
@@ -253,6 +267,7 @@
<script setup>
import { ref, reactive, computed, onMounted, nextTick, getCurrentInstance, defineAsyncComponent } from "vue";
+import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { listCustomer } from "@/api/basicData/customer.js";
@@ -524,6 +539,13 @@
applyDate: "",
content: "",
remark: "",
+ createTime: "",
+});
+const formCreateTimeDate = computed({
+ get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
const rules = {
@@ -706,6 +728,7 @@
status: normalizeStatus(row.status ?? row.auditStatus),
outboundBatchNos,
outboundBatches: formatOutboundBatches(row.outboundBatches),
+ createTime: row.createTime ?? "",
});
};
@@ -714,7 +737,7 @@
isView.value = false;
dialogTitle.value = "鏂板寮�绁ㄧ敵璇�";
Object.assign(form, {
- applyCode: "KP" + Date.now().toString().slice(-8),
+ applyCode: "",
customerId: "",
outboundBatchNos: [],
outboundBatches: "",
@@ -724,6 +747,7 @@
applyDate: new Date().toISOString().split("T")[0],
content: "",
remark: "",
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
outboundBatchList.value = [];
outboundBatchOptions.value = [];
@@ -752,6 +776,7 @@
invoiceAmount: form.amount,
taxRate: form.taxRate,
status: 0,
+ createTime: form.createTime,
};
if (forUpdate) {
payload.id = currentId.value;
@@ -766,6 +791,7 @@
dialogTitle.value = "缂栬緫寮�绁ㄧ敵璇�";
fillFormFromRow(row);
dialogVisible.value = true;
+ loadOutboundBatches(form.customerId, true);
};
const view = (row) => {
diff --git a/src/views/financialManagement/receivable/receipt.vue b/src/views/financialManagement/receivable/receipt.vue
index 6ddb3fe..ae7a763 100644
--- a/src/views/financialManagement/receivable/receipt.vue
+++ b/src/views/financialManagement/receivable/receipt.vue
@@ -111,7 +111,7 @@
<el-form-item label="鏀舵鍗曞彿"
prop="receiptCode">
<el-input v-model="form.receiptCode"
- placeholder="绯荤粺鑷姩鐢熸垚"
+ placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�"
disabled />
</el-form-item>
</el-col>
@@ -191,6 +191,17 @@
:label="item.label"
:value="item.value" />
</el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿"
+ prop="createTime">
+ <el-date-picker v-model="formCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%;"
+ :disabled="isView" />
</el-form-item>
</el-col>
</el-row>
@@ -288,6 +299,7 @@
nextTick,
getCurrentInstance,
} from "vue";
+ import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { listCustomer } from "@/api/basicData/customer.js";
@@ -379,6 +391,13 @@
stockOutRecordIds: [],
outboundBatches: "",
remark: "",
+ createTime: "",
+ });
+ const formCreateTimeDate = computed({
+ get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
const rules = {
@@ -658,6 +677,7 @@
collectionNumber: form.receiptCode || "",
remark: form.remark || "",
stockOutRecordIds: (form.stockOutRecordIds || []).join(","),
+ createTime: form.createTime,
};
if (forUpdate) {
payload.id = currentId.value;
@@ -678,6 +698,7 @@
stockOutRecordIds,
outboundBatches: formatOutboundBatches(row.outboundBatches),
remark: row.remark ?? "",
+ createTime: row.createTime ?? "",
});
};
@@ -746,7 +767,7 @@
isView.value = false;
dialogTitle.value = "鏂板鏀舵";
Object.assign(form, {
- receiptCode: "SK" + Date.now().toString().slice(-8),
+ receiptCode: "",
customerId: "",
receiptDate: new Date().toISOString().split("T")[0],
amount: 0,
@@ -754,6 +775,7 @@
stockOutRecordIds: [],
outboundBatches: "",
remark: "",
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
outboundBatchList.value = [];
outboundBatchOptions.value = [];
diff --git a/src/views/financialManagement/receivable/salesOut.vue b/src/views/financialManagement/receivable/salesOut.vue
index 297a82c..0e24b37 100644
--- a/src/views/financialManagement/receivable/salesOut.vue
+++ b/src/views/financialManagement/receivable/salesOut.vue
@@ -1,27 +1,33 @@
<template>
-<!-- 閿�鍞嚭搴� -->
+ <!-- 閿�鍞嚭搴� -->
<div class="app-container">
- <el-form :model="filters" :inline="true">
+ <el-form :model="filters"
+ :inline="true">
<el-form-item label="鍑哄簱鍗曞彿:">
- <el-input v-model="filters.outboundBatches" placeholder="璇疯緭鍏ュ嚭搴撳崟鍙�" clearable style="width: 200px;" />
+ <el-input v-model="filters.outboundBatches"
+ placeholder="璇疯緭鍏ュ嚭搴撳崟鍙�"
+ clearable
+ style="width: 200px;" />
</el-form-item>
<el-form-item label="瀹㈡埛鍚嶇О:">
- <el-input v-model="filters.customerName" placeholder="璇疯緭鍏ュ鎴峰悕绉�" clearable style="width: 200px;" />
+ <el-input v-model="filters.customerName"
+ placeholder="璇疯緭鍏ュ鎴峰悕绉�"
+ clearable
+ style="width: 200px;" />
</el-form-item>
<el-form-item label="鍑哄簱鏃ユ湡:">
- <el-date-picker
- v-model="filters.dateRange"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- clearable
- />
+ <el-date-picker v-model="filters.dateRange"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ clearable />
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="onSearch">鎼滅储</el-button>
+ <el-button type="primary"
+ @click="onSearch">鎼滅储</el-button>
<el-button @click="resetFilters">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -29,141 +35,146 @@
<div class="actions">
<div></div>
<div>
- <el-button @click="handleOut" icon="Download">瀵煎嚭</el-button>
+ <el-button @click="handleOut"
+ icon="Download">瀵煎嚭</el-button>
</div>
</div>
- <PIMTable
- rowKey="id"
- :column="columns"
- :tableData="dataList"
- :tableLoading="tableLoading"
- :page="{
+ <PIMTable rowKey="id"
+ :column="columns"
+ :tableData="dataList"
+ :tableLoading="tableLoading"
+ :page="{
current: pagination.currentPage,
size: pagination.pageSize,
total: pagination.total,
}"
- @pagination="changePage"
- />
+ @pagination="changePage" />
</div>
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, getCurrentInstance } from "vue";
-import { ElMessage } from "element-plus";
-import { listPageAccountSales } from "@/api/financialManagement/accountSales";
+ import { ref, reactive, onMounted, getCurrentInstance } from "vue";
+ import { ElMessage } from "element-plus";
+ import { listPageAccountSales } from "@/api/financialManagement/accountSales";
-defineOptions({
- name: "閿�鍞嚭搴�",
-});
+ defineOptions({
+ name: "閿�鍞嚭搴�",
+ });
-const { proxy } = getCurrentInstance();
+ const { proxy } = getCurrentInstance();
-const filters = reactive({
- outboundBatches: "",
- customerName: "",
- dateRange: [],
-});
+ const filters = reactive({
+ outboundBatches: "",
+ customerName: "",
+ dateRange: [],
+ });
-const pagination = reactive({
- currentPage: 1,
- pageSize: 10,
- total: 0,
-});
+ const pagination = reactive({
+ currentPage: 1,
+ pageSize: 10,
+ total: 0,
+ });
-const columns = [
- { label: "鍑哄簱鍗曞彿", prop: "outboundBatches", minWidth: "150" },
- { label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: "180" },
- { label: "鍑哄簱鏃ユ湡", prop: "shippingDate", width: "170" },
- { label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
- { label: "浜у搧瑙勬牸", prop: "specificationModel", minWidth: "140" },
- {
- label: "閲戦",
- prop: "outboundAmount",
- minWidth: "120",
- align: "right",
- formatData: (val) => (val === null || val === undefined || val === "" ? "" : Number(val).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 })),
- },
- { label: "鍙戣揣缂栧彿", prop: "shippingNo", minWidth: "140" },
- { label: "閿�鍞鍗曞彿", prop: "salesContractNo", minWidth: "150" },
-];
+ const columns = [
+ { label: "鍑哄簱鍗曞彿", prop: "outboundBatches", minWidth: "150" },
+ { label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: "180" },
+ { label: "鍑哄簱鏃ユ湡", prop: "shippingDate", width: "170" },
+ { label: "浜у搧鍚嶇О", prop: "productName", minWidth: "140" },
+ { label: "瑙勬牸鍨嬪彿", prop: "specificationModel", minWidth: "140" },
+ {
+ label: "閲戦",
+ prop: "outboundAmount",
+ minWidth: "120",
+ align: "right",
+ formatData: val =>
+ val === null || val === undefined || val === ""
+ ? ""
+ : Number(val).toLocaleString("zh-CN", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ }),
+ },
+ { label: "鍙戣揣缂栧彿", prop: "shippingNo", minWidth: "140" },
+ { label: "閿�鍞鍗曞彿", prop: "salesContractNo", minWidth: "150" },
+ ];
-const dataList = ref([]);
-const tableLoading = ref(false);
+ const dataList = ref([]);
+ const tableLoading = ref(false);
-function buildFilterParams() {
- const params = {
- outboundBatches: filters.outboundBatches || undefined,
- customerName: filters.customerName || undefined,
- };
- if (filters.dateRange && filters.dateRange.length === 2) {
- params.startDate = filters.dateRange[0];
- params.endDate = filters.dateRange[1];
+ function buildFilterParams() {
+ const params = {
+ outboundBatches: filters.outboundBatches || undefined,
+ customerName: filters.customerName || undefined,
+ };
+ if (filters.dateRange && filters.dateRange.length === 2) {
+ params.startDate = filters.dateRange[0];
+ params.endDate = filters.dateRange[1];
+ }
+ return params;
}
- return params;
-}
-const onSearch = () => {
- pagination.currentPage = 1;
- getTableData();
-};
+ const onSearch = () => {
+ pagination.currentPage = 1;
+ getTableData();
+ };
-const getTableData = () => {
- tableLoading.value = true;
- listPageAccountSales({
- ...buildFilterParams(),
- current: pagination.currentPage,
- size: pagination.pageSize,
- })
- .then((res) => {
- const ok = res.code === 200 || res.code === 0;
- if (ok && res.data) {
- pagination.total = res.data.total ?? 0;
- dataList.value = res.data.records ?? [];
- } else {
- ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ const getTableData = () => {
+ tableLoading.value = true;
+ listPageAccountSales({
+ ...buildFilterParams(),
+ current: pagination.currentPage,
+ size: pagination.pageSize,
+ })
+ .then(res => {
+ const ok = res.code === 200 || res.code === 0;
+ if (ok && res.data) {
+ pagination.total = res.data.total ?? 0;
+ dataList.value = res.data.records ?? [];
+ } else {
+ ElMessage.error(res.msg || "鏌ヨ澶辫触");
+ dataList.value = [];
+ }
+ })
+ .catch(() => {
dataList.value = [];
- }
- })
- .catch(() => {
- dataList.value = [];
- })
- .finally(() => {
- tableLoading.value = false;
- });
-};
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
-const resetFilters = () => {
- filters.outboundBatches = "";
- filters.customerName = "";
- filters.dateRange = [];
- pagination.currentPage = 1;
- getTableData();
-};
+ const resetFilters = () => {
+ filters.outboundBatches = "";
+ filters.customerName = "";
+ filters.dateRange = [];
+ pagination.currentPage = 1;
+ getTableData();
+ };
-const changePage = ({ page, limit }) => {
- pagination.currentPage = page;
- pagination.pageSize = limit;
- getTableData();
-};
+ const changePage = ({ page, limit }) => {
+ pagination.currentPage = page;
+ pagination.pageSize = limit;
+ getTableData();
+ };
-const handleOut = () => {
- proxy.download(
- "/accountSales/exportAccountSalesOutbound",
- buildFilterParams(),
- `閿�鍞嚭搴揰${new Date().getTime()}.xlsx`
- );
-};
+ const handleOut = () => {
+ proxy.download(
+ "/accountSales/exportAccountSalesOutbound",
+ buildFilterParams(),
+ `閿�鍞嚭搴揰${new Date().getTime()}.xlsx`
+ );
+ };
-onMounted(() => {
- getTableData();
-});
+ onMounted(() => {
+ getTableData();
+ });
</script>
<style lang="scss" scoped>
-.actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 15px;
-}
+ .actions {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 15px;
+ }
</style>
diff --git a/src/views/inventoryManagement/dispatchLog/Record.vue b/src/views/inventoryManagement/dispatchLog/Record.vue
index fb24e40..2d7411d 100644
--- a/src/views/inventoryManagement/dispatchLog/Record.vue
+++ b/src/views/inventoryManagement/dispatchLog/Record.vue
@@ -1,71 +1,70 @@
<template>
<div>
- <div class="search_form" style="margin-bottom: 10px">
- <el-form
- ref="searchFormRef"
- :model="searchForm"
- class="demo-form-inline"
- >
+ <div class="search_form"
+ style="margin-bottom: 10px">
+ <el-form ref="searchFormRef"
+ :model="searchForm"
+ class="demo-form-inline">
<el-row :gutter="20">
<el-col :span="4">
- <el-form-item label="鍑哄簱鏃ユ湡" prop="timeStr">
+ <el-form-item label="鍑哄簱鏃ユ湡"
+ prop="timeStr">
<el-date-picker v-model="searchForm.timeStr"
type="date"
placeholder="璇烽�夋嫨鏃ユ湡"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="浜у搧澶х被" prop="productName">
+ <el-form-item label="浜у搧澶х被"
+ prop="productName">
<el-input v-model="searchForm.productName"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
-
<el-col :span="4">
- <el-form-item label="浜у搧瑙勬牸" prop="model">
+ <el-form-item label="瑙勬牸鍨嬪彿"
+ prop="model">
<el-input v-model="searchForm.model"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鎵瑰彿" prop="batchNo">
+ <el-form-item label="鎵瑰彿"
+ prop="batchNo">
<el-input v-model="searchForm.batchNo"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鏉ユ簮" prop="recordType">
- <el-select
- v-model="searchForm.recordType"
- style="width: 240px"
- placeholder="璇烽�夋嫨"
- clearable
- >
- <el-option
- v-for="item in stockRecordTypeOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
+ <el-form-item label="鏉ユ簮"
+ prop="recordType">
+ <el-select v-model="searchForm.recordType"
+ style="width: 240px"
+ placeholder="璇烽�夋嫨"
+ clearable>
+ <el-option v-for="item in stockRecordTypeOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<!-- 鎸夐挳 -->
<el-col :span="4">
<el-form-item>
- <el-button type="primary" @click="getList">
+ <el-button type="primary"
+ @click="getList">
鎼滅储
</el-button>
-
<el-button @click="resetSearch">
閲嶇疆
</el-button>
@@ -75,792 +74,796 @@
</el-form>
</div>
<div class="actions">
- <el-button type="primary" @click="handleBatchApprove">瀹℃壒</el-button>
+ <el-button type="primary"
+ @click="handleBatchApprove">瀹℃壒</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
- <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+ <el-button type="danger"
+ plain
+ @click="handleDelete">鍒犻櫎</el-button>
+ <el-button type="primary"
+ plain
+ @click="handlePrint">鎵撳嵃</el-button>
</div>
<div class="table_list">
- <el-table
- :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- style="width: 100%"
- height="calc(100vh - 18.5em)"
- >
- <el-table-column align="center" type="selection" width="55" />
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column
- label="鍑哄簱鎵规"
- prop="outboundBatches"
- min-width="100"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍑哄簱鏃ユ湡"
- prop="createTime"
- show-overflow-tooltip
- />
- <el-table-column
- label="浜у搧澶х被"
- prop="productName"
- show-overflow-tooltip
- />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
- <el-table-column label="鎵瑰彿" prop="batchNo" show-overflow-tooltip />
- <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
- <el-table-column
- label="鍑哄簱鏁伴噺"
- prop="stockOutNum"
- show-overflow-tooltip
- />
- <el-table-column label="鍑哄簱浜�" prop="createBy" show-overflow-tooltip />
- <el-table-column label="鏉ユ簮" prop="recordType" show-overflow-tooltip>
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.id"
+ style="width: 100%"
+ height="calc(100vh - 18.5em)">
+ <el-table-column align="center"
+ type="selection"
+ width="55" />
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="鍑哄簱鎵规"
+ prop="outboundBatches"
+ min-width="100"
+ show-overflow-tooltip />
+ <el-table-column label="鍑哄簱鏃ユ湡"
+ prop="createTime"
+ show-overflow-tooltip />
+ <el-table-column label="浜у搧澶х被"
+ prop="productName"
+ show-overflow-tooltip />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="model"
+ show-overflow-tooltip />
+ <el-table-column label="鎵瑰彿"
+ prop="batchNo"
+ show-overflow-tooltip />
+ <el-table-column label="鍗曚綅"
+ prop="unit"
+ show-overflow-tooltip />
+ <el-table-column label="鍑哄簱鏁伴噺"
+ prop="stockOutNum"
+ show-overflow-tooltip />
+ <el-table-column label="鍑哄簱浜�"
+ prop="createBy"
+ show-overflow-tooltip />
+ <el-table-column label="鏉ユ簮"
+ prop="recordType"
+ show-overflow-tooltip>
<template #default="scope">
{{ getRecordType(scope.row.recordType) }}
</template>
</el-table-column>
- <el-table-column
- label="瀹℃壒鐘舵��"
- prop="approvalStatus"
- show-overflow-tooltip
- >
+ <el-table-column label="瀹℃壒鐘舵��"
+ prop="approvalStatus"
+ show-overflow-tooltip>
<template #default="scope">
- <el-tag
- :type="getApprovalStatusTagType(scope.row.approvalStatus)"
- size="small"
- >
+ <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)"
+ size="small">
{{ getApprovalStatusLabel(scope.row.approvalStatus) }}
</el-tag>
</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"
- />
+ <pagination v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
</div>
</div>
</template>
<script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import { ref } from "vue";
-import { ElMessageBox } from "element-plus";
-import useUserStore from "@/store/modules/user";
-import { getCurrentDate } from "@/utils/index.js";
-import {
- getStockOutPage,
- delPendingStockOut,
- batchApproveStockOutRecords,
-} from "@/api/inventoryManagement/stockOut.js";
-import {
- findAllQualifiedStockOutRecordTypeOptions,
- findAllUnQualifiedStockOutRecordTypeOptions,
-} from "@/api/basicData/enum.js";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import { ref } from "vue";
+ import { ElMessageBox } from "element-plus";
+ import useUserStore from "@/store/modules/user";
+ import { getCurrentDate } from "@/utils/index.js";
+ import {
+ getStockOutPage,
+ delPendingStockOut,
+ batchApproveStockOutRecords,
+ } from "@/api/inventoryManagement/stockOut.js";
+ import {
+ findAllQualifiedStockOutRecordTypeOptions,
+ findAllUnQualifiedStockOutRecordTypeOptions,
+ } from "@/api/basicData/enum.js";
-const userStore = useUserStore();
-const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-// 鏉ユ簮绫诲瀷閫夐」
-const stockRecordTypeOptions = ref([]);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
+ const userStore = useUserStore();
+ const { proxy } = getCurrentInstance();
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ // 鏉ユ簮绫诲瀷閫夐」
+ const stockRecordTypeOptions = ref([]);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ });
+ const total = ref(0);
-const props = defineProps({
- type: {
- type: String,
- required: true,
- default: "0",
- },
- topParentProductId: {
- type: [String, Number],
- default: undefined,
- },
-});
+ const props = defineProps({
+ type: {
+ type: String,
+ required: true,
+ default: "0",
+ },
+ topParentProductId: {
+ type: [String, Number],
+ default: undefined,
+ },
+ });
-// 鎵撳嵃鐩稿叧
-const printPreviewVisible = ref(false);
-const printData = ref([]);
+ // 鎵撳嵃鐩稿叧
+ const printPreviewVisible = ref(false);
+ const printData = ref([]);
-// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
-const data = reactive({
- searchForm: {
- supplierName: "",
- timeStr: "",
- recordType: "",
- },
-});
-const { searchForm } = toRefs(data);
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const data = reactive({
+ searchForm: {
+ supplierName: "",
+ timeStr: "",
+ recordType: "",
+ },
+ });
+ const { searchForm } = toRefs(data);
-const searchFormRef = ref(null);
+ const searchFormRef = ref(null);
-const resetSearch = () => {
- searchFormRef.value?.resetFields();
- page.current = 1;
- getList();
-}
+ const resetSearch = () => {
+ searchFormRef.value?.resetFields();
+ page.current = 1;
+ getList();
+ };
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- getStockOutPage({
- ...searchForm.value,
- ...page,
- topParentProductId: props.topParentProductId,
- })
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- tableData.value.map((item) => {
- item.children = [];
- });
- total.value = res.data.total;
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ tableLoading.value = true;
+ getStockOutPage({
+ ...searchForm.value,
+ ...page,
+ topParentProductId: props.topParentProductId,
})
- .catch(() => {
- tableLoading.value = false;
- });
-};
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ tableData.value.map(item => {
+ item.children = [];
+ });
+ total.value = res.data.total;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+ };
-const getRecordType = (recordType) => {
- return (
- stockRecordTypeOptions.value.find((item) => item.value === recordType)
- ?.label || ""
- );
-};
+ const getRecordType = recordType => {
+ return (
+ stockRecordTypeOptions.value.find(item => item.value === recordType)
+ ?.label || ""
+ );
+ };
-const approvalStatusLabelMap = {
- 0: "寰呭鎵�",
- 1: "閫氳繃",
- 2: "椹冲洖",
- 3: "寰呯‘璁�",
- pending: "寰呭鎵�",
- approved: "閫氳繃",
- rejected: "椹冲洖",
- PENDING: "寰呭鎵�",
- APPROVED: "閫氳繃",
- REJECTED: "椹冲洖",
-};
+ const approvalStatusLabelMap = {
+ 0: "寰呭鎵�",
+ 1: "閫氳繃",
+ 2: "椹冲洖",
+ 3: "寰呯‘璁�",
+ pending: "寰呭鎵�",
+ approved: "閫氳繃",
+ rejected: "椹冲洖",
+ PENDING: "寰呭鎵�",
+ APPROVED: "閫氳繃",
+ REJECTED: "椹冲洖",
+ };
-const getApprovalStatusLabel = (status) => {
- if (status === null || status === undefined || status === "") {
- return "寰呭鎵�";
- }
- return approvalStatusLabelMap[status] || "寰呭鎵�";
-};
+ const getApprovalStatusLabel = status => {
+ if (status === null || status === undefined || status === "") {
+ return "寰呭鎵�";
+ }
+ return approvalStatusLabelMap[status] || "寰呭鎵�";
+ };
-// 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
-const getApprovalStatusTagType = (status) => {
- if (
- status === 1 ||
- status === "1" ||
- status === "approved" ||
- status === "APPROVED"
- )
- return "success";
- if (
- status === 2 ||
- status === "2" ||
- status === "rejected" ||
- status === "REJECTED"
- )
- return "danger";
- return "warning";
-};
+ // 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
+ const getApprovalStatusTagType = status => {
+ if (
+ status === 1 ||
+ status === "1" ||
+ status === "approved" ||
+ status === "APPROVED"
+ )
+ return "success";
+ if (
+ status === 2 ||
+ status === "2" ||
+ status === "rejected" ||
+ status === "REJECTED"
+ )
+ return "danger";
+ return "warning";
+ };
-// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
-const fetchStockRecordTypeOptions = () => {
- if (props.type === "0") {
- findAllQualifiedStockOutRecordTypeOptions().then((res) => {
+ // 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+ const fetchStockRecordTypeOptions = () => {
+ if (props.type === "0") {
+ findAllQualifiedStockOutRecordTypeOptions().then(res => {
+ stockRecordTypeOptions.value = res.data;
+ });
+ return;
+ }
+ findAllUnQualifiedStockOutRecordTypeOptions().then(res => {
stockRecordTypeOptions.value = res.data;
});
- return;
- }
- findAllUnQualifiedStockOutRecordTypeOptions().then((res) => {
- stockRecordTypeOptions.value = res.data;
- });
-};
+ };
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter((item) => item.id);
- console.log("selection", selectedRows.value);
-};
-const expandedRowKeys = ref([]);
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter(item => item.id);
+ console.log("selection", selectedRows.value);
+ };
+ const expandedRowKeys = ref([]);
-const handleBatchApprove = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map((item) => item.id);
- ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
- confirmButtonText: "閫氳繃",
- cancelButtonText: "椹冲洖",
- type: "warning",
- distinguishCancelAndClose: true,
- })
- .then(() => {
- batchApproveStockOutRecords({ ids, approvalStatus: 1 })
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
- });
+ const handleBatchApprove = () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
+ ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
+ confirmButtonText: "閫氳繃",
+ cancelButtonText: "椹冲洖",
+ type: "warning",
+ distinguishCancelAndClose: true,
})
- .catch((action) => {
- if (action === "cancel") {
- batchApproveStockOutRecords({ ids, approvalStatus: 2 })
+ .then(() => {
+ batchApproveStockOutRecords({ ids, approvalStatus: 1 })
.then(() => {
- proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
+ proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
getList();
})
.catch(() => {
- proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
+ proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
});
- return;
- }
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download(
- "/stockOutRecord/exportStockOutRecord",
- { type: props.type },
- props.type === "0" ? "鍚堟牸鍑哄簱鍙拌处.xlsx" : "涓嶅悎鏍煎嚭搴撳彴璐�.xlsx"
- );
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-// 鍒犻櫎
-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(() => {
- delPendingStockOut(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
+ })
+ .catch(action => {
+ if (action === "cancel") {
+ batchApproveStockOutRecords({ ids, approvalStatus: 2 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
+ });
+ return;
+ }
+ proxy.$modal.msg("宸插彇娑�");
});
+ };
+
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
})
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
+ .then(() => {
+ proxy.download(
+ "/stockOutRecord/exportStockOutRecord",
+ { type: props.type },
+ props.type === "0" ? "鍚堟牸鍑哄簱鍙拌处.xlsx" : "涓嶅悎鏍煎嚭搴撳彴璐�.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
-// 鎵撳嵃鍔熻兘
-const handlePrint = () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
- return;
- }
- printData.value = [...selectedRows.value];
- console.log("鎵撳嵃鏁版嵁:", printData.value);
- printPreviewVisible.value = true;
-};
+ // 鍒犻櫎
+ 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(() => {
+ delPendingStockOut(ids).then(res => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
-// 鎵ц鎵撳嵃
-const executePrint = () => {
- console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
- console.log("鎵撳嵃鏁版嵁:", printData.value);
+ // 鎵撳嵃鍔熻兘
+ const handlePrint = () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+ return;
+ }
+ printData.value = [...selectedRows.value];
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
+ printPreviewVisible.value = true;
+ };
- // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
- const printWindow = window.open("", "_blank", "width=800,height=600");
+ // 鎵ц鎵撳嵃
+ const executePrint = () => {
+ console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
- // 鏋勫缓鎵撳嵃鍐呭
- let printContent = `
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>鎵撳嵃棰勮</title>
- <style>
- body {
- margin: 0;
- padding: 0;
- font-family: "SimSun", serif;
- background: white;
- }
- .print-page {
- width: 200mm;
- height: 75mm;
- padding: 10mm;
- padding-left: 20mm;
- background: white;
- box-sizing: border-box;
- page-break-after: always;
- page-break-inside: avoid;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
- .delivery-note {
- width: 100%;
- height: 100%;
- font-size: 12px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
- color: #000;
- }
- .header {
- text-align: center;
- margin-bottom: 8px;
- }
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
- .document-title {
- font-size: 16px;
- font-weight: bold;
- }
- .info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .info-row {
- line-height: 20px;
- }
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 12px;
- }
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 12px;
- }
- .table-section {
- margin-bottom: 40px;
- // flex: 0.6;
- }
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
- }
- .product-table th, .product-table td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 12px;
- line-height: 1.4;
- }
- .product-table th {
- font-weight: bold;
- }
- .total-value {
- font-weight: bold;
- }
- .footer-section {
- margin-top: auto;
- }
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 22px;
- justify-content: space-between;
- }
- .footer-item {
- display: flex;
- margin-right: 20px;
- }
- .footer-item .label {
- font-weight: bold;
- width: 80px;
- font-size: 12px;
- }
- .footer-item .value {
- min-width: 80px;
- font-size: 12px;
- }
- .address-item .address-value {
- min-width: 200px;
- }
- @media print {
+ // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+ const printWindow = window.open("", "_blank", "width=800,height=600");
+
+ // 鏋勫缓鎵撳嵃鍐呭
+ let printContent = `
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset="UTF-8">
+ <title>鎵撳嵃棰勮</title>
+ <style>
body {
margin: 0;
padding: 0;
+ font-family: "SimSun", serif;
+ background: white;
}
- .print-page {
- margin: 0;
- padding: 10mm;
- /* padding-left: 20mm; */
- page-break-inside: avoid;
- page-break-after: always;
- }
+ .print-page {
+ width: 200mm;
+ height: 75mm;
+ padding: 10mm;
+ padding-left: 20mm;
+ background: white;
+ box-sizing: border-box;
+ page-break-after: always;
+ page-break-inside: avoid;
+ }
.print-page:last-child {
page-break-after: avoid;
}
- }
- </style>
- </head>
- <body>
- `;
+ .delivery-note {
+ width: 100%;
+ height: 100%;
+ font-size: 12px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+ color: #000;
+ }
+ .header {
+ text-align: center;
+ margin-bottom: 8px;
+ }
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+ .info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+ .info-row {
+ line-height: 20px;
+ }
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 12px;
+ }
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 12px;
+ }
+ .table-section {
+ margin-bottom: 40px;
+ // flex: 0.6;
+ }
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+ }
+ .product-table th, .product-table td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 12px;
+ line-height: 1.4;
+ }
+ .product-table th {
+ font-weight: bold;
+ }
+ .total-value {
+ font-weight: bold;
+ }
+ .footer-section {
+ margin-top: auto;
+ }
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 22px;
+ justify-content: space-between;
+ }
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+ }
+ .footer-item .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 12px;
+ }
+ .footer-item .value {
+ min-width: 80px;
+ font-size: 12px;
+ }
+ .address-item .address-value {
+ min-width: 200px;
+ }
+ @media print {
+ body {
+ margin: 0;
+ padding: 0;
+ }
+ .print-page {
+ margin: 0;
+ padding: 10mm;
+ /* padding-left: 20mm; */
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+ }
+ </style>
+ </head>
+ <body>
+ `;
- // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
- printData.value.forEach((item, index) => {
- printContent += `
- <div class="print-page">
- <div class="delivery-note">
- <div class="header">
- <div class="document-title">闆跺敭鍙戣揣鍗�</div>
- </div>
-
- <div class="info-section">
- <div class="info-row">
- <div>
- <span class="label">鍙戣揣鏃ユ湡锛�</span>
- <span class="value">${formatDate(item.createTime)}</span>
+ // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+ printData.value.forEach((item, index) => {
+ printContent += `
+ <div class="print-page">
+ <div class="delivery-note">
+ <div class="header">
+ <div class="document-title">闆跺敭鍙戣揣鍗�</div>
+ </div>
+
+ <div class="info-section">
+ <div class="info-row">
+ <div>
+ <span class="label">鍙戣揣鏃ユ湡锛�</span>
+ <span class="value">${formatDate(item.createTime)}</span>
+ </div>
+ <div>
+ <span class="label">瀹㈡埛鍚嶇О锛�</span>
+ <span class="value">${item.supplierName}</span>
+ </div>
</div>
- <div>
- <span class="label">瀹㈡埛鍚嶇О锛�</span>
- <span class="value">${item.supplierName}</span>
+ <div class="info-row">
+ <span class="label">鍗曞彿锛�</span>
+ <span class="value">${item.code || ""}</span>
</div>
</div>
- <div class="info-row">
- <span class="label">鍗曞彿锛�</span>
- <span class="value">${item.code || ""}</span>
- </div>
- </div>
- <div class="table-section">
- <table class="product-table">
- <thead>
- <tr>
- <th>浜у搧鍚嶇О</th>
- <th>瑙勬牸鍨嬪彿</th>
- <th>鍗曚綅</th>
- <th>鍗曚环</th>
- <th>闆跺敭鏁伴噺</th>
- <th>闆跺敭閲戦</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>${item.productName || "鐮傜伆鐮�"}</td>
- <td>${item.model || "鏍囧噯"}</td>
- <td>${item.unit || "鍧�"}</td>
- <td>${item.taxInclusiveUnitPrice || "0"}</td>
- <td>${item.inboundNum || "2000"}</td>
- <td>${item.taxInclusiveTotalPrice || "0"}</td>
- </tr>
- </tbody>
- <tfoot>
- <tr>
- <td class="label">鍚堣</td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value"></td>
- <td class="total-value">${item.inboundNum || "2000"}</td>
- <td class="total-value">${
- item.taxInclusiveTotalPrice || "0"
- }</td>
- </tr>
- </tfoot>
- </table>
- </div>
-
- <div class="footer-section">
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鏀惰揣鐢佃瘽锛�</span>
- <span class="value"></span>
- </div>
- <div class="footer-item">
- <span class="label">鏀惰揣浜猴細</span>
- <span class="value"></span>
- </div>
- <div class="footer-item address-item">
- <span class="label">鏀惰揣鍦板潃锛�</span>
- <span class="value address-value"></span>
- </div>
+ <div class="table-section">
+ <table class="product-table">
+ <thead>
+ <tr>
+ <th>浜у搧鍚嶇О</th>
+ <th>瑙勬牸鍨嬪彿</th>
+ <th>鍗曚綅</th>
+ <th>鍗曚环</th>
+ <th>闆跺敭鏁伴噺</th>
+ <th>闆跺敭閲戦</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>${item.productName || "鐮傜伆鐮�"}</td>
+ <td>${item.model || "鏍囧噯"}</td>
+ <td>${item.unit || "鍧�"}</td>
+ <td>${item.taxInclusiveUnitPrice || "0"}</td>
+ <td>${item.inboundNum || "2000"}</td>
+ <td>${item.taxInclusiveTotalPrice || "0"}</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="label">鍚堣</td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value"></td>
+ <td class="total-value">${item.inboundNum || "2000"}</td>
+ <td class="total-value">${
+ item.taxInclusiveTotalPrice || "0"
+ }</td>
+ </tr>
+ </tfoot>
+ </table>
</div>
- <div class="footer-row">
- <div class="footer-item">
- <span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">${userStore.nickName || "鎾曞紑鍓�"}</span>
+
+ <div class="footer-section">
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鏀惰揣鐢佃瘽锛�</span>
+ <span class="value"></span>
+ </div>
+ <div class="footer-item">
+ <span class="label">鏀惰揣浜猴細</span>
+ <span class="value"></span>
+ </div>
+ <div class="footer-item address-item">
+ <span class="label">鏀惰揣鍦板潃锛�</span>
+ <span class="value address-value"></span>
+ </div>
</div>
- <div class="footer-item">
- <span class="label">鎵撳嵃鏃ユ湡锛�</span>
- <span class="value">${formatDateTime(new Date())}</span>
+ <div class="footer-row">
+ <div class="footer-item">
+ <span class="label">鎿嶄綔鍛橈細</span>
+ <span class="value">${userStore.nickName || "鎾曞紑鍓�"}</span>
+ </div>
+ <div class="footer-item">
+ <span class="label">鎵撳嵃鏃ユ湡锛�</span>
+ <span class="value">${formatDateTime(new Date())}</span>
+ </div>
</div>
</div>
</div>
</div>
- </div>
+ `;
+ });
+
+ printContent += `
+ </body>
+ </html>
`;
+
+ // 鍐欏叆鍐呭鍒版柊绐楀彛
+ printWindow.document.write(printContent);
+ printWindow.document.close();
+
+ // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+ printWindow.onload = () => {
+ setTimeout(() => {
+ printWindow.print();
+ printWindow.close();
+ printPreviewVisible.value = false;
+ }, 500);
+ };
+ };
+
+ // 鏍煎紡鍖栨棩鏈�
+ const formatDate = dateString => {
+ if (!dateString) return getCurrentDate();
+ const date = new Date(dateString);
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ return `${year}/${month}/${day}`;
+ };
+
+ // 鏍煎紡鍖栨棩鏈熸椂闂�
+ const formatDateTime = date => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ const hours = String(date.getHours()).padStart(2, "0");
+ const minutes = String(date.getMinutes()).padStart(2, "0");
+ const seconds = String(date.getSeconds()).padStart(2, "0");
+ return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+ };
+ onMounted(() => {
+ getList();
+ fetchStockRecordTypeOptions();
});
- printContent += `
- </body>
- </html>
- `;
-
- // 鍐欏叆鍐呭鍒版柊绐楀彛
- printWindow.document.write(printContent);
- printWindow.document.close();
-
- // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
- printWindow.onload = () => {
- setTimeout(() => {
- printWindow.print();
- printWindow.close();
- printPreviewVisible.value = false;
- }, 500);
- };
-};
-
-// 鏍煎紡鍖栨棩鏈�
-const formatDate = (dateString) => {
- if (!dateString) return getCurrentDate();
- const date = new Date(dateString);
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- return `${year}/${month}/${day}`;
-};
-
-// 鏍煎紡鍖栨棩鏈熸椂闂�
-const formatDateTime = (date) => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const seconds = String(date.getSeconds()).padStart(2, "0");
- return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
-};
-onMounted(() => {
- getList();
- fetchStockRecordTypeOptions();
-});
-
-watch(
- () => props.topParentProductId,
- () => {
- page.current = 1;
- getList();
- }
-);
+ watch(
+ () => props.topParentProductId,
+ () => {
+ page.current = 1;
+ getList();
+ }
+ );
</script>
<style scoped lang="scss">
-.print-preview-dialog {
- .el-dialog__body {
- padding: 0;
- max-height: 80vh;
- overflow-y: auto;
- }
-}
-
-.print-preview-container {
- .print-preview-header {
- padding: 15px;
- border-bottom: 1px solid #e4e7ed;
- text-align: center;
-
- .el-button {
- margin: 0 10px;
+ .print-preview-dialog {
+ .el-dialog__body {
+ padding: 0;
+ max-height: 80vh;
+ overflow-y: auto;
}
}
- .print-preview-content {
- padding: 20px;
- background-color: #f5f5f5;
- min-height: 400px;
- }
-}
-
-.print-page {
- width: 220mm;
- height: 90mm;
- padding: 10mm;
- margin: 0 auto;
- background: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- margin-bottom: 10px;
- box-sizing: border-box;
-}
-
-.delivery-note {
- width: 100%;
- height: 100%;
- font-family: "SimSun", serif;
- font-size: 10px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
-}
-
-.header {
- text-align: center;
- margin-bottom: 8px;
-
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
-
- .document-title {
- font-size: 16px;
- font-weight: bold;
- }
-}
-
-.info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
-
- .info-row {
- line-height: 20px;
-
- .label {
- font-weight: bold;
- width: 60px;
- font-size: 14px;
- }
-
- .value {
- margin-right: 20px;
- min-width: 80px;
- font-size: 14px;
- }
- }
-}
-
-.table-section {
- margin-bottom: 4px;
- flex: 1;
-
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
-
- th,
- td {
- border: 1px solid #000;
- padding: 6px;
+ .print-preview-container {
+ .print-preview-header {
+ padding: 15px;
+ border-bottom: 1px solid #e4e7ed;
text-align: center;
- font-size: 14px;
- line-height: 1.4;
+
+ .el-button {
+ margin: 0 10px;
+ }
}
- th {
+ .print-preview-content {
+ padding: 20px;
+ background-color: #f5f5f5;
+ min-height: 400px;
+ }
+ }
+
+ .print-page {
+ width: 220mm;
+ height: 90mm;
+ padding: 10mm;
+ margin: 0 auto;
+ background: white;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ margin-bottom: 10px;
+ box-sizing: border-box;
+ }
+
+ .delivery-note {
+ width: 100%;
+ height: 100%;
+ font-family: "SimSun", serif;
+ font-size: 10px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .header {
+ text-align: center;
+ margin-bottom: 8px;
+
+ .company-name {
+ font-size: 18px;
font-weight: bold;
+ margin-bottom: 4px;
}
- .total-label {
- text-align: right;
- font-weight: bold;
- }
-
- .total-value {
+ .document-title {
+ font-size: 16px;
font-weight: bold;
}
}
-}
-.footer-section {
- .footer-row {
+ .info-section {
+ margin-bottom: 8px;
display: flex;
- margin-bottom: 3px;
- line-height: 20px;
justify-content: space-between;
+ align-items: center;
- .footer-item {
- display: flex;
- margin-right: 20px;
+ .info-row {
+ line-height: 20px;
.label {
font-weight: bold;
- width: 80px;
+ width: 60px;
font-size: 14px;
}
.value {
+ margin-right: 20px;
min-width: 80px;
font-size: 14px;
}
+ }
+ }
- &.address-item {
- .address-value {
- min-width: 200px;
+ .table-section {
+ margin-bottom: 4px;
+ flex: 1;
+
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+
+ th,
+ td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 1.4;
+ }
+
+ th {
+ font-weight: bold;
+ }
+
+ .total-label {
+ text-align: right;
+ font-weight: bold;
+ }
+
+ .total-value {
+ font-weight: bold;
+ }
+ }
+ }
+
+ .footer-section {
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 20px;
+ justify-content: space-between;
+
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 80px;
+ font-size: 14px;
+ }
+
+ .value {
+ min-width: 80px;
+ font-size: 14px;
+ }
+
+ &.address-item {
+ .address-value {
+ min-width: 200px;
+ }
}
}
}
}
-}
-@media print {
- .app-container {
- display: none;
+ @media print {
+ .app-container {
+ display: none;
+ }
+
+ .print-page {
+ box-shadow: none;
+ margin: 0;
+ padding: 10mm;
+ padding-left: 20mm;
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
}
- .print-page {
- box-shadow: none;
- margin: 0;
- padding: 10mm;
- padding-left: 20mm;
- page-break-inside: avoid;
- page-break-after: always;
+ .actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
}
- .print-page:last-child {
- page-break-after: avoid;
- }
-}
-
-.actions {
- display: flex;
- justify-content: flex-end;
- margin-bottom: 10px;
-}
</style>
diff --git a/src/views/inventoryManagement/receiptManagement/Record.vue b/src/views/inventoryManagement/receiptManagement/Record.vue
index 3fce379..0a01def 100644
--- a/src/views/inventoryManagement/receiptManagement/Record.vue
+++ b/src/views/inventoryManagement/receiptManagement/Record.vue
@@ -1,49 +1,52 @@
<template>
<div>
- <div class="search_form" style="margin-bottom: 10px;">
- <el-form
- ref="searchFormRef"
- :model="searchForm"
- class="demo-form-inline"
- >
+ <div class="search_form"
+ style="margin-bottom: 10px;">
+ <el-form ref="searchFormRef"
+ :model="searchForm"
+ class="demo-form-inline">
<el-row :gutter="20">
<el-col :span="4">
- <el-form-item label="鍏ュ簱鏃ユ湡" prop="timeStr">
+ <el-form-item label="鍏ュ簱鏃ユ湡"
+ prop="timeStr">
<el-date-picker v-model="searchForm.timeStr"
type="date"
placeholder="璇烽�夋嫨鏃ユ湡"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="浜у搧澶х被" prop="productName">
+ <el-form-item label="浜у搧澶х被"
+ prop="productName">
<el-input v-model="searchForm.productName"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
-
<el-col :span="4">
- <el-form-item label="浜у搧瑙勬牸" prop="model">
+ <el-form-item label="瑙勬牸鍨嬪彿"
+ prop="model">
<el-input v-model="searchForm.model"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鎵瑰彿" prop="batchNo">
+ <el-form-item label="鎵瑰彿"
+ prop="batchNo">
<el-input v-model="searchForm.batchNo"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鏉ユ簮" prop="recordType">
+ <el-form-item label="鏉ユ簮"
+ prop="recordType">
<el-select v-model="searchForm.recordType"
style="width: 240px"
placeholder="璇烽�夋嫨"
@@ -51,17 +54,17 @@
<el-option v-for="item in stockRecordTypeOptions"
:key="item.value"
:label="item.label"
- :value="item.value"/>
+ :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<!-- 鎸夐挳 -->
<el-col :span="4">
<el-form-item>
- <el-button type="primary" @click="getList">
+ <el-button type="primary"
+ @click="getList">
鎼滅储
</el-button>
-
<el-button @click="resetSearch">
閲嶇疆
</el-button>
@@ -95,36 +98,36 @@
<el-table-column align="center"
type="selection"
:selectable="isRowSelectable"
- width="55"/>
+ width="55" />
<el-table-column align="center"
label="搴忓彿"
type="index"
- width="60"/>
+ width="60" />
<el-table-column label="鍏ュ簱鎵规"
prop="inboundBatches"
width="200"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="鍏ュ簱鏃堕棿"
prop="createTime"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="浜у搧澶х被"
prop="productName"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="瑙勬牸鍨嬪彿"
prop="model"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="鎵瑰彿"
prop="batchNo"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="鍗曚綅"
prop="unit"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="鍏ュ簱鏁伴噺"
prop="stockInNum"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="鍏ュ簱浜�"
prop="createBy"
- show-overflow-tooltip/>
+ show-overflow-tooltip />
<el-table-column label="鏉ユ簮"
prop="recordType"
show-overflow-tooltip>
@@ -132,12 +135,11 @@
{{ getRecordType(scope.row.recordType) }}
</template>
</el-table-column>
- <el-table-column
- v-if="showSourceOrderNoColumn"
- label="婧愬崟鍙�"
- width="150"
- prop="sourceOrderNo"
- show-overflow-tooltip>
+ <el-table-column v-if="showSourceOrderNoColumn"
+ label="婧愬崟鍙�"
+ width="150"
+ prop="sourceOrderNo"
+ show-overflow-tooltip>
<template #default="scope">
{{ formatSourceOrderNo(scope.row?.sourceOrderNo) }}
</template>
@@ -146,7 +148,8 @@
prop="approvalStatus"
show-overflow-tooltip>
<template #default="scope">
- <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)" size="small">
+ <el-tag :type="getApprovalStatusTagType(scope.row.approvalStatus)"
+ size="small">
{{ getApprovalStatusLabel(scope.row.approvalStatus) }}
</el-tag>
</template>
@@ -157,305 +160,355 @@
layout="total, sizes, prev, pager, next, jumper"
:page="page.current"
:limit="page.size"
- @pagination="pageProductChange"/>
+ @pagination="pageProductChange" />
</div>
</div>
</template>
<script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import {
- ref,
- reactive,
- toRefs,
- computed,
- onMounted,
- getCurrentInstance,
-} from "vue";
-import {ElMessageBox} from "element-plus";
-import {
- getStockInRecordListPage,
- batchDeletePendingStockInRecords,
- batchApproveStockInRecords,
- batchUnapproveStockInRecords,
-} from "@/api/inventoryManagement/stockInRecord.js";
-import {
- findAllQualifiedStockInRecordTypeOptions,
- // findAllUnQualifiedStockInRecordTypeOptions,
-} from "@/api/basicData/enum.js";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import {
+ ref,
+ reactive,
+ toRefs,
+ computed,
+ onMounted,
+ getCurrentInstance,
+ } from "vue";
+ import { ElMessageBox } from "element-plus";
+ import {
+ getStockInRecordListPage,
+ batchDeletePendingStockInRecords,
+ batchApproveStockInRecords,
+ batchUnapproveStockInRecords,
+ } from "@/api/inventoryManagement/stockInRecord.js";
+ import {
+ findAllQualifiedStockInRecordTypeOptions,
+ // findAllUnQualifiedStockInRecordTypeOptions,
+ } from "@/api/basicData/enum.js";
-const {proxy} = getCurrentInstance();
+ const { proxy } = getCurrentInstance();
-const props = defineProps({
- type: {
- type: String,
- required: true,
- default: '0'
- },
- topParentProductId: {
- type: [String, Number],
- default: undefined
- }
-})
+ const props = defineProps({
+ type: {
+ type: String,
+ required: true,
+ default: "0",
+ },
+ topParentProductId: {
+ type: [String, Number],
+ default: undefined,
+ },
+ });
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-// 鏉ユ簮绫诲瀷閫夐」
-const stockRecordTypeOptions = ref([]);
-const page = reactive({
- current: 1,
- size: 10,
-});
-const total = ref(0);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ // 鏉ユ簮绫诲瀷閫夐」
+ const stockRecordTypeOptions = ref([]);
+ const page = reactive({
+ current: 1,
+ size: 10,
+ });
+ const total = ref(0);
-const data = reactive({
- searchForm: {
- productName: "",
- batchNo: "",
- model: "",
- timeStr: "",
- recordType: "",
- },
-});
-const {searchForm} = toRefs(data);
-const searchFormRef = ref(null);
+ const data = reactive({
+ searchForm: {
+ productName: "",
+ batchNo: "",
+ model: "",
+ timeStr: "",
+ recordType: "",
+ },
+ });
+ const { searchForm } = toRefs(data);
+ const searchFormRef = ref(null);
-const resetSearch = () => {
- searchFormRef.value?.resetFields();
- page.current = 1;
- getList();
-}
+ const resetSearch = () => {
+ searchFormRef.value?.resetFields();
+ page.current = 1;
+ getList();
+ };
-const getRecordType = (recordType) => {
- return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
-}
+ const getRecordType = recordType => {
+ return (
+ stockRecordTypeOptions.value.find(item => item.value === recordType)
+ ?.label || ""
+ );
+ };
-const approvalStatusLabelMap = {
- 0: "寰呭鎵�",
- 1: "閫氳繃",
- 2: "椹冲洖",
- pending: "寰呭鎵�",
- approved: "閫氳繃",
- rejected: "椹冲洖",
- PENDING: "寰呭鎵�",
- APPROVED: "閫氳繃",
- REJECTED: "椹冲洖",
-};
-approvalStatusLabelMap[3] = "寰呯‘璁�";
+ const approvalStatusLabelMap = {
+ 0: "寰呭鎵�",
+ 1: "閫氳繃",
+ 2: "椹冲洖",
+ pending: "寰呭鎵�",
+ approved: "閫氳繃",
+ rejected: "椹冲洖",
+ PENDING: "寰呭鎵�",
+ APPROVED: "閫氳繃",
+ REJECTED: "椹冲洖",
+ };
+ approvalStatusLabelMap[3] = "寰呯‘璁�";
-const getApprovalStatusLabel = (status) => {
- if (status === null || status === undefined || status === "") {
- return "寰呭鎵�";
- }
- return approvalStatusLabelMap[status] || "寰呭鎵�";
-};
+ const getApprovalStatusLabel = status => {
+ if (status === null || status === undefined || status === "") {
+ return "寰呭鎵�";
+ }
+ return approvalStatusLabelMap[status] || "寰呭鎵�";
+ };
-// 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
-const getApprovalStatusTagType = (status) => {
- if (status === 1 || status === "1" || status === "approved" || status === "APPROVED") return "success";
- if (status === 2 || status === "2" || status === "rejected" || status === "REJECTED") return "danger";
- return "warning";
-};
+ // 閫氳繃/椹冲洖鍥哄畾鑹诧紱鍏朵綑锛堝惈寰呭鎵广�佺┖鍊笺�佹湭鏄犲皠浣嗘枃妗堜负寰呭鎵癸級缁熶竴鐢� warning 棰勮鑹�
+ const getApprovalStatusTagType = status => {
+ if (
+ status === 1 ||
+ status === "1" ||
+ status === "approved" ||
+ status === "APPROVED"
+ )
+ return "success";
+ if (
+ status === 2 ||
+ status === "2" ||
+ status === "rejected" ||
+ status === "REJECTED"
+ )
+ return "danger";
+ return "warning";
+ };
-const isPendingApproval = status => {
- return status === 0 || status === "0" || status === "pending" || status === "PENDING" || status === null || status === undefined || status === "";
-};
+ const isPendingApproval = status => {
+ return (
+ status === 0 ||
+ status === "0" ||
+ status === "pending" ||
+ status === "PENDING" ||
+ status === null ||
+ status === undefined ||
+ status === ""
+ );
+ };
-const isRejectedApproval = status => {
- return status === 2 || status === "2" || status === "rejected" || status === "REJECTED";
-};
+ const isRejectedApproval = status => {
+ return (
+ status === 2 ||
+ status === "2" ||
+ status === "rejected" ||
+ status === "REJECTED"
+ );
+ };
-const isRowSelectable = row => {
- return isPendingApproval(row?.approvalStatus) || isRejectedApproval(row?.approvalStatus);
-};
+ const isRowSelectable = row => {
+ return (
+ isPendingApproval(row?.approvalStatus) ||
+ isRejectedApproval(row?.approvalStatus)
+ );
+ };
-const canBatchApprove = computed(() => {
- return selectedRows.value.length > 0
- && selectedRows.value.every(row => isPendingApproval(row.approvalStatus));
-});
+ const canBatchApprove = computed(() => {
+ return (
+ selectedRows.value.length > 0 &&
+ selectedRows.value.every(row => isPendingApproval(row.approvalStatus))
+ );
+ });
-const canReverseApprove = computed(() => {
- return selectedRows.value.length > 0
- && selectedRows.value.every(row => isRejectedApproval(row.approvalStatus));
-});
+ const canReverseApprove = computed(() => {
+ return (
+ selectedRows.value.length > 0 &&
+ selectedRows.value.every(row => isRejectedApproval(row.approvalStatus))
+ );
+ });
-const canDelete = computed(() => canBatchApprove.value);
-const showSourceOrderNoColumn = computed(() => {
- const topParentProductId = Number(props.topParentProductId);
- return topParentProductId === 276 || topParentProductId === 278;
-});
+ const canDelete = computed(() => canBatchApprove.value);
+ const showSourceOrderNoColumn = computed(() => {
+ const topParentProductId = Number(props.topParentProductId);
+ return topParentProductId === 276 || topParentProductId === 278;
+ });
-const formatSourceOrderNo = (value) => {
- const text = String(value ?? "").trim();
- return text || "--";
-};
+ const formatSourceOrderNo = value => {
+ const text = String(value ?? "").trim();
+ return text || "--";
+ };
-const pageProductChange = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
+ const pageProductChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
-const getList = () => {
- tableLoading.value = true;
- getStockInRecordListPage(Object.assign({}, {...searchForm.value, ...page, topParentProductId: props.topParentProductId}))
+ const getList = () => {
+ tableLoading.value = true;
+ getStockInRecordListPage(
+ Object.assign(
+ {},
+ {
+ ...searchForm.value,
+ ...page,
+ topParentProductId: props.topParentProductId,
+ }
+ )
+ )
.then(res => {
tableData.value = res.data.records;
total.value = res.data.total || 0;
- }).finally(() => {
- tableLoading.value = false;
- })
-};
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ };
-// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
-const fetchStockRecordTypeOptions = () => {
- if (props.type === '0') {
- findAllQualifiedStockInRecordTypeOptions()
- .then(res => {
- stockRecordTypeOptions.value = res.data;
- })
- return
- }
- // findAllUnQualifiedStockInRecordTypeOptions()
- // .then(res => {
- // stockRecordTypeOptions.value = res.data;
- // })
-}
+ // 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+ const fetchStockRecordTypeOptions = () => {
+ if (props.type === "0") {
+ findAllQualifiedStockInRecordTypeOptions().then(res => {
+ stockRecordTypeOptions.value = res.data;
+ });
+ return;
+ }
+ // findAllUnQualifiedStockInRecordTypeOptions()
+ // .then(res => {
+ // stockRecordTypeOptions.value = res.data;
+ // })
+ };
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = selection => {
- selectedRows.value = selection.filter(item => item.id && isRowSelectable(item));
-};
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ selectedRows.value = selection.filter(
+ item => item.id && isRowSelectable(item)
+ );
+ };
-const expandedRowKeys = ref([]);
+ const expandedRowKeys = ref([]);
-const handleReverseApprove = () => {
- if (!canReverseApprove.value) {
- proxy.$modal.msgWarning("璇烽�夋嫨宸查┏鍥炵殑鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("鍙嶅鍚庤褰曞皢鎭㈠涓哄緟瀹℃壒鐘舵�侊紝鏄惁纭鍙嶅锛�", "鍙嶅", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ const handleReverseApprove = () => {
+ if (!canReverseApprove.value) {
+ proxy.$modal.msgWarning("璇烽�夋嫨宸查┏鍥炵殑鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
+ ElMessageBox.confirm("鍙嶅鍚庤褰曞皢鎭㈠涓哄緟瀹℃壒鐘舵�侊紝鏄惁纭鍙嶅锛�", "鍙嶅", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- batchUnapproveStockInRecords({ids})
- .then(() => {
- proxy.$modal.msgSuccess("鍙嶅鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("鍙嶅澶辫触");
- });
+ batchUnapproveStockInRecords({ ids })
+ .then(() => {
+ proxy.$modal.msgSuccess("鍙嶅鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鍙嶅澶辫触");
+ });
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-const handleBatchApprove = () => {
- if (!canBatchApprove.value) {
- proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
- confirmButtonText: "閫氳繃",
- cancelButtonText: "椹冲洖",
- type: "warning",
- distinguishCancelAndClose: true,
- })
+ const handleBatchApprove = () => {
+ if (!canBatchApprove.value) {
+ proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
+ ElMessageBox.confirm("璇烽�夋嫨瀹℃壒缁撴灉", "瀹℃壒", {
+ confirmButtonText: "閫氳繃",
+ cancelButtonText: "椹冲洖",
+ type: "warning",
+ distinguishCancelAndClose: true,
+ })
.then(() => {
- batchApproveStockInRecords({ids, approvalStatus: 1})
+ batchApproveStockInRecords({ ids, approvalStatus: 1 })
+ .then(() => {
+ proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
+ });
+ })
+ .catch(action => {
+ if (action === "cancel") {
+ batchApproveStockInRecords({ ids, approvalStatus: 2 })
.then(() => {
- proxy.$modal.msgSuccess("瀹℃壒閫氳繃鎴愬姛");
+ proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
getList();
})
.catch(() => {
- proxy.$modal.msgError("瀹℃壒閫氳繃澶辫触");
+ proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
});
- })
- .catch((action) => {
- if (action === "cancel") {
- batchApproveStockInRecords({ids, approvalStatus: 2})
- .then(() => {
- proxy.$modal.msgSuccess("瀹℃壒椹冲洖鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("瀹℃壒椹冲洖澶辫触");
- });
return;
}
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
// 鏍规嵁涓嶅悓鐨� tab 绫诲瀷璋冪敤涓嶅悓鐨勫鍑烘帴鍙�
- proxy.download("/stockInRecord/exportStockInRecord", {type: props.type}, props.type === '0' ? "鍚堟牸鍏ュ簱.xlsx" : "涓嶅悎鏍煎叆搴�.xlsx");
+ proxy.download(
+ "/stockInRecord/exportStockInRecord",
+ { type: props.type },
+ props.type === "0" ? "鍚堟牸鍏ュ簱.xlsx" : "涓嶅悎鏍煎叆搴�.xlsx"
+ );
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-// 鍒犻櫎
-const handleDelete = () => {
- if (!canDelete.value) {
- proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
- return;
- }
- const ids = selectedRows.value.map(item => item.id);
+ // 鍒犻櫎
+ const handleDelete = () => {
+ if (!canDelete.value) {
+ proxy.$modal.msgWarning("璇烽�夋嫨寰呭鎵圭殑鏁版嵁");
+ return;
+ }
+ const ids = selectedRows.value.map(item => item.id);
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
batchDeletePendingStockInRecords(ids)
- .then(() => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
- })
- .catch(() => {
- proxy.$modal.msgError("鍒犻櫎澶辫触");
- });
+ .then(() => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鍒犻櫎澶辫触");
+ });
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
+ };
-onMounted(() => {
- getList();
- fetchStockRecordTypeOptions();
-});
-
-watch(
- () => props.topParentProductId,
- () => {
- page.current = 1;
+ onMounted(() => {
getList();
- }
-);
+ fetchStockRecordTypeOptions();
+ });
+
+ watch(
+ () => props.topParentProductId,
+ () => {
+ page.current = 1;
+ getList();
+ }
+ );
</script>
<style scoped lang="scss">
-.actions {
- display: flex;
- justify-content: flex-end;
- margin-bottom: 10px;
-}
+ .actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+ }
</style>
diff --git a/src/views/inventoryManagement/stockManagement/Record.vue b/src/views/inventoryManagement/stockManagement/Record.vue
index d898a37..8f58262 100644
--- a/src/views/inventoryManagement/stockManagement/Record.vue
+++ b/src/views/inventoryManagement/stockManagement/Record.vue
@@ -1,384 +1,358 @@
<template>
<div>
<div class="search_form mb10">
- <el-form
- ref="searchFormRef"
- :model="searchForm"
- class="demo-form-inline"
- >
+ <el-form ref="searchFormRef"
+ :model="searchForm"
+ class="demo-form-inline">
<el-row :gutter="20">
<el-col :span="4">
- <el-form-item label="浜у搧澶х被" prop="productName">
+ <el-form-item label="浜у搧澶х被"
+ prop="productName">
<el-input v-model="searchForm.productName"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
-
<el-col :span="4">
- <el-form-item label="浜у搧瑙勬牸" prop="model">
+ <el-form-item label="瑙勬牸鍨嬪彿"
+ prop="model">
<el-input v-model="searchForm.model"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="4">
- <el-form-item label="鎵瑰彿" prop="batchNo">
+ <el-form-item label="鎵瑰彿"
+ prop="batchNo">
<el-input v-model="searchForm.batchNo"
style="width: 240px"
placeholder="璇疯緭鍏�"
- clearable/>
+ clearable />
</el-form-item>
</el-col>
<el-col :span="24" :sm="24" :md="12" :lg="12">
<el-form-item>
- <div style="display: flex; align-items: center; gap: 4px; width: 100%; flex-wrap: wrap;">
- <el-button type="primary" @click="getList">
- 鎼滅储
- </el-button>
-
- <el-button @click="resetSearch">
- 閲嶇疆
- </el-button>
- <div style="display: flex; gap: 4px; margin-left: auto;">
- <el-button type="primary" @click="isShowNewModal = true">
- 鏂板搴撳瓨
- </el-button>
- <el-button
- type="info"
- plain
- icon="Upload"
- @click="isShowImportModal = true"
- >
- 瀵煎叆搴撳瓨
- </el-button>
- <el-button @click="handleOut">瀵煎嚭</el-button>
- </div>
- </div>
+ <el-button type="primary"
+ @click="getList">
+ 鎼滅储
+ </el-button>
+ <el-button @click="resetSearch">
+ 閲嶇疆
+ </el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
+ <div>
+ <el-button type="primary"
+ @click="isShowNewModal = true">鏂板搴撳瓨</el-button>
+ <el-button type="info"
+ plain
+ icon="Upload"
+ @click="isShowImportModal = true">
+ 瀵煎叆搴撳瓨
+ </el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ </div>
</div>
<div class="table_list">
- <el-table
- :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row, index) => index"
- style="width: 100%"
- :row-class-name="tableRowClassName"
- height="calc(100vh - 18.5em)"
- >
- <el-table-column align="center" type="selection" width="55" />
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column
- label="浜у搧鍚嶇О"
- prop="productName"
- show-overflow-tooltip
- />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="model" show-overflow-tooltip />
- <el-table-column label="鍗曚綅" prop="unit" show-overflow-tooltip />
- <el-table-column label="鎵瑰彿" prop="batchNo" show-overflow-tooltip />
- <el-table-column
- label="鍚堟牸搴撳瓨鏁伴噺"
- prop="qualifiedQuantity"
- show-overflow-tooltip
- />
- <el-table-column
- label="涓嶅悎鏍煎簱瀛樻暟閲�"
- prop="unQualifiedQuantity"
- show-overflow-tooltip
- />
- <el-table-column
- label="鍚堟牸鍐荤粨鏁伴噺"
- prop="qualifiedLockedQuantity"
- show-overflow-tooltip
- />
- <el-table-column
- label="涓嶅悎鏍煎喕缁撴暟閲�"
- prop="unQualifiedLockedQuantity"
- show-overflow-tooltip
- />
- <el-table-column
- label="搴撳瓨棰勮鏁伴噺"
- prop="warnNum"
- show-overflow-tooltip
- />
- <el-table-column label="澶囨敞" prop="remark" show-overflow-tooltip />
- <el-table-column
- label="鏈�杩戞洿鏂版椂闂�"
- prop="updateTime"
- show-overflow-tooltip
- />
- <el-table-column
- fixed="right"
- label="鎿嶄綔"
- min-width="80"
- align="center"
- >
+ <el-table :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row, index) => index"
+ style="width: 100%"
+ :row-class-name="tableRowClassName"
+ height="calc(100vh - 18.5em)">
+ <el-table-column align="center"
+ type="selection"
+ width="55" />
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="浜у搧鍚嶇О"
+ prop="productName"
+ show-overflow-tooltip />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="model"
+ show-overflow-tooltip />
+ <el-table-column label="鍗曚綅"
+ prop="unit"
+ show-overflow-tooltip />
+ <el-table-column label="鎵瑰彿"
+ prop="batchNo"
+ show-overflow-tooltip />
+ <el-table-column label="鍚堟牸搴撳瓨鏁伴噺"
+ prop="qualifiedQuantity"
+ show-overflow-tooltip />
+ <el-table-column label="涓嶅悎鏍煎簱瀛樻暟閲�"
+ prop="unQualifiedQuantity"
+ show-overflow-tooltip />
+ <el-table-column label="鍚堟牸鍐荤粨鏁伴噺"
+ prop="qualifiedLockedQuantity"
+ show-overflow-tooltip />
+ <el-table-column label="涓嶅悎鏍煎喕缁撴暟閲�"
+ prop="unQualifiedLockedQuantity"
+ show-overflow-tooltip />
+ <el-table-column label="搴撳瓨棰勮鏁伴噺"
+ prop="warnNum"
+ show-overflow-tooltip />
+ <el-table-column label="澶囨敞"
+ prop="remark"
+ show-overflow-tooltip />
+ <el-table-column label="鏈�杩戞洿鏂版椂闂�"
+ prop="updateTime"
+ show-overflow-tooltip />
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ min-width="80"
+ align="center">
<template #default="scope">
- <el-button
- link
- type="primary"
- @click="showDetailModal(scope.row)"
- >璇︽儏</el-button
- >
+ <el-button link
+ type="primary"
+ @click="showDetailModal(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"
- />
+ <pagination v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange" />
</div>
- <batch-no-qty-detail
- v-if="isShowDetailModal"
- v-model:visible="isShowDetailModal"
- :record="record"
- @subtract="handleDetailSubtract"
- @frozen="handleDetailFrozen"
- @thaw="handleDetailThaw"
- />
- <new-stock-inventory
- v-if="isShowNewModal"
- v-model:visible="isShowNewModal"
- :top-product-parent-id="props.productId"
- @completed="handleQuery"
- />
-
- <subtract-stock-inventory
- v-if="isShowSubtractModal"
- v-model:visible="isShowSubtractModal"
- :record="record"
- :type="record.stockType"
- @completed="handleQuery"
- />
+ <batch-no-qty-detail v-if="isShowDetailModal"
+ v-model:visible="isShowDetailModal"
+ :record="record"
+ @subtract="handleDetailSubtract"
+ @frozen="handleDetailFrozen"
+ @thaw="handleDetailThaw" />
+ <new-stock-inventory v-if="isShowNewModal"
+ v-model:visible="isShowNewModal"
+ :top-product-parent-id="props.productId"
+ @completed="handleQuery" />
+ <subtract-stock-inventory v-if="isShowSubtractModal"
+ v-model:visible="isShowSubtractModal"
+ :record="record"
+ :type="record.stockType"
+ @completed="handleQuery" />
<!-- 瀵煎叆搴撳瓨-->
- <import-stock-inventory
- v-if="isShowImportModal"
- v-model:visible="isShowImportModal"
- type="qualified"
- @uploadSuccess="handleQuery"
- />
+ <import-stock-inventory v-if="isShowImportModal"
+ v-model:visible="isShowImportModal"
+ type="qualified"
+ @uploadSuccess="handleQuery" />
<!-- 鍐荤粨/瑙e喕搴撳瓨-->
- <frozen-and-thaw-stock-inventory
- v-if="isShowFrozenAndThawModal"
- v-model:visible="isShowFrozenAndThawModal"
- :record="record"
- :operation-type="operationType"
- :type="record.stockType"
- @completed="handleQuery"
- />
+ <frozen-and-thaw-stock-inventory v-if="isShowFrozenAndThawModal"
+ v-model:visible="isShowFrozenAndThawModal"
+ :record="record"
+ :operation-type="operationType"
+ :type="record.stockType"
+ @completed="handleQuery" />
</div>
</template>
<script setup>
-import pagination from "@/components/PIMTable/Pagination.vue";
-import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
-import { ElMessage, ElMessageBox } from "element-plus";
-import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js";
-const props = defineProps({
- productId: {
- type: Number,
- required: true,
- default: 0,
- },
-});
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { getStockInventoryListPageCombined } from "@/api/inventoryManagement/stockInventory.js";
+ const props = defineProps({
+ productId: {
+ type: Number,
+ required: true,
+ default: 0,
+ },
+ });
-const NewStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/New.vue")
-);
-const SubtractStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/Subtract.vue")
-);
-const ImportStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/Import.vue")
-);
-const FrozenAndThawStockInventory = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue")
-);
-const BatchNoQtyDetail = defineAsyncComponent(() =>
- import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue")
-);
-const { proxy } = getCurrentInstance();
-const tableData = ref([]);
-const selectedRows = ref([]);
-const record = ref({});
-const tableLoading = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-// 鏄惁鏄剧ず鏂板寮规
-const isShowNewModal = ref(false);
-// 鏄惁鏄剧ず棰嗙敤寮规
-const isShowSubtractModal = ref(false);
-// 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
-const isShowFrozenAndThawModal = ref(false);
-// 鏄惁鏄剧ず璇︽儏寮规
-const isShowDetailModal = ref(false);
-// 鎿嶄綔绫诲瀷
-const operationType = ref("frozen");
-// 鏄惁鏄剧ず瀵煎叆寮规
-const isShowImportModal = ref(false);
-const data = reactive({
- searchForm: {
- productName: "",
- model: "",
- batchNo: "",
- topParentProductId: props.productId,
- },
-});
-const { searchForm } = toRefs(data);
-const searchFormRef = ref(null);
+ const NewStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/New.vue")
+ );
+ const SubtractStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/Subtract.vue")
+ );
+ const ImportStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/Import.vue")
+ );
+ const FrozenAndThawStockInventory = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/FrozenAndThaw.vue")
+ );
+ const BatchNoQtyDetail = defineAsyncComponent(() =>
+ import("@/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue")
+ );
+ const { proxy } = getCurrentInstance();
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const record = ref({});
+ const tableLoading = ref(false);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ });
+ const total = ref(0);
+ // 鏄惁鏄剧ず鏂板寮规
+ const isShowNewModal = ref(false);
+ // 鏄惁鏄剧ず棰嗙敤寮规
+ const isShowSubtractModal = ref(false);
+ // 鏄惁鏄剧ず鍐荤粨/瑙e喕寮规
+ const isShowFrozenAndThawModal = ref(false);
+ // 鏄惁鏄剧ず璇︽儏寮规
+ const isShowDetailModal = ref(false);
+ // 鎿嶄綔绫诲瀷
+ const operationType = ref("frozen");
+ // 鏄惁鏄剧ず瀵煎叆寮规
+ const isShowImportModal = ref(false);
+ const data = reactive({
+ searchForm: {
+ productName: "",
+ model: "",
+ batchNo: "",
+ topParentProductId: props.productId,
+ },
+ });
+ const { searchForm } = toRefs(data);
+ const searchFormRef = ref(null);
-const resetSearch = () => {
- searchFormRef.value?.resetFields();
- page.current = 1;
- getList();
-}
+ const resetSearch = () => {
+ searchFormRef.value?.resetFields();
+ page.current = 1;
+ getList();
+ };
-// 鏌ヨ鍒楄〃
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-const handleQuery = () => {
- page.current = 1;
- getList();
-};
-const paginationChange = (obj) => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
-};
-const getList = () => {
- tableLoading.value = true;
- getStockInventoryListPageCombined({ ...searchForm.value, ...page })
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- total.value = res.data.total;
- // 鏁版嵁鍔犺浇瀹屾垚鍚庢鏌ュ簱瀛�
- // checkStockAndCreatePurchase();
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+ const paginationChange = obj => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+ };
+ const getList = () => {
+ tableLoading.value = true;
+ getStockInventoryListPageCombined({ ...searchForm.value, ...page })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ // 鏁版嵁鍔犺浇瀹屾垚鍚庢鏌ュ簱瀛�
+ // checkStockAndCreatePurchase();
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
+ };
+
+ const handleFileSuccess = response => {
+ const { code, msg } = response;
+ if (code == 200) {
+ ElMessage({ message: "瀵煎叆鎴愬姛", type: "success" });
+ upload.open = false;
+ emits("uploadSuccess");
+ } else {
+ ElMessage({ message: msg, type: "error" });
+ }
+ };
+
+ // 鐐瑰嚮棰嗙敤
+ const showSubtractModal = row => {
+ record.value = row;
+ isShowSubtractModal.value = true;
+ };
+
+ // 鐐瑰嚮璇︽儏
+ const showDetailModal = row => {
+ if (!row?.productId || !row?.productModelId) {
+ proxy.$modal.msgError("褰撳墠鏁版嵁缂哄皯浜у搧ID鎴栬鏍煎瀷鍙稩D");
+ return;
+ }
+ record.value = row;
+ isShowDetailModal.value = true;
+ };
+
+ const handleDetailSubtract = row => {
+ isShowDetailModal.value = false;
+ showSubtractModal(row);
+ };
+
+ const handleDetailFrozen = row => {
+ isShowDetailModal.value = false;
+ showFrozenModal(row);
+ };
+
+ const handleDetailThaw = row => {
+ isShowDetailModal.value = false;
+ showThawModal(row);
+ };
+
+ // 鐐瑰嚮鍐荤粨
+ const showFrozenModal = row => {
+ record.value = row;
+ isShowFrozenAndThawModal.value = true;
+ operationType.value = "frozen";
+ };
+
+ // 鐐瑰嚮瑙e喕
+ const showThawModal = row => {
+ record.value = row;
+ isShowFrozenAndThawModal.value = true;
+ operationType.value = "thaw";
+ };
+
+ // 琛ㄦ牸閫夋嫨鏁版嵁
+ const handleSelectionChange = selection => {
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter(item => item.id);
+ console.log("selection", selectedRows.value);
+ };
+ const expandedRowKeys = ref([]);
+
+ // 琛ㄦ牸琛岀被鍚�
+ const tableRowClassName = ({ row }) => {
+ const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
+ const warn = Number(row?.warnNum ?? 0);
+ if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
+ return "";
+ }
+ return stock < warn ? "row-low-stock" : "";
+ };
+
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
})
- .catch(() => {
- tableLoading.value = false;
- });
-};
+ .then(() => {
+ proxy.download(
+ "/stockInventory/exportStockInventory",
+ { topParentProductId: props.productId },
+ "搴撳瓨淇℃伅.xlsx"
+ );
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+ };
-const handleFileSuccess = (response) => {
- const { code, msg } = response;
- if (code == 200) {
- ElMessage({ message: "瀵煎叆鎴愬姛", type: "success" });
- upload.open = false;
- emits("uploadSuccess");
- } else {
- ElMessage({ message: msg, type: "error" });
- }
-};
-
-// 鐐瑰嚮棰嗙敤
-const showSubtractModal = (row) => {
- record.value = row;
- isShowSubtractModal.value = true;
-};
-
-// 鐐瑰嚮璇︽儏
-const showDetailModal = (row) => {
- if (!row?.productId || !row?.productModelId) {
- proxy.$modal.msgError("褰撳墠鏁版嵁缂哄皯浜у搧ID鎴栬鏍煎瀷鍙稩D");
- return;
- }
- record.value = row;
- isShowDetailModal.value = true;
-};
-
-const handleDetailSubtract = (row) => {
- isShowDetailModal.value = false;
- showSubtractModal(row);
-};
-
-const handleDetailFrozen = (row) => {
- isShowDetailModal.value = false;
- showFrozenModal(row);
-};
-
-const handleDetailThaw = (row) => {
- isShowDetailModal.value = false;
- showThawModal(row);
-};
-
-// 鐐瑰嚮鍐荤粨
-const showFrozenModal = (row) => {
- record.value = row;
- isShowFrozenAndThawModal.value = true;
- operationType.value = "frozen";
-};
-
-// 鐐瑰嚮瑙e喕
-const showThawModal = (row) => {
- record.value = row;
- isShowFrozenAndThawModal.value = true;
- operationType.value = "thaw";
-};
-
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter((item) => item.id);
- console.log("selection", selectedRows.value);
-};
-const expandedRowKeys = ref([]);
-
-// 琛ㄦ牸琛岀被鍚�
-const tableRowClassName = ({ row }) => {
- const stock = Number(row?.qualifiedUnLockedQuantity ?? 0);
- const warn = Number(row?.warnNum ?? 0);
- if (!Number.isFinite(stock) || !Number.isFinite(warn)) {
- return "";
- }
- return stock < warn ? "row-low-stock" : "";
-};
-
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- proxy.download(
- "/stockInventory/exportStockInventory",
- { topParentProductId: props.productId },
- "搴撳瓨淇℃伅.xlsx"
- );
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
-};
-
-onMounted(() => {
- getList();
-});
+ onMounted(() => {
+ getList();
+ });
</script>
<style scoped lang="scss">
-:deep(.row-low-stock td) {
- background-color: #fde2e2;
- color: #c45656;
-}
+ :deep(.row-low-stock td) {
+ background-color: #fde2e2;
+ color: #c45656;
+ }
-:deep(.row-low-stock:hover > td) {
- background-color: #fcd4d4;
-}
+ :deep(.row-low-stock:hover > td) {
+ background-color: #fcd4d4;
+ }
</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js b/src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js
new file mode 100644
index 0000000..3251f0c
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js
@@ -0,0 +1,609 @@
+import { createEmptyNode, formatDisplayTime, mapNodesFromApi, mapSignModeFromApi, mapSignModeToApi, normalizeFlowNodes, nodeSignModeLabel } from "../approve-template/approveTemplateConstants.js";
+import { buildFormPayloadFromFields, parseFormConfigToData } from "../approve-template/formConfigUtils.js";
+import { isDynamicOptionSource, resolveSelectDisplayLabel } from "../approve-template/selectOptionSource.js";
+import { appendDotNotationQuery, buildApprovalInstanceSearchDto } from "../approve-shared/approvalInstanceListSearch.js";
+
+/** 瀹℃壒绫诲瀷锛堜笌鍚庣瀛楁 approvalType 瀵归綈锛屽悗鏈熷彲鍚屾锛� */
+export const APPROVAL_TYPE_OPTIONS = [
+ { value: "cost_reimburse", label: "璐圭敤鎶ラ攢鐢宠", cellBg: "#e8f8ef", cellColor: "#1a7f4b" },
+ { value: "travel_reimburse", label: "宸梾鎶ラ攢鐢宠", cellBg: "#f0f2f5", cellColor: "#606266" },
+ { value: "overtime", label: "鍔犵彮鐢宠", cellBg: "#fdf3e8", cellColor: "#c45c26" },
+ { value: "leave", label: "璇峰亣鐢宠", cellBg: "#fce8f0", cellColor: "#b84d7a" },
+ { value: "work_handover", label: "宸ヤ綔浜ゆ帴鐢宠", cellBg: "#f0e8fc", cellColor: "#6b4d9e" },
+ { value: "regular", label: "杞鐢宠", cellBg: "#e8f4fc", cellColor: "#2b6cb0" },
+ { value: "resign", label: "绂昏亴鐢宠", cellBg: "#ffffff", cellColor: "#303133", border: "1px solid #e4e7ed" },
+ { value: "transfer", label: "璋冨矖鐢宠", cellBg: "#ffffff", cellColor: "#303133", border: "1px solid #e4e7ed" },
+ { value: "out_office", label: "鍏嚭鐢宠", cellBg: "#e8f4ff", cellColor: "#409eff" },
+ { value: "business_trip", label: "鍑哄樊鐢宠", cellBg: "#fdf6ec", cellColor: "#e6a23c" },
+ { value: "procurement", label: "閲囪喘瀹℃壒", cellBg: "#f4f4f5", cellColor: "#909399" },
+ { value: "quotation", label: "鎶ヤ环瀹℃壒", cellBg: "#f4ecfc", cellColor: "#9b59b6" },
+ { value: "shipment", label: "鍙戣揣瀹℃壒", cellBg: "#e8faf6", cellColor: "#1abc9c" },
+ { value: "enterprise_news", label: "浼佷笟鏂伴椈", cellBg: "#ecf5ff", cellColor: "#409eff" },
+];
+
+/** 鍒楄〃鏌ヨ锛氬鎵圭姸鎬侊紙涓庡悗绔� status 鏋氫妇涓�鑷达級 */
+export const APPROVAL_STATUS_SEARCH_OPTIONS = [
+ { value: "DRAFT", label: "鑽夌" },
+ { value: "PENDING", label: "寰呭鎵�" },
+ { value: "APPROVED", label: "宸查�氳繃" },
+ { value: "REJECTED", label: "宸查┏鍥�" },
+];
+
+/**
+ * 瀹℃壒鐘舵�佸睍绀猴紙涓庡悗绔� status 鏋氫妇涓�鑷达級
+ * DRAFT鈫掕崏绋� PENDING鈫掑緟瀹℃壒/杩涜涓� APPROVED鈫掑凡閫氳繃/宸插畬鎴� REJECTED鈫掑凡椹冲洖
+ */
+export const APPROVAL_STATUS_OPTIONS = [
+ { value: "draft", api: "DRAFT", label: "鑽夌" },
+ { value: "pending", api: "PENDING", label: "寰呭鎵�" },
+ { value: "approved", api: "APPROVED", label: "宸查�氳繃" },
+ { value: "rejected", api: "REJECTED", label: "宸查┏鍥�" },
+ { value: "cancelled", api: "CANCELLED", label: "宸叉挙閿�" },
+];
+
+/** 鏁板瓧鐘舵�佺爜锛堥儴鍒嗗悗绔敤 0/1/2锛� */
+const STATUS_NUMERIC_MAP = {
+ 0: "pending",
+ 1: "approved",
+ 2: "rejected",
+ 3: "cancelled",
+ 4: "cancelled",
+};
+
+/** 鍚庣 status / 椤甸潰 approvalStatus 鈫� 缁熶竴椤甸潰 key锛坧ending | approved | rejected | cancelled锛� */
+export function normalizeApprovalStatusKey(v) {
+ if (v == null || v === "") return "pending";
+ if (typeof v === "number" || (typeof v === "string" && /^\d+$/.test(v.trim()))) {
+ const numKey = STATUS_NUMERIC_MAP[Number(v)];
+ if (numKey) return numKey;
+ }
+ const s = String(v).trim();
+ if (!s) return "pending";
+ const upper = s.toUpperCase();
+ if (upper === "DRAFT") return "draft";
+ if (upper === "PUBLISHED") return "approved";
+ if (upper === "OFFLINE") return "cancelled";
+ if (upper === "APPROVED" || upper === "APPROVE" || upper === "PASS" || upper === "AGREE") {
+ return "approved";
+ }
+ if (upper === "REJECTED" || upper === "REJECT" || upper === "REFUSE" || upper === "REFUSED" || upper === "DENIED") {
+ return "rejected";
+ }
+ if (upper === "CANCELLED" || upper === "CANCEL" || upper === "REVOKED") return "cancelled";
+ if (upper === "PENDING" || upper === "IN_PROGRESS" || upper === "PROCESSING" || upper === "RUNNING" || upper === "WAIT" || upper === "WAITING") {
+ return "pending";
+ }
+ if (s.includes("鑽夌")) return "draft";
+ if (s.includes("椹冲洖") || s.includes("鎷掔粷")) return "rejected";
+ if (s.includes("涓嬬嚎")) return "cancelled";
+ if (s.includes("鎾ら攢")) return "cancelled";
+ if (s.includes("鍙戝竷") || s.includes("閫氳繃") || s.includes("瀹屾垚")) return "approved";
+ if (s.includes("寰呭") || s.includes("杩涜涓�") || s.includes("瀹℃壒涓�")) return "pending";
+ const lower = s.toLowerCase();
+ if (["draft", "pending", "approved", "rejected", "cancelled"].includes(lower)) return lower;
+ return "pending";
+}
+
+/** 浠庡垪琛�/璇︽儏琛岃В鏋愬悗绔師濮嬬姸鎬侊紙鍏煎澶氬瓧娈靛懡鍚嶏級 */
+export function resolveInstanceStatusRaw(row) {
+ if (!row || typeof row !== "object") return "";
+ const candidates = [
+ row.status,
+ row.statusRaw,
+ row.approvalStatus,
+ row.statusName,
+ row.statusLabel,
+ row.approvalStatusName,
+ row.statusDesc,
+ row.instanceStatus,
+ row.approvalInstanceStatus,
+ row.approveStatus,
+ row.auditStatus,
+ row.approvalInstance?.status,
+ row.approvalInstanceVo?.status,
+ ];
+ for (const c of candidates) {
+ if (c != null && c !== "") return c;
+ }
+ const tasks = row.tasks;
+ if (Array.isArray(tasks) && tasks.length) {
+ const rejected = tasks.some(t => normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "rejected");
+ if (rejected) return "REJECTED";
+ const allApproved = tasks.every(t => normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "approved");
+ if (allApproved) return "APPROVED";
+ }
+ return "";
+}
+
+/** 鎻愪氦寮圭獥锛氭ā鏉垮崱鐗囷紙鏉ヨ嚜鍚庣鍒楄〃锛� */
+export function mapSubmitTemplateCard(row) {
+ const cfg = parseFormConfigToData(row?.formConfig);
+ return {
+ id: row?.id,
+ key: String(row?.id ?? ""),
+ businessType: row?.businessType ?? cfg.approvalType ?? row?.approvalType ?? "",
+ approvalType: cfg.approvalType || row?.approvalType || "",
+ label: row?.templateName || "鈥�",
+ summaryPlaceholder: (row?.description || "").trim() || cfg.summaryPlaceholder || "鐐瑰嚮濉啓骞舵彁浜�",
+ };
+}
+
+export function matchBusinessTypeValue(a, b) {
+ if (a == null || a === "" || b == null || b === "") return false;
+ return a === b || a === Number(b) || Number(a) === b || String(a) === String(b);
+}
+
+/** 瀹℃壒璁板綍 approveAction 鈫� 椤甸潰 result */
+export function mapRecordResultFromApi(action) {
+ const s = String(action || "").toUpperCase();
+ if (s === "APPROVED" || s === "APPROVE" || s === "PASS") return "approved";
+ if (s === "REJECTED" || s === "REJECT" || s === "REFUSE") return "rejected";
+ return "pending";
+}
+
+/** 鍚庣 records 鈫� 鏃堕棿绾垮睍绀虹粨鏋� */
+export function mapRecordsFromApi(records) {
+ const list = Array.isArray(records) ? records : [];
+ return list.map(r => ({
+ id: r.id,
+ operatorName: r.approverName || r.operatorName || r.createUserName || "",
+ result: mapRecordResultFromApi(r.approveAction ?? r.action ?? r.status),
+ opinion: r.approveComment || r.comment || r.opinion || "",
+ time: formatDisplayTime(r.approveTime || r.createTime || r.time || ""),
+ raw: r,
+ }));
+}
+
+export function mapTaskStatusLabel(status) {
+ return approvalStatusLabel(status);
+}
+
+export function mapTaskStatusTagType(status) {
+ return approvalStatusTagType(status);
+}
+
+/** 鍚庣 tasks 鈫� 椤甸潰 flowNodes锛堟寜 levelNo 鍒嗙粍锛屼緵娴佺▼缂栬緫/灞曠ず锛� */
+export function mapTasksToFlowNodes(tasks) {
+ const list = Array.isArray(tasks) ? tasks : [];
+ if (!list.length) return [];
+ const byLevel = new Map();
+ list.forEach(t => {
+ const level = Number(t.levelNo ?? t.taskLevel ?? t.nodeOrder ?? 1);
+ if (!byLevel.has(level)) {
+ byLevel.set(level, {
+ id: t.nodeId,
+ templateId: t.templateId,
+ nodeOrder: level,
+ signMode: mapSignModeFromApi(t.approveType),
+ approvers: [],
+ tasks: [],
+ });
+ }
+ const node = byLevel.get(level);
+ node.approvers.push({
+ id: t.id,
+ nodeId: t.nodeId,
+ templateId: t.templateId,
+ approverId: t.approverId,
+ approverName: t.approverName || "",
+ status: t.status,
+ approveComment: t.approveComment,
+ approveTime: t.approveTime,
+ });
+ node.tasks.push(t);
+ if (t.approveType != null) {
+ node.signMode = mapSignModeFromApi(t.approveType);
+ }
+ });
+ return [...byLevel.entries()].sort(([a], [b]) => a - b).map(([, node]) => node);
+}
+
+/** 椤甸潰 flowNodes 鈫� 鍚庣 tasks */
+export function mapFlowNodesToTasks(flowNodes, { instanceId, templateId } = {}) {
+ const nodes = normalizeFlowNodes(flowNodes);
+ const tasks = [];
+ nodes.forEach(n => {
+ const levelNo = n.nodeOrder ?? 1;
+ const approveType = mapSignModeToApi(n.signMode);
+ n.approvers.forEach((a, idx) => {
+ const task = {
+ levelNo,
+ approveType,
+ approverId: a.approverId,
+ approverName: a.approverName || "",
+ sortNo: a.sortNo ?? idx + 1,
+ };
+ if (a.id != null) task.id = a.id;
+ if (a.nodeId != null) task.nodeId = a.nodeId;
+ if (a.templateId != null) task.templateId = a.templateId;
+ else if (templateId) task.templateId = templateId;
+ if (instanceId) task.instanceId = instanceId;
+ if (a.status != null) task.status = a.status;
+ tasks.push(task);
+ });
+ });
+ return tasks;
+}
+
+function guessFieldTypeFromValue(val) {
+ if (Array.isArray(val) && val.length === 2) return "datetimerange";
+ if (typeof val === "number") return "number";
+ if (typeof val === "string" && /^\d{4}-\d{2}-\d{2}$/.test(val)) return "date";
+ if (typeof val === "string" && val.length > 100) return "textarea";
+ return "text";
+}
+
+/**
+ * 鍗曞瓧娈靛睍绀哄�硷紙璇︽儏鍙銆佸垪琛ㄤ富琛級
+ * @param {object} [caches] 浜哄憳/閮ㄩ棬涓嬫媺缂撳瓨锛岀敤浜庤В鏋愩�屼汉鍛樺垪琛ㄣ�嶇被瀛楁涓哄鍚�
+ */
+export function formatFieldDisplayValue(field, val, caches) {
+ if (val == null || val === "" || (Array.isArray(val) && !val.length)) return "鈥�";
+ if (field?.type === "select" && isDynamicOptionSource(field.optionSource)) {
+ const label = resolveSelectDisplayLabel(field, val, caches || {});
+ if (label && label !== "鈥�") return label;
+ return String(val);
+ }
+ if (field?.type === "select" && field.options?.length) {
+ const hit = field.options.find(o => String(o.value) === String(val));
+ return hit?.label || String(val);
+ }
+ if (Array.isArray(val)) return val.join(" 鑷� ");
+ return String(val);
+}
+
+/**
+ * 浠庤鏁版嵁 / formConfig 瑙f瀽濉姤瀛楁瀹氫箟涓� formPayload锛堜笌鏂板鎻愪氦缁撴瀯涓�鑷达級
+ */
+export function resolveInstanceFormFields(row) {
+ const cfg = parseInstanceFormConfig(row?.formConfig);
+ let fields = (row?.formFieldDefs?.length ? row.formFieldDefs : cfg.fields) || [];
+ const formPayload = {
+ ...(fields.length ? buildFormPayloadFromFields(fields) : {}),
+ ...cfg.formPayload,
+ ...(row?.formPayload || {}),
+ };
+ if (!fields.length && Object.keys(formPayload).length) {
+ fields = Object.keys(formPayload)
+ .filter(k => k && k !== "summary")
+ .map(k => ({
+ key: k,
+ label: k,
+ type: guessFieldTypeFromValue(formPayload[k]),
+ required: false,
+ rows: 3,
+ min: 0,
+ precision: 0,
+ options: [],
+ }));
+ }
+ const templateSnapshot = {
+ label: row?.templateName || row?.title || "瀹℃壒",
+ approvalType: cfg.approvalType || row?.approvalType || "",
+ summaryPlaceholder: cfg.summaryPlaceholder || "",
+ templateId: row?.templateId,
+ fields,
+ };
+ return { fields, formPayload, templateSnapshot, formConfigData: cfg };
+}
+
+/** 瑙f瀽瀹炰緥 formConfig */
+export function parseInstanceFormConfig(formConfig) {
+ let raw = {};
+ if (formConfig) {
+ if (typeof formConfig === "object") raw = formConfig;
+ else {
+ try {
+ raw = JSON.parse(formConfig);
+ } catch {
+ raw = {};
+ }
+ }
+ }
+ const data = parseFormConfigToData(formConfig);
+ const payload = raw.formPayload;
+ return {
+ summaryPlaceholder: raw.summaryPlaceholder || data.summaryPlaceholder || "",
+ approvalType: raw.approvalType || "",
+ fields: data.fields || [],
+ formPayload: payload && typeof payload === "object" ? payload : {},
+ };
+}
+
+export function unwrapInstanceDetail(res) {
+ const data = res?.data ?? res;
+ if (!data || typeof data !== "object") return {};
+ if (data.id != null || data.instanceNo) return data;
+ if (data.approvalInstanceVo) return data.approvalInstanceVo;
+ return data;
+}
+
+/** 濉姤鍐呭 + 妯℃澘瀛楁瀹氫箟 鈫� formConfig JSON */
+export function buildInstanceFormConfigJson(templateSnapshot, formPayload) {
+ const payload = formPayload || {};
+ return JSON.stringify({
+ summaryPlaceholder: templateSnapshot?.summaryPlaceholder || "",
+ approvalType: templateSnapshot?.approvalType || "",
+ fields: templateSnapshot?.fields || [],
+ formPayload: payload,
+ });
+}
+
+/** 缁勮淇濆瓨/鏇存柊瀹℃壒 DTO */
+export function buildInstanceDto({ submitForm, activeTemplate, userStore, flowNodes, existingRow }) {
+ const payload = submitForm?.formPayload || {};
+ const tpl = activeTemplate || {};
+ const title = String(payload.summary || payload.title || "").trim() || tpl.label || submitForm?.templateName || "瀹℃壒鐢宠";
+ const templateId = submitForm?.templateId || tpl.templateId;
+ const instanceId = existingRow?.id ?? submitForm?.instanceId;
+ const taskList = mapFlowNodesToTasks(flowNodes || submitForm?.flowNodes, {
+ instanceId,
+ templateId,
+ });
+ const isUpdate = Boolean(instanceId);
+
+ const dto = {
+ templateId,
+ templateName: submitForm?.templateName || tpl.label || "",
+ businessType: tpl.businessType ?? submitForm?.businessType ?? "",
+ title,
+ formConfig: buildInstanceFormConfigJson({ ...tpl, fields: tpl.fields || submitForm?.formFieldDefs }, payload),
+ tasks: taskList,
+ };
+
+ const attachments = (Array.isArray(submitForm?.storageBlobDTOs) && submitForm.storageBlobDTOs.length ? submitForm.storageBlobDTOs : null) || tpl.storageBlobDTOs;
+ if (attachments?.length) dto.storageBlobDTOs = attachments;
+
+ if (isUpdate) {
+ dto.id = existingRow?.id ?? submitForm?.instanceId;
+ dto.instanceNo = existingRow?.instanceNo ?? submitForm?.instanceNo ?? "";
+ dto.status = submitForm?.saveStatusApi || existingRow?.statusRaw || mapInstanceStatusToApi(existingRow?.approvalStatus) || "PENDING";
+ dto.currentLevel = existingRow?.currentLevel ?? submitForm?.currentLevel ?? 1;
+ dto.applicantId = existingRow?.applicantId ?? existingRow?.applicantNo;
+ dto.applicantName = existingRow?.applicantName || "";
+ } else {
+ dto.status = submitForm?.saveStatusApi || "PENDING";
+ dto.currentLevel = 1;
+ dto.applicantId = userStore?.id;
+ dto.applicantName = userStore?.nickName || userStore?.name || "";
+ }
+ return dto;
+}
+
+/** 鏍¢獙鎻愪氦瀹℃壒娴佺▼锛堜笌妯℃澘椤佃鍒欎竴鑷达級 */
+export function validateSubmitFlowNodes(flowNodes) {
+ const nodes = normalizeFlowNodes(flowNodes);
+ if (!nodes.length) return { ok: false, message: "璇疯嚦灏戦厤缃竴涓鎵硅妭鐐�" };
+ for (let i = 0; i < nodes.length; i++) {
+ if (!nodes[i].approvers.length) {
+ return { ok: false, message: `璇蜂负绗� ${i + 1} 涓妭鐐归�夋嫨鑷冲皯涓�鍚嶅鎵逛汉` };
+ }
+ }
+ return { ok: true, nodes };
+}
+
+/** 鍚庣 status 鈫� 椤甸潰 approvalStatus */
+export function mapInstanceStatusFromApi(status) {
+ return normalizeApprovalStatusKey(status);
+}
+
+/** 鍒楄〃/璇︽儏琛� 鈫� 椤甸潰 approvalStatus key */
+export function mapInstanceApprovalStatusFromRow(row) {
+ const raw = resolveInstanceStatusRaw(row);
+ return normalizeApprovalStatusKey(raw);
+}
+
+/** 椤甸潰 approvalStatus 鈫� 鍚庣 status */
+export function mapInstanceStatusToApi(approvalStatus) {
+ const key = normalizeApprovalStatusKey(approvalStatus);
+ const hit = APPROVAL_STATUS_OPTIONS.find(x => x.value === key);
+ return hit?.api || "PENDING";
+}
+
+export function unwrapInstancePage(res) {
+ const data = res?.data ?? res;
+ return {
+ records: Array.isArray(data?.records) ? data.records : [],
+ total: Number(data?.total ?? 0),
+ };
+}
+
+/** 鍒嗛〉鍒楄〃椤� 鈫� 琛ㄦ牸琛� */
+export function mapInstanceFromApi(row) {
+ if (!row) return {};
+ const statusRaw = resolveInstanceStatusRaw(row);
+ const approvalStatus = normalizeApprovalStatusKey(statusRaw);
+ const createTime = formatDisplayTime(row.createTime ?? row.applyTime ?? "");
+ const applyTime = formatDisplayTime(row.applyTime ?? "");
+ const finishTime = formatDisplayTime(row.finishTime ?? "");
+ const resolved = resolveInstanceFormFields(row);
+ const { fields, formPayload, templateSnapshot } = resolved;
+ const tasks = Array.isArray(row.tasks) ? row.tasks : [];
+ const flowNodes = tasks.length ? mapTasksToFlowNodes(tasks) : mapNodesFromApi(row.nodes || row.flowNodes);
+ const approvalRecords = mapRecordsFromApi(row.records);
+ return {
+ id: row.id,
+ bizId: row.instanceNo || String(row.id ?? ""),
+ instanceNo: row.instanceNo || "",
+ templateId: row.templateId,
+ templateName: row.templateName || "",
+ businessId: row.businessId,
+ businessType: row.businessType,
+ businessName: row.businessName || "",
+ applicantId: row.applicantId,
+ applicantNo: row.applicantId != null ? String(row.applicantId) : "",
+ applicantName: row.applicantName || "",
+ approvalType: row.approvalType || row.templateName || "",
+ unread: Boolean(row.isApprove) && approvalStatus === "pending",
+ isApprove: Boolean(row.isApprove),
+ approvalStatus,
+ statusRaw: statusRaw || row.status,
+ createTime,
+ applyTime: applyTime === "鈥�" ? "" : applyTime,
+ finishTime: finishTime === "鈥�" ? "" : finishTime,
+ title: row.title || "",
+ summary: row.title || row.templateName || "",
+ currentLevel: row.currentLevel,
+ formConfig: row.formConfig,
+ formPayload,
+ formFieldDefs: fields,
+ templateSnapshot,
+ tasks,
+ records: Array.isArray(row.records) ? row.records : [],
+ storageBlobVOList: row.storageBlobVOList || [],
+ storageBlobDTOs: row.storageBlobVOList || row.storageBlobDTOs || [],
+ flowNodes,
+ approvalFlowNodes: [],
+ currentNodeIndex: 0,
+ approvalRecords,
+ rejectReason: approvalRecords.find(r => r.result === "rejected")?.opinion || "",
+ };
+}
+
+/** 瀹℃壒鎿嶄綔锛氫笌鍚庣 status 鏋氫妇涓�鑷� */
+export const APPROVE_ACTION_APPROVED = "APPROVED";
+export const APPROVE_ACTION_REJECTED = "REJECTED";
+
+/** 椤甸潰鎿嶄綔 鈫� approveAction */
+export function mapApproveActionToApi(uiResult) {
+ return uiResult === "rejected" ? APPROVE_ACTION_REJECTED : APPROVE_ACTION_APPROVED;
+}
+
+/** 缁勮瀹℃壒鎻愪氦 DTO */
+export function buildApproveInstanceDto(row, uiResult, comment) {
+ const opinion = (comment || "").trim();
+ return {
+ id: row?.id,
+ approveAction: mapApproveActionToApi(uiResult),
+ approveComment: opinion || (uiResult === "approved" ? "鍚屾剰" : ""),
+ };
+}
+
+export function buildApprovalInstanceListParams({ page, searchForm, businessType, extraParams }) {
+ const dto = buildApprovalInstanceSearchDto(searchForm, extraParams);
+ const bizType = businessType ?? searchForm?.businessType;
+ if (bizType != null && bizType !== "") {
+ dto.businessType = bizType;
+ }
+
+ const params = {
+ current: page.current,
+ size: page.size,
+ "page.current": page.current,
+ "page.size": page.size,
+ ...dto,
+ };
+ appendDotNotationQuery(params, "approvalInstanceDto", dto);
+ return params;
+}
+
+export function approvalTypeLabel(v) {
+ return APPROVAL_TYPE_OPTIONS.find(x => x.value === v)?.label || v || "鈥�";
+}
+
+export function approvalTypeStyle(v) {
+ const hit = APPROVAL_TYPE_OPTIONS.find(x => x.value === v);
+ if (!hit) return {};
+ return {
+ backgroundColor: hit.cellBg,
+ color: hit.cellColor,
+ border: hit.border || "none",
+ };
+}
+
+export function approvalStatusLabel(v) {
+ const key = normalizeApprovalStatusKey(v);
+ return APPROVAL_STATUS_OPTIONS.find(x => x.value === key)?.label || "鈥�";
+}
+
+/** 涓氬姟鐢宠椤电姸鎬佹枃妗堬細PENDING鈫掕繘琛屼腑 APPROVED鈫掑凡瀹屾垚 REJECTED鈫掑凡椹冲洖 */
+export function businessApprovalStatusLabel(v) {
+ const key = normalizeApprovalStatusKey(v);
+ if (key === "draft") return "鑽夌";
+ if (key === "pending") return "杩涜涓�";
+ if (key === "approved") return "宸插畬鎴�";
+ if (key === "rejected") return "宸查┏鍥�";
+ if (key === "cancelled") return "宸叉挙閿�";
+ return "鈥�";
+}
+
+/**
+ * 涓氬姟鐢宠椤垫槸鍚﹀厑璁镐慨鏀癸紙浜斾釜鐢宠椤碉級
+ * 杩涜涓�(PENDING)銆佸凡瀹屾垚(APPROVED) 涓嶅彲淇敼锛涘凡椹冲洖銆佸凡鎾ら攢绛夊彲淇敼
+ */
+export function canEditBusinessInstanceRow(row) {
+ const key = normalizeApprovalStatusKey(row?.approvalStatus ?? row?.statusRaw ?? row?.status);
+ return key !== "pending" && key !== "approved";
+}
+
+export function businessApprovalStatusTagType(v) {
+ const key = normalizeApprovalStatusKey(v);
+ if (key === "draft") return "info";
+ if (key === "approved") return "success";
+ if (key === "rejected") return "danger";
+ if (key === "cancelled") return "info";
+ return "warning";
+}
+
+export function approvalStatusTagType(v) {
+ const key = normalizeApprovalStatusKey(v);
+ if (key === "draft") return "info";
+ if (key === "approved") return "success";
+ if (key === "rejected") return "danger";
+ if (key === "cancelled") return "info";
+ return "warning";
+}
+
+/** 鍒楄〃琛� 鈫� 缂栬緫琛ㄥ崟锛堜粎鐢ㄨ鏁版嵁鍥炴樉锛� */
+export function buildEditFormFromInstanceRow(row) {
+ const { fields, formPayload, templateSnapshot } = resolveInstanceFormFields(row);
+ const normalized = normalizeFlowNodes(row?.flowNodes?.length ? row.flowNodes : mapTasksToFlowNodes(row?.tasks));
+ const flowNodes = normalized.length ? JSON.parse(JSON.stringify(normalized)) : [createEmptyNode(1)];
+
+ return {
+ templateKey: String(row?.templateId || ""),
+ templateId: row?.templateId,
+ templateName: row?.templateName || templateSnapshot.label,
+ instanceId: row?.id,
+ instanceNo: row?.instanceNo || "",
+ statusRaw: row?.statusRaw || row?.status || "PENDING",
+ currentLevel: row?.currentLevel ?? 1,
+ applicantId: row?.applicantId,
+ applicantName: row?.applicantName || "",
+ templateSnapshot,
+ formFieldDefs: fields,
+ formPayload,
+ flowNodes,
+ templateAttachments: initTemplateAttachmentsFromSnapshot(templateSnapshot),
+ storageBlobDTOs: (row?.storageBlobDTOs?.length ? row.storageBlobDTOs : row?.storageBlobVOList || []).map(f => JSON.parse(JSON.stringify(f))),
+ };
+}
+
+export function createEmptySubmitForm(templateKey, templateOverride, flowNodesOverride) {
+ const tpl = templateOverride || null;
+ const payload = tpl?.fields?.length ? buildFormPayloadFromFields(tpl.fields) : { summary: "" };
+ const normalized = normalizeFlowNodes(flowNodesOverride);
+ const flowNodes = normalized.length ? JSON.parse(JSON.stringify(normalized)) : [createEmptyNode(1)];
+ return {
+ templateKey: templateKey || "",
+ templateId: tpl?.templateId || "",
+ templateName: tpl?.label || "",
+ instanceId: "",
+ instanceNo: "",
+ statusRaw: "",
+ currentLevel: 1,
+ applicantId: null,
+ applicantName: "",
+ templateSnapshot: templateOverride || null,
+ formFieldDefs: tpl?.fields || [],
+ formPayload: payload,
+ flowNodes,
+ templateAttachments: tpl?.storageBlobDTOs ? JSON.parse(JSON.stringify(tpl.storageBlobDTOs)) : [],
+ storageBlobDTOs: [],
+ };
+}
+
+export function initTemplateAttachmentsFromSnapshot(templateSnapshot) {
+ const list = templateSnapshot?.storageBlobDTOs;
+ return list?.length ? JSON.parse(JSON.stringify(list)) : [];
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/components/ApproveDetailPanel.vue b/src/views/officeProcessAutomation/ApproveManage/approve-list/components/ApproveDetailPanel.vue
new file mode 100644
index 0000000..721a5c2
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/components/ApproveDetailPanel.vue
@@ -0,0 +1,167 @@
+<!-- 瀹℃壒璇︽儏锛氬熀纭�淇℃伅 + 濉姤鍐呭 -->
+<template>
+ <div class="approve-detail-panel">
+ <div class="detail-block">
+ <div class="detail-block-title">鍩烘湰淇℃伅</div>
+ <el-descriptions :column="2"
+ border>
+ <el-descriptions-item label="涓氬姟鍗曞彿">{{ row.bizId || row.id || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="瀹℃壒鐘舵��">
+ <el-tag :type="approvalStatusTagType(row.approvalStatus)"
+ size="small"
+ effect="plain">
+ {{ approvalStatusLabel(row.approvalStatus) }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="瀹℃壒绫诲瀷">
+ <span class="approve-type-cell"
+ :style="approvalTypeStyle(row.approvalType)">
+ {{ approvalTypeLabel(row.approvalType) }}
+ </span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鐢宠浜虹紪鍙�">{{ row.applicantNo || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐢宠浜哄悕绉�">{{ row.applicantName || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐢宠鎽樿">{{ row.summary || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item v-if="row.rejectReason"
+ label="椹冲洖鍘熷洜"
+ :span="2">
+ <span class="reject-text">{{ row.rejectReason }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鍒涘缓鏃堕棿"
+ :span="2">
+ {{ formatDisplayTime(row.createTime) }}
+ </el-descriptions-item>
+ </el-descriptions>
+ </div>
+ <div class="detail-block">
+ <div class="detail-block-title">濉姤鍐呭</div>
+ <FormPayloadFields :fields="formResolved.fields"
+ :form-payload="formResolved.formPayload"
+ readonly />
+ </div>
+ <div v-if="attachmentList.length"
+ class="detail-block">
+ <div class="detail-block-title">闄勪欢鍒楄〃</div>
+ <div class="attachment-list">
+ <div v-for="file in attachmentList"
+ :key="file.id"
+ class="attachment-item">
+ <el-icon class="file-icon">
+ <Paperclip />
+ </el-icon>
+ <span class="file-name"
+ :title="file.name || file.originalFilename">
+ {{ file.name || file.originalFilename }}
+ </span>
+ <div class="file-actions">
+ <el-link v-if="file.previewURL || file.url"
+ type="primary"
+ :underline="false"
+ @click="openFile(file.previewURL || file.url)">棰勮</el-link>
+ <el-divider v-if="(file.previewURL || file.url) && file.downloadURL"
+ direction="vertical" />
+ <el-link v-if="file.downloadURL"
+ type="primary"
+ :underline="false"
+ @click="openFile(file.downloadURL)">涓嬭浇</el-link>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script setup>
+ import { computed } from "vue";
+ import { Paperclip } from "@element-plus/icons-vue";
+ import { formatDisplayTime } from "../../approve-template/approveTemplateConstants.js";
+ import {
+ approvalTypeLabel,
+ approvalTypeStyle,
+ approvalStatusLabel,
+ approvalStatusTagType,
+ resolveInstanceFormFields,
+ } from "../approveListConstants.js";
+ import FormPayloadFields from "./FormPayloadFields.vue";
+
+ const props = defineProps({
+ row: { type: Object, default: () => ({}) },
+ });
+
+ const formResolved = computed(() => resolveInstanceFormFields(props.row));
+
+ const attachmentList = computed(() => {
+ const list = props.row.storageBlobVOList || props.row.storageBlobDTOs || [];
+ return Array.isArray(list) ? list : [];
+ });
+
+ function openFile(url) {
+ if (!url) return;
+ window.open(url, "_blank");
+ }
+</script>
+
+<style scoped>
+ .approve-detail-panel {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ }
+ .detail-block-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+ margin: 0 0 12px;
+ padding-left: 10px;
+ border-left: 3px solid var(--el-color-primary);
+ line-height: 1.4;
+ }
+ .approve-type-cell {
+ display: inline-block;
+ padding: 2px 10px;
+ border-radius: 4px;
+ font-size: 13px;
+ line-height: 1.5;
+ }
+ .reject-text {
+ color: var(--el-color-danger);
+ }
+
+ .attachment-list {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ gap: 12px;
+ }
+ .attachment-item {
+ display: flex;
+ align-items: center;
+ padding: 10px 12px;
+ background-color: var(--el-fill-color-light);
+ border-radius: 6px;
+ border: 1px solid var(--el-border-color-lighter);
+ transition: all 0.3s;
+ }
+ .attachment-item:hover {
+ border-color: var(--el-color-primary-light-5);
+ background-color: var(--el-color-primary-light-9);
+ }
+ .file-icon {
+ font-size: 18px;
+ color: var(--el-text-color-secondary);
+ margin-right: 10px;
+ }
+ .file-name {
+ flex: 1;
+ font-size: 13px;
+ color: var(--el-text-color-primary);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-right: 12px;
+ }
+ .file-actions {
+ display: flex;
+ align-items: center;
+ flex-shrink: 0;
+ }
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/components/FormPayloadFields.vue b/src/views/officeProcessAutomation/ApproveManage/approve-list/components/FormPayloadFields.vue
new file mode 100644
index 0000000..7933db5
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/components/FormPayloadFields.vue
@@ -0,0 +1,152 @@
+<!-- 濉姤椤癸細缂栬緫涓鸿〃鍗曟帶浠讹紝璇︽儏涓� descriptions 琛ㄦ牸锛堜笌涓婃柟鍩虹淇℃伅涓�鑷达級 -->
+<template>
+ <template v-if="fields?.length">
+ <el-descriptions
+ v-if="readonly"
+ :column="2"
+ border
+ class="form-payload-desc"
+ >
+ <el-descriptions-item
+ v-for="field in fields"
+ :key="field.key"
+ :label="field.label"
+ :span="field.type === 'textarea' || field.type === 'datetimerange' ? 2 : 1"
+ >
+ <span class="field-value">{{ displayValue(field) }}</span>
+ </el-descriptions-item>
+ </el-descriptions>
+
+ <div
+ v-else
+ class="form-payload-edit"
+ v-loading="optionSourceLoading"
+ >
+ <el-form-item
+ v-for="field in fields"
+ :key="field.key"
+ :label="field.label"
+ :prop="`formPayload.${field.key}`"
+ :required="Boolean(field.required)"
+ >
+ <el-input
+ v-if="field.type === 'text'"
+ v-model="formPayload[field.key]"
+ :placeholder="`璇疯緭鍏�${field.label}`"
+ maxlength="200"
+ />
+ <el-input
+ v-else-if="field.type === 'textarea'"
+ v-model="formPayload[field.key]"
+ type="textarea"
+ :rows="field.rows || 3"
+ :placeholder="`璇峰~鍐�${field.label}`"
+ maxlength="2000"
+ show-word-limit
+ />
+ <el-input-number
+ v-else-if="field.type === 'number'"
+ v-model="formPayload[field.key]"
+ :min="field.min ?? 0"
+ :precision="field.precision ?? 0"
+ controls-position="right"
+ style="width: 100%"
+ />
+ <el-date-picker
+ v-else-if="field.type === 'date'"
+ v-model="formPayload[field.key]"
+ type="date"
+ :placeholder="`璇烽�夋嫨${field.label}`"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 100%"
+ />
+ <el-date-picker
+ v-else-if="field.type === 'datetimerange'"
+ v-model="formPayload[field.key]"
+ type="datetimerange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫椂闂�"
+ end-placeholder="缁撴潫鏃堕棿"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ style="width: 100%"
+ />
+ <el-select
+ v-else-if="field.type === 'select'"
+ v-model="formPayload[field.key]"
+ :placeholder="`璇烽�夋嫨${field.label}`"
+ style="width: 100%"
+ clearable
+ filterable
+ >
+ <el-option
+ v-for="o in getOptions(field)"
+ :key="String(o.value)"
+ :label="o.label"
+ :value="o.value"
+ />
+ </el-select>
+ <span v-else class="field-value">{{ displayValue(field) }}</span>
+ </el-form-item>
+ </div>
+ </template>
+ <el-empty v-else description="鏆傛棤濉姤椤�" :image-size="48" />
+</template>
+
+<script setup>
+import { onMounted, watch } from "vue";
+import { useSelectOptionSources } from "../../approve-template/useSelectOptionSources.js";
+import { formatFieldDisplayValue } from "../approveListConstants.js";
+
+const props = defineProps({
+ fields: { type: Array, default: () => [] },
+ formPayload: { type: Object, default: () => ({}) },
+ readonly: { type: Boolean, default: false },
+});
+
+const { loading: optionSourceLoading, ensureForFields, getOptions, getDisplayLabel } =
+ useSelectOptionSources();
+
+async function loadOptionCaches() {
+ await ensureForFields(props.fields);
+}
+
+onMounted(() => {
+ loadOptionCaches();
+});
+
+watch(
+ () => props.fields,
+ () => {
+ loadOptionCaches();
+ },
+ { deep: true }
+);
+
+function displayValue(field) {
+ const val = props.formPayload?.[field.key];
+ if (field.type === "select" && field.optionSource && field.optionSource !== "static") {
+ return getDisplayLabel(field, val);
+ }
+ return formatFieldDisplayValue(field, val);
+}
+</script>
+
+<style scoped>
+.form-payload-desc {
+ width: 100%;
+}
+.form-payload-desc :deep(.el-descriptions__label) {
+ width: 120px;
+ font-weight: 500;
+}
+.field-value {
+ color: var(--el-text-color-primary);
+ line-height: 1.6;
+ word-break: break-word;
+}
+.form-payload-edit {
+ width: 100%;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/components/InstanceFlowDisplay.vue b/src/views/officeProcessAutomation/ApproveManage/approve-list/components/InstanceFlowDisplay.vue
new file mode 100644
index 0000000..e5f2eef
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/components/InstanceFlowDisplay.vue
@@ -0,0 +1,147 @@
+<!-- 瀹℃壒瀹炰緥锛歵asks 瀹℃壒娴佺▼灞曠ず锛堟í鍚戞楠ゆ潯锛� -->
+<template>
+ <div v-if="displayNodes.length" class="flow-track">
+ <div
+ v-for="(node, index) in displayNodes"
+ :key="index"
+ class="flow-step"
+ :class="{ 'is-last': index === displayNodes.length - 1 }"
+ >
+ <div class="flow-step-card">
+ <div class="flow-step-badge">{{ index + 1 }}</div>
+ <div class="flow-step-main">
+ <div class="flow-step-head">
+ <span class="flow-step-name">鑺傜偣 {{ index + 1 }}</span>
+ <el-tag size="small" :type="node.signMode === 'or_sign' ? 'warning' : 'primary'" effect="plain">
+ {{ nodeSignModeLabel(node.signMode) }}
+ </el-tag>
+ </div>
+ <div class="flow-approvers">
+ <div
+ v-for="a in node.approvers"
+ :key="String(a.approverId ?? a.id)"
+ class="flow-approver"
+ >
+ <span class="flow-approver-name">{{ a.approverName || "鈥�" }}</span>
+ <el-tag
+ v-if="a.status"
+ size="small"
+ :type="mapTaskStatusTagType(a.status)"
+ effect="plain"
+ >
+ {{ mapTaskStatusLabel(a.status) }}
+ </el-tag>
+ </div>
+ <span v-if="!node.approvers?.length" class="flow-empty">鏈厤缃鎵逛汉</span>
+ </div>
+ </div>
+ </div>
+ <div v-if="index < displayNodes.length - 1" class="flow-connector" aria-hidden="true">
+ <el-icon><ArrowRight /></el-icon>
+ </div>
+ </div>
+ </div>
+ <el-empty v-else description="鏆傛棤娴佺▼鑺傜偣" :image-size="48" />
+</template>
+
+<script setup>
+import { computed } from "vue";
+import { ArrowRight } from "@element-plus/icons-vue";
+import { nodeSignModeLabel } from "../../approve-template/approveTemplateConstants.js";
+import {
+ mapTaskStatusLabel,
+ mapTaskStatusTagType,
+ mapTasksToFlowNodes,
+} from "../approveListConstants.js";
+
+const props = defineProps({
+ tasks: { type: Array, default: () => [] },
+ nodes: { type: Array, default: () => [] },
+});
+
+const displayNodes = computed(() => {
+ if (props.tasks?.length) return mapTasksToFlowNodes(props.tasks);
+ return props.nodes || [];
+});
+</script>
+
+<style scoped>
+.flow-track {
+ display: flex;
+ align-items: stretch;
+ gap: 0;
+ overflow-x: auto;
+ padding: 4px 2px 8px;
+}
+.flow-step {
+ display: flex;
+ align-items: center;
+ flex: 0 0 auto;
+}
+.flow-step-card {
+ display: flex;
+ gap: 12px;
+ min-width: 200px;
+ max-width: 260px;
+ padding: 14px;
+ border: 1px solid var(--el-border-color-lighter);
+ border-radius: 8px;
+ background: var(--el-bg-color);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
+}
+.flow-step-badge {
+ flex-shrink: 0;
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ background: var(--el-color-primary-light-9);
+ color: var(--el-color-primary);
+ font-size: 13px;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.flow-step-main {
+ flex: 1;
+ min-width: 0;
+}
+.flow-step-head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ margin-bottom: 10px;
+}
+.flow-step-name {
+ font-weight: 600;
+ font-size: 13px;
+ color: var(--el-text-color-primary);
+}
+.flow-approvers {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+.flow-approver {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 6px;
+}
+.flow-approver-name {
+ font-size: 13px;
+ color: var(--el-text-color-regular);
+}
+.flow-empty {
+ font-size: 12px;
+ color: var(--el-text-color-placeholder);
+}
+.flow-connector {
+ display: flex;
+ align-items: center;
+ padding: 0 6px;
+ color: var(--el-text-color-placeholder);
+ font-size: 16px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue b/src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue
new file mode 100644
index 0000000..bbfa56a
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue
@@ -0,0 +1,613 @@
+<!--OA妯″潡锛氬鎵瑰垪琛�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div class="search_fields">
+ <span class="search_title">妯℃澘绫诲瀷锛�</span>
+ <el-select
+ v-model="searchForm.businessType"
+ placeholder="璇烽�夋嫨妯℃澘绫诲瀷"
+ clearable
+ filterable
+ style="width: 200px"
+ >
+ <el-option
+ v-for="opt in searchBusinessTypeOptions"
+ :key="`search-biz-type-${opt.value}`"
+ :label="opt.label"
+ :value="opt.value"
+ />
+ </el-select>
+ <span class="search_title" style="margin-left: 12px">瀹℃壒鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.status"
+ placeholder="璇烽�夋嫨瀹℃壒鐘舵��"
+ clearable
+ style="width: 140px"
+ >
+ <el-option
+ v-for="opt in APPROVAL_STATUS_SEARCH_OPTIONS"
+ :key="opt.value"
+ :label="opt.label"
+ :value="opt.value"
+ />
+ </el-select>
+ <span class="search_title" style="margin-left: 12px">鍒涘缓鏃堕棿锛�</span>
+ <el-date-picker
+ v-model="searchForm.createTimeRange"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 260px"
+ clearable
+ />
+ <el-button type="primary" :icon="Search" style="margin-left: 10px" @click="handleQuery">鎼滅储</el-button>
+ <el-button :icon="RefreshRight" @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div class="search_actions">
+ <el-button type="primary" :icon="Plus" @click="openSubmitDialog">鎻愪氦瀹℃壒</el-button>
+ </div>
+ </div>
+
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ :total="page.total"
+ @pagination="pagination"
+ >
+ <template #approveType="{ row }">
+ <span class="approve-type-cell" :style="approvalTypeStyle(row.approvalType)">
+ {{ approvalTypeLabel(row.approvalType) }}
+ </span>
+ </template>
+ </PIMTable>
+ </div>
+
+ <!-- 鎻愪氦瀹℃壒锛堟寜妯℃澘锛� -->
+ <el-dialog
+ v-model="submitDialog.visible"
+ :title="submitDialogTitle"
+ width="720px"
+ append-to-body
+ destroy-on-close
+ class="approve-submit-dialog"
+ @closed="resetSubmitDialogState"
+ >
+ <template v-if="submitDialog.step === 1 && !isSubmitEdit">
+ <p class="template-hint">璇峰厛閫夋嫨妯℃澘绫诲瀷锛屽啀閫夋嫨璇ョ被鍨嬩笅宸插惎鐢ㄧ殑瀹℃壒妯℃澘銆�</p>
+ <div v-loading="submitTemplatesLoading" class="template-grid">
+ <div
+ v-for="opt in submitBusinessTypeOptions"
+ :key="`biz-type-${opt.value}`"
+ class="template-card"
+ :class="{ 'is-disabled': !countTemplatesByBusinessType(opt.value) }"
+ @click="onBusinessTypePick(opt.value)"
+ >
+ <span class="template-card-type">{{ opt.label }}</span>
+ <span class="template-card-desc">
+ {{ countTemplatesByBusinessType(opt.value) }} 涓彲鐢ㄦā鏉�
+ </span>
+ </div>
+ <el-empty
+ v-if="!submitTemplatesLoading && !submitBusinessTypeOptions.length"
+ description="鏆傛棤妯℃澘绫诲瀷"
+ :image-size="80"
+ class="template-empty"
+ />
+ </div>
+ </template>
+
+ <template v-else-if="submitDialog.step === 2 && !isSubmitEdit">
+ <p class="template-hint">
+ 褰撳墠绫诲瀷锛歿{ selectedBusinessTypeLabel || "鈥�" }}锛岃閫夋嫨鍏蜂綋瀹℃壒妯℃澘銆�
+ <el-button type="primary" link class="ml8" @click="backToBusinessTypePick">鏇存崲绫诲瀷</el-button>
+ </p>
+ <ApprovalTemplatePicker
+ :cards="submitTemplateCards"
+ :loading="submitTemplatesLoading"
+ @pick="onTemplatePick"
+ />
+ </template>
+
+ <template v-else>
+ <div v-loading="submitTemplatesLoading && !isSubmitEdit">
+ <el-form ref="submitFormRef" :model="submitForm" :rules="submitFormRules" label-width="120px">
+ <el-form-item v-if="isSubmitEdit" label="瀹℃壒绫诲瀷">
+ <span class="approve-type-cell" :style="approvalTypeStyle(activeTemplate.approvalType)">
+ {{ activeTemplate.label }}
+ </span>
+ </el-form-item>
+ <ApprovalTemplateFormSection
+ :active-template="activeTemplate"
+ :fields="submitFormFields"
+ :form-payload="submitForm.formPayload"
+ v-model:flow-nodes="submitForm.flowNodes"
+ v-model:attachments="submitForm.storageBlobDTOs"
+ :template-attachments="submitForm.templateAttachments"
+ :user-options="flowUserOptions"
+ :show-template-name="!isSubmitEdit"
+ :allow-change-template="!isSubmitEdit"
+ @change-template="backToTemplatePick"
+ />
+ </el-form>
+ </div>
+ </template>
+
+ <template #footer>
+ <el-button
+ v-if="submitDialog.step === 3 || isSubmitEdit"
+ type="primary"
+ :loading="submitSaving"
+ @click="onSubmitInstance"
+ >
+ {{ isSubmitEdit ? "淇� 瀛�" : "鎻� 浜�" }}
+ </el-button>
+ <el-button
+ v-if="submitDialog.step === 2 && !isSubmitEdit"
+ @click="backToBusinessTypePick"
+ >
+ 涓婁竴姝�
+ </el-button>
+ <el-button @click="submitDialog.visible = false">
+ {{ submitDialog.step === 1 && !isSubmitEdit ? "鍙� 娑�" : "鍏� 闂�" }}
+ </el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 璇︽儏 -->
+ <el-dialog
+ v-model="detailDialog.visible"
+ title="瀹℃壒璇︽儏"
+ width="920px"
+ append-to-body
+ destroy-on-close
+ class="approve-detail-dialog"
+ >
+ <div class="approve-detail-body">
+ <ApproveDetailPanel :row="detailRow" />
+ <div class="detail-block">
+ <div class="detail-block-title">
+ 瀹℃壒娴佺▼锛坽{ detailRow.tasks?.length || detailRow.flowNodes?.length || 0 }} 椤癸級
+ </div>
+ <InstanceFlowDisplay :tasks="detailRow.tasks" :nodes="detailRow.flowNodes" />
+ </div>
+ <div class="detail-block">
+ <div class="detail-block-title">瀹℃壒璁板綍</div>
+ <el-timeline v-if="detailRow.approvalRecords?.length" class="approve-record-timeline">
+ <el-timeline-item
+ v-for="(rec, i) in detailRow.approvalRecords"
+ :key="rec.id ?? i"
+ :type="rec.result === 'approved' ? 'success' : rec.result === 'rejected' ? 'danger' : 'primary'"
+ :timestamp="formatRecordTime(rec.time)"
+ placement="top"
+ >
+ <div class="record-item">
+ <span class="record-operator">{{ rec.operatorName || "鈥�" }}</span>
+ <el-tag
+ size="small"
+ :type="rec.result === 'approved' ? 'success' : rec.result === 'rejected' ? 'danger' : 'info'"
+ effect="plain"
+ >
+ {{ approvalActionLabel(rec.result) }}
+ </el-tag>
+ <p class="record-opinion">{{ rec.opinion || "鏃犳剰瑙�" }}</p>
+ </div>
+ </el-timeline-item>
+ </el-timeline>
+ <el-empty v-else description="鏆傛棤瀹℃壒璁板綍" :image-size="48" />
+ </div>
+ </div>
+ <template #footer>
+ <el-button
+ v-if="detailRow.approvalStatus === 'pending'"
+ @click="openEditFromDetail"
+ >
+ 淇� 鏀�
+ </el-button>
+ <el-button
+ v-if="detailRow.approvalStatus === 'pending' && detailRow.isApprove"
+ type="primary"
+ @click="openApproveFromDetail"
+ >
+ 鍘诲鎵�
+ </el-button>
+ <el-button @click="detailDialog.visible = false">鍏� 闂�</el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 宸梾/璐圭敤鎶ラ攢璇︽儏锛堝鎵瑰垪琛級 -->
+ <el-dialog
+ v-model="reimburseDialog.visible"
+ :title="reimburseDialog.mode === 'approve' ? reimburseApproveTitle : reimburseDetailTitle"
+ width="1000px"
+ append-to-body
+ destroy-on-close
+ @closed="approveOpinion = ''"
+ >
+ <FinReimburseApprovePanel
+ :mode="reimburseDialog.mode"
+ :module-key="reimburseDialog.moduleKey"
+ :reimburse-row="reimburseDialog.reimburseRow"
+ :loading="reimburseDialog.loading"
+ v-model:approve-opinion="approveOpinion"
+ />
+ <template #footer>
+ <template v-if="reimburseDialog.mode === 'approve'">
+ <el-button
+ type="success"
+ :loading="approveSubmitting"
+ @click="onReimburseApprove('approved')"
+ >
+ 閫� 杩�
+ </el-button>
+ <el-button
+ type="danger"
+ :loading="approveSubmitting"
+ @click="onReimburseApprove('rejected')"
+ >
+ 椹� 鍥�
+ </el-button>
+ <el-button :disabled="approveSubmitting" @click="reimburseDialog.visible = false">
+ 鍙� 娑�
+ </el-button>
+ </template>
+ <template v-else>
+ <el-button
+ v-if="reimburseDialog.instanceRow?.approvalStatus === 'pending'"
+ @click="openEditFromReimburseDetail"
+ >
+ 淇� 鏀�
+ </el-button>
+ <el-button
+ v-if="
+ reimburseDialog.instanceRow?.approvalStatus === 'pending' &&
+ reimburseDialog.instanceRow?.isApprove
+ "
+ type="primary"
+ @click="openReimburseApproveFromDetail"
+ >
+ 鍘诲鎵�
+ </el-button>
+ <el-button type="primary" @click="reimburseDialog.visible = false">鍏� 闂�</el-button>
+ </template>
+ </template>
+ </el-dialog>
+
+ <!-- 瀹℃壒鎿嶄綔 -->
+ <el-dialog
+ v-model="approveDialog.visible"
+ title="瀹℃壒澶勭悊"
+ width="960px"
+ append-to-body
+ destroy-on-close
+ @closed="approveOpinion = ''"
+ >
+ <ApproveDetailPanel :row="approveDialog.row" />
+ <div class="detail-block mt16">
+ <div class="detail-block-title">
+ 瀹℃壒娴佺▼锛坽{ approveDialog.row?.tasks?.length || approveDialog.row?.flowNodes?.length || 0 }} 椤癸級
+ </div>
+ <InstanceFlowDisplay :tasks="approveDialog.row?.tasks" :nodes="approveDialog.row?.flowNodes" />
+ </div>
+ <el-form label-width="100px" class="mt16">
+ <el-form-item label="瀹℃壒鎰忚" required>
+ <el-input
+ v-model="approveOpinion"
+ type="textarea"
+ :rows="3"
+ maxlength="500"
+ show-word-limit
+ placeholder="閫氳繃鍙暀绌猴紱椹冲洖璇峰~鍐欏叿浣撳師鍥�"
+ />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button
+ type="success"
+ :loading="approveSubmitting"
+ @click="onApprove('approved')"
+ >
+ 閫� 杩�
+ </el-button>
+ <el-button
+ type="danger"
+ :loading="approveSubmitting"
+ @click="onApprove('rejected')"
+ >
+ 椹� 鍥�
+ </el-button>
+ <el-button :disabled="approveSubmitting" @click="approveDialog.visible = false">
+ 鍙� 娑�
+ </el-button>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { Plus, RefreshRight } from "@element-plus/icons-vue";
+import { ElMessage } from "element-plus";
+import { computed, onMounted, ref } from "vue";
+import { APPROVAL_MODULE_KEYS } from "../approve-shared/approvalModuleRegistry.js";
+import FinReimburseApprovePanel from "../../ReimburseManage/shared/components/FinReimburseApprovePanel.vue";
+import ApprovalTemplateFormSection from "../approve-shared/components/ApprovalTemplateFormSection.vue";
+import ApprovalTemplatePicker from "../approve-shared/components/ApprovalTemplatePicker.vue";
+import { useFlowUserOptions } from "../approve-shared/useFlowUserOptions.js";
+import { formatDisplayTime } from "../approve-template/approveTemplateConstants.js";
+import { approvalTypeStyle } from "./approveListConstants.js";
+import ApproveDetailPanel from "./components/ApproveDetailPanel.vue";
+import InstanceFlowDisplay from "./components/InstanceFlowDisplay.vue";
+import { useApproveList } from "./useApproveList.js";
+
+const al = useApproveList();
+const {
+ Search,
+ APPROVAL_STATUS_SEARCH_OPTIONS,
+ searchBusinessTypeOptions,
+ loadSearchBusinessTypeOptions,
+ submitBusinessTypeOptions,
+ submitTemplateCards,
+ selectedBusinessTypeLabel,
+ countTemplatesByBusinessType,
+ submitTemplatesLoading,
+ onBusinessTypePick,
+ backToBusinessTypePick,
+ approvalTypeLabel,
+ approvalActionLabel,
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ tableColumn,
+ detailDialog,
+ detailRow,
+ reimburseDialog,
+ approveDialog,
+ approveOpinion,
+ approveSubmitting,
+ submitReimburseApprove,
+ submitDialog,
+ isSubmitEdit,
+ submitDialogTitle,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ handleQuery,
+ resetSearch,
+ pagination,
+ resetSubmitDialogState,
+ openSubmitDialog,
+ openEditDialog,
+ onTemplatePick,
+ backToTemplatePick,
+ submitInstanceForm,
+ submitApprove,
+ openDetail,
+ openApprove,
+} = al;
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+async function onSubmitInstance() {
+ const ok = await submitInstanceForm();
+ if (ok) ElMessage.success(isSubmitEdit.value ? "淇敼鎴愬姛" : "瀹℃壒宸叉彁浜�");
+}
+
+const reimburseDetailTitle = computed(() =>
+ reimburseDialog.moduleKey === APPROVAL_MODULE_KEYS.COST_REIMBURSE
+ ? "璐圭敤鎶ラ攢璇︽儏"
+ : "宸梾鎶ラ攢璇︽儏"
+);
+const reimburseApproveTitle = computed(() =>
+ reimburseDialog.moduleKey === APPROVAL_MODULE_KEYS.COST_REIMBURSE
+ ? "璐圭敤鎶ラ攢瀹℃壒"
+ : "宸梾鎶ラ攢瀹℃壒"
+);
+
+async function onApprove(result) {
+ const ret = await submitApprove(result);
+ if (ret?.needOpinion) {
+ ElMessage.warning("椹冲洖鏃惰濉啓瀹℃壒鎰忚");
+ return;
+ }
+ if (ret?.ok) {
+ ElMessage.success(result === "approved" ? "宸查�氳繃" : "宸查┏鍥�");
+ }
+}
+
+async function onReimburseApprove(result) {
+ const ret = await submitReimburseApprove(result);
+ if (ret?.needOpinion) {
+ ElMessage.warning("椹冲洖鏃惰濉啓瀹℃壒鎰忚");
+ return;
+ }
+ if (ret?.ok) {
+ ElMessage.success(result === "approved" ? "宸查�氳繃" : "宸查┏鍥�");
+ }
+}
+
+function formatRecordTime(time) {
+ return formatDisplayTime(time) || "鈥�";
+}
+
+async function openApproveFromDetail() {
+ const row = detailRow.value;
+ detailDialog.visible = false;
+ await openApprove(row);
+}
+
+function openEditFromDetail() {
+ const row = detailRow.value;
+ detailDialog.visible = false;
+ openEditDialog(row);
+}
+
+function openEditFromReimburseDetail() {
+ const row = reimburseDialog.instanceRow;
+ reimburseDialog.visible = false;
+ if (row) openEditDialog(row);
+}
+
+async function openReimburseApproveFromDetail() {
+ const row = reimburseDialog.instanceRow;
+ if (!row) return;
+ reimburseDialog.mode = "approve";
+ approveOpinion.value = "";
+}
+
+onMounted(() => {
+ loadFlowUsers();
+ loadSearchBusinessTypeOptions();
+ handleQuery();
+});
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.ml12 {
+ margin-left: 12px;
+}
+.mt16 {
+ margin-top: 16px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_fields {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 4px;
+}
+.search_actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+.approve-type-cell {
+ display: inline-block;
+ padding: 2px 10px;
+ border-radius: 4px;
+ font-size: 13px;
+ line-height: 1.5;
+}
+.template-hint {
+ font-size: 13px;
+ color: var(--el-text-color-secondary);
+ margin: 0 0 16px;
+}
+.template-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+ gap: 12px;
+ min-height: 120px;
+}
+.template-empty {
+ grid-column: 1 / -1;
+}
+.template-card {
+ padding: 14px 16px;
+ border: 1px solid var(--el-border-color-lighter);
+ border-radius: var(--radius-md, 8px);
+ cursor: pointer;
+ transition: border-color 0.2s, box-shadow 0.2s;
+ background: var(--el-fill-color-blank);
+}
+.template-card:hover {
+ border-color: var(--el-color-primary);
+ box-shadow: var(--shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.06));
+}
+.template-card.is-disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+.template-card.is-disabled:hover {
+ border-color: var(--el-border-color-lighter);
+ box-shadow: none;
+}
+.ml8 {
+ margin-left: 8px;
+}
+.template-card-type {
+ display: inline-block;
+ padding: 2px 8px;
+ border-radius: 4px;
+ font-size: 13px;
+ font-weight: 600;
+ margin-bottom: 8px;
+}
+.template-card-desc {
+ display: block;
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ line-height: 1.5;
+}
+.flow-tip {
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ margin-top: 8px;
+}
+.approve-submit-dialog :deep(.el-dialog__body) {
+ padding-top: 12px;
+}
+.approve-detail-dialog :deep(.el-dialog__body) {
+ padding-top: 16px;
+ max-height: 70vh;
+ overflow-y: auto;
+}
+.approve-detail-body .detail-block {
+ margin-top: 20px;
+}
+.approve-detail-body .detail-block-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+ margin: 0 0 12px;
+ padding-left: 10px;
+ border-left: 3px solid var(--el-color-primary);
+ line-height: 1.4;
+}
+.approve-record-timeline {
+ padding-left: 4px;
+}
+.record-item {
+ padding: 4px 0 2px;
+}
+.record-operator {
+ font-weight: 600;
+ margin-right: 8px;
+ color: var(--el-text-color-primary);
+}
+.record-opinion {
+ margin: 8px 0 0;
+ font-size: 13px;
+ color: var(--el-text-color-regular);
+ line-height: 1.5;
+}
+.detail-block-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+ margin: 0 0 12px;
+ padding-left: 10px;
+ border-left: 3px solid var(--el-color-primary);
+ line-height: 1.4;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js b/src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js
new file mode 100644
index 0000000..a4aa917
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js
@@ -0,0 +1,628 @@
+import {
+ getApprovalTemplateDetail,
+ listApprovalTemplate,
+ TEMPLATE_TYPE_CUSTOM,
+} from "@/api/officeProcessAutomation/approvalTemplate.js";
+import {
+ approveApprovalInstance,
+ deleteApprovalInstance,
+ listApprovalInstancePage,
+ saveApprovalInstance,
+ updateApprovalInstance,
+} from "@/api/officeProcessAutomation/approvalInstance.js";
+import useUserStore from "@/store/modules/user";
+import { Search } from "@element-plus/icons-vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { computed, getCurrentInstance, reactive, ref } from "vue";
+import {
+ inferReimburseModuleKeyFromInstance,
+ loadReimburseDetailForInstance,
+ navigateToReimburseManageForEdit,
+ resolveFinReimbursementIdFromInstance,
+} from "../../ReimburseManage/shared/reimburseApproveBridge.js";
+import {
+ fetchBusinessTypeOptions,
+ formatDisplayTime,
+ mapEnabledFromApi,
+ unwrapTemplateList,
+} from "../approve-template/approveTemplateConstants.js";
+import {
+ buildFormPayloadRules,
+ buildTemplateBindingFromDetail,
+ validateTemplateBinding,
+} from "../approve-shared/approvalTemplateBindingUtils.js";
+import {
+ APPROVAL_STATUS_SEARCH_OPTIONS,
+ APPROVAL_TYPE_OPTIONS,
+ approvalStatusLabel,
+ approvalStatusTagType,
+ approvalTypeLabel,
+ buildApprovalInstanceListParams,
+ buildApproveInstanceDto,
+ buildEditFormFromInstanceRow,
+ buildInstanceDto,
+ createEmptySubmitForm,
+ mapInstanceFromApi,
+ mapSubmitTemplateCard,
+ matchBusinessTypeValue,
+ unwrapInstancePage,
+} from "./approveListConstants.js";
+
+export function useApproveList() {
+ const { proxy } = getCurrentInstance() || {};
+ const userStore = useUserStore();
+
+ const tableData = ref([]);
+ const searchBusinessTypeOptions = ref([]);
+ const submitBusinessTypeOptions = ref([]);
+ const allSubmitTemplates = ref([]);
+ const selectedBusinessType = ref("");
+ const submitTemplatesLoading = ref(false);
+
+ const submitTemplateCards = computed(() => {
+ if (selectedBusinessType.value == null || selectedBusinessType.value === "") return [];
+ return allSubmitTemplates.value.filter((card) =>
+ matchBusinessTypeValue(card.businessType, selectedBusinessType.value)
+ );
+ });
+
+ const searchForm = reactive({
+ businessType: "",
+ status: "",
+ createTimeRange: [],
+ });
+
+ const tableLoading = ref(false);
+ const page = reactive({ current: 1, size: 10, total: 0 });
+
+ const detailDialog = reactive({ visible: false });
+ const detailRow = ref({});
+
+ const approveDialog = reactive({ visible: false, row: null });
+ const approveOpinion = ref("");
+ const approveSubmitting = ref(false);
+
+ /** 宸梾/璐圭敤鎶ラ攢涓撶敤璇︽儏銆佸鎵瑰脊绐� */
+ const reimburseDialog = reactive({
+ visible: false,
+ mode: "detail",
+ moduleKey: "",
+ loading: false,
+ reimburseRow: {},
+ instanceRow: null,
+ });
+
+ const submitDialog = reactive({ visible: false, step: 1, mode: "add" });
+ const submitEditRow = ref(null);
+ const submitForm = reactive(createEmptySubmitForm(""));
+ const submitFormRef = ref();
+ const submitSaving = ref(false);
+
+ const isSubmitEdit = computed(() => submitDialog.mode === "edit");
+ const submitDialogTitle = computed(() => {
+ if (submitDialog.mode === "edit") {
+ return `淇敼${activeTemplate.value?.label || submitForm.templateName || "瀹℃壒"}`;
+ }
+ if (submitDialog.step === 1) return "閫夋嫨妯℃澘绫诲瀷";
+ if (submitDialog.step === 2) return `閫夋嫨瀹℃壒妯℃澘${businessTypeLabel(selectedBusinessType.value) ? `锛�${businessTypeLabel(selectedBusinessType.value)}锛塦 : ""}`;
+ return `鎻愪氦${activeTemplate.value?.label || "瀹℃壒"}`;
+ });
+
+ const selectedBusinessTypeLabel = computed(() => businessTypeLabel(selectedBusinessType.value));
+
+ function businessTypeLabel(type) {
+ if (type == null || type === "") return "";
+ const hit = submitBusinessTypeOptions.value.find((x) => matchBusinessTypeValue(x.value, type));
+ return hit?.label || "";
+ }
+
+ function countTemplatesByBusinessType(type) {
+ return allSubmitTemplates.value.filter((card) => matchBusinessTypeValue(card.businessType, type)).length;
+ }
+
+ const activeTemplate = computed(() => submitForm.templateSnapshot || null);
+
+ /** 濉姤椤瑰畾涔夛紙鏂板/淇敼涓� formConfig 涓�鑷达級 */
+ const submitFormFields = computed(() => {
+ const tplFields = activeTemplate.value?.fields;
+ if (tplFields?.length) return tplFields;
+ return submitForm.formFieldDefs || [];
+ });
+
+ const submitFormRules = computed(() => ({
+ templateKey: [{ required: true, message: "璇烽�夋嫨瀹℃壒绫诲瀷", trigger: "change" }],
+ ...buildFormPayloadRules(submitFormFields.value),
+ }));
+
+ const tableColumn = ref([
+ // { label: "鐢宠浜虹紪鍙�", prop: "applicantNo", width: 110 },
+ { label: "鐢宠浜哄悕绉�", prop: "applicantName", minWidth: 100 },
+ { label: "妯℃澘绫诲瀷", prop: "businessName", minWidth: 120 },
+ {
+ label: "瀹℃壒绫诲瀷",
+ prop: "approvalType",
+ minWidth: 140,
+ dataType: "slot",
+ slot: "approveType",
+ },
+ {
+ label: "寰呮垜瀹℃壒",
+ prop: "unread",
+ width: 90,
+ align: "center",
+ formatData: (v) => (v ? "鏄�" : "鍚�"),
+ },
+ {
+ label: "瀹℃壒鐘舵��",
+ prop: "approvalStatus",
+ width: 100,
+ dataType: "tag",
+ formatData: (v) => approvalStatusLabel(v),
+ formatType: (v) => approvalStatusTagType(v),
+ },
+ {
+ label: "鍒涘缓鏃堕棿",
+ prop: "createTime",
+ width: 170,
+ formatData: (v) => formatDisplayTime(v),
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 240,
+ operation: [
+ { name: "璇︽儏", type: "text", clickFun: (row) => openDetail(row) },
+ {
+ name: "淇敼",
+ type: "text",
+ disabled: (row) => row.approvalStatus !== "pending",
+ clickFun: (row) => openEditDialog(row),
+ },
+ {
+ name: "瀹℃壒",
+ type: "text",
+ disabled: (row) => row.approvalStatus !== "pending" || !row.isApprove,
+ clickFun: (row) => openApprove(row),
+ },
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ clickFun: (row) => removeInstance(row),
+ },
+ ],
+ },
+ ]);
+
+ async function fetchApprovalList() {
+ tableLoading.value = true;
+ try {
+ const res = await listApprovalInstancePage(
+ buildApprovalInstanceListParams({ page, searchForm })
+ );
+ const { records, total } = unwrapInstancePage(res);
+ tableData.value = records.map(mapInstanceFromApi);
+ page.total = total;
+ } catch {
+ tableData.value = [];
+ page.total = 0;
+ ElMessage.error("瀹℃壒鍒楄〃鍔犺浇澶辫触");
+ } finally {
+ tableLoading.value = false;
+ }
+ }
+
+ async function loadSubmitTemplates() {
+ submitTemplatesLoading.value = true;
+ try {
+ const [typeOptions, customRes] = await Promise.all([
+ fetchBusinessTypeOptions(),
+ listApprovalTemplate(TEMPLATE_TYPE_CUSTOM),
+ ]);
+ submitBusinessTypeOptions.value = typeOptions;
+ allSubmitTemplates.value = unwrapTemplateList(customRes)
+ .filter((row) => mapEnabledFromApi(row.enabled))
+ .map(mapSubmitTemplateCard);
+ } catch {
+ submitBusinessTypeOptions.value = [];
+ allSubmitTemplates.value = [];
+ ElMessage.error("鍔犺浇瀹℃壒妯℃澘澶辫触");
+ } finally {
+ submitTemplatesLoading.value = false;
+ }
+ }
+
+ function handleQuery() {
+ page.current = 1;
+ fetchApprovalList();
+ }
+
+ function resetSearch() {
+ searchForm.businessType = "";
+ searchForm.status = "";
+ searchForm.createTimeRange = [];
+ handleQuery();
+ }
+
+ async function loadSearchBusinessTypeOptions() {
+ try {
+ searchBusinessTypeOptions.value = await fetchBusinessTypeOptions();
+ } catch {
+ searchBusinessTypeOptions.value = [];
+ }
+ }
+
+ function pagination({ page: p, limit }) {
+ page.current = p;
+ page.size = limit;
+ fetchApprovalList();
+ }
+
+ async function openReimburseDetail(row, mode) {
+ const moduleKey = inferReimburseModuleKeyFromInstance(row);
+ if (!moduleKey) return false;
+ reimburseDialog.mode = mode;
+ reimburseDialog.moduleKey = moduleKey;
+ reimburseDialog.instanceRow = row;
+ reimburseDialog.visible = true;
+ reimburseDialog.loading = true;
+ reimburseDialog.reimburseRow = {};
+ try {
+ const { reimburseRow, moduleKey: resolvedMk } =
+ await loadReimburseDetailForInstance(row, moduleKey);
+ reimburseDialog.moduleKey = resolvedMk || moduleKey;
+ reimburseDialog.reimburseRow = reimburseRow;
+ return true;
+ } catch {
+ ElMessage.error("鍔犺浇鎶ラ攢璇︽儏澶辫触");
+ reimburseDialog.visible = false;
+ return false;
+ } finally {
+ reimburseDialog.loading = false;
+ }
+ }
+
+ async function openDetail(row) {
+ if (isReimburseApprovalInstance(row)) {
+ await openReimburseDetail(row, "detail");
+ return;
+ }
+ detailRow.value = { ...row };
+ detailDialog.visible = true;
+ }
+
+ async function openApprove(row) {
+ if (inferReimburseModuleKeyFromInstance(row)) {
+ approveOpinion.value = "";
+ await openReimburseDetail(row, "approve");
+ return;
+ }
+ approveDialog.row = { ...row };
+ approveOpinion.value = "";
+ approveDialog.visible = true;
+ }
+
+ function isReimburseApprovalInstance(row) {
+ return Boolean(inferReimburseModuleKeyFromInstance(row));
+ }
+
+ function resetSubmitDialogState() {
+ submitDialog.mode = "add";
+ submitDialog.step = 1;
+ selectedBusinessType.value = "";
+ submitEditRow.value = null;
+ Object.assign(submitForm, createEmptySubmitForm(""));
+ }
+
+ function openSubmitDialog() {
+ resetSubmitDialogState();
+ submitDialog.visible = true;
+ loadSubmitTemplates();
+ }
+
+ async function openEditDialog(row) {
+ if (row?.approvalStatus !== "pending") {
+ ElMessage.warning("浠呭鏍镐腑鐨勫鎵瑰彲淇敼");
+ return;
+ }
+ const moduleKey = inferReimburseModuleKeyFromInstance(row);
+ if (moduleKey) {
+ const rid = resolveFinReimbursementIdFromInstance(row);
+ if (rid == null) {
+ ElMessage.warning("鏃犳硶淇敼锛氱己灏戞姤閿�鍗� ID");
+ return;
+ }
+ try {
+ await navigateToReimburseManageForEdit(proxy?.$router, moduleKey, rid);
+ } catch {
+ ElMessage.warning("鏈壘鍒板樊鏃�/璐圭敤鎶ラ攢鑿滃崟璺敱锛岃浠庡乏渚ц彍鍗曡繘鍏ュ悗鍐嶇紪杈�");
+ }
+ return;
+ }
+ if (!row?.id) {
+ ElMessage.warning("鏃犳硶淇敼锛氱己灏戝鎵瑰疄渚� ID");
+ return;
+ }
+ submitDialog.mode = "edit";
+ submitDialog.step = 3;
+ submitEditRow.value = { ...row };
+ Object.assign(submitForm, buildEditFormFromInstanceRow(row));
+ submitDialog.visible = true;
+ }
+
+ async function onTemplatePick(card) {
+ if (!card?.id) return;
+ submitTemplatesLoading.value = true;
+ try {
+ const res = await getApprovalTemplateDetail(card.id);
+ const applied = buildTemplateBindingFromDetail(res);
+ Object.assign(submitForm, {
+ templateKey: String(card.id),
+ ...applied,
+ businessType:
+ applied.businessType ?? card.businessType ?? selectedBusinessType.value,
+ });
+ submitDialog.step = 3;
+ } catch {
+ ElMessage.error("鍔犺浇妯℃澘璇︽儏澶辫触");
+ } finally {
+ submitTemplatesLoading.value = false;
+ }
+ }
+
+ function onBusinessTypePick(type) {
+ if (!countTemplatesByBusinessType(type)) {
+ ElMessage.warning("璇ョ被鍨嬩笅鏆傛棤鍙敤瀹℃壒妯℃澘");
+ return;
+ }
+ selectedBusinessType.value = type;
+ submitDialog.step = 2;
+ }
+
+ function backToBusinessTypePick() {
+ selectedBusinessType.value = "";
+ submitDialog.step = 1;
+ }
+
+ function backToTemplatePick() {
+ submitDialog.step = 2;
+ }
+
+ async function submitInstanceForm() {
+ if (submitDialog.mode === "edit") return submitEditApproval();
+ return submitNewApproval();
+ }
+
+ async function submitNewApproval() {
+ if (!submitFormRef.value) return false;
+ try {
+ await submitFormRef.value.validate();
+ } catch {
+ return false;
+ }
+ if (!activeTemplate.value) return false;
+ const bindingCheck = validateTemplateBinding({ flowNodes: submitForm.flowNodes });
+ if (!bindingCheck.ok) {
+ ElMessage.warning(bindingCheck.message);
+ return false;
+ }
+ if (!submitForm.templateId) {
+ ElMessage.warning("缂哄皯妯℃澘 ID锛屾棤娉曟彁浜�");
+ return false;
+ }
+ if (submitSaving.value) return false;
+ submitSaving.value = true;
+ try {
+ await saveApprovalInstance(
+ buildInstanceDto({
+ submitForm,
+ activeTemplate: activeTemplate.value,
+ userStore,
+ flowNodes: bindingCheck.nodes,
+ })
+ );
+ submitDialog.visible = false;
+ page.current = 1;
+ await fetchApprovalList();
+ return true;
+ } catch {
+ return false;
+ } finally {
+ submitSaving.value = false;
+ }
+ }
+
+ async function submitEditApproval() {
+ if (!submitFormRef.value) return false;
+ try {
+ await submitFormRef.value.validate();
+ } catch {
+ return false;
+ }
+ if (!activeTemplate.value) return false;
+ const bindingCheck = validateTemplateBinding({ flowNodes: submitForm.flowNodes });
+ if (!bindingCheck.ok) {
+ ElMessage.warning(bindingCheck.message);
+ return false;
+ }
+ if (!submitForm.instanceId) {
+ ElMessage.warning("缂哄皯瀹℃壒瀹炰緥 ID锛屾棤娉曚繚瀛�");
+ return false;
+ }
+ if (submitSaving.value) return false;
+ submitSaving.value = true;
+ try {
+ await updateApprovalInstance(
+ buildInstanceDto({
+ submitForm,
+ activeTemplate: activeTemplate.value,
+ flowNodes: bindingCheck.nodes,
+ existingRow: submitEditRow.value,
+ })
+ );
+ submitDialog.visible = false;
+ await fetchApprovalList();
+ if (detailDialog.visible && detailRow.value?.id === submitForm.instanceId) {
+ const hit = tableData.value.find((r) => r.id === submitForm.instanceId);
+ if (hit) detailRow.value = { ...hit };
+ else detailDialog.visible = false;
+ }
+ return true;
+ } catch {
+ return false;
+ } finally {
+ submitSaving.value = false;
+ }
+ }
+
+ async function removeInstance(row) {
+ if (row?.id == null || row.id === "") {
+ ElMessage.warning("鏃犳硶鍒犻櫎锛氱己灏戝鎵瑰疄渚� ID");
+ return;
+ }
+ const title = row.title || row.templateName || row.instanceNo || "璇ュ鎵�";
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゅ鎵广��${title}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+ "鍒犻櫎纭",
+ {
+ type: "warning",
+ confirmButtonText: "纭畾鍒犻櫎",
+ cancelButtonText: "鍙栨秷",
+ distinguishCancelAndClose: true,
+ autofocus: false,
+ }
+ );
+ } catch {
+ return;
+ }
+ try {
+ await deleteApprovalInstance([row.id]);
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ if (detailDialog.visible && detailRow.value?.id === row.id) {
+ detailDialog.visible = false;
+ }
+ if (approveDialog.visible && approveDialog.row?.id === row.id) {
+ approveDialog.visible = false;
+ }
+ await fetchApprovalList();
+ } catch {
+ /* 閿欒鐢辨嫤鎴櫒鎻愮ず */
+ }
+ }
+
+ async function submitReimburseApprove(result) {
+ const row = reimburseDialog.instanceRow;
+ if (!row?.id) return { ok: false };
+ if (result === "rejected" && !(approveOpinion.value || "").trim()) {
+ return { needOpinion: true };
+ }
+ if (approveSubmitting.value) return { ok: false };
+ approveSubmitting.value = true;
+ try {
+ await approveApprovalInstance(
+ buildApproveInstanceDto(row, result, approveOpinion.value)
+ );
+ reimburseDialog.visible = false;
+ await fetchApprovalList();
+ return { ok: true, result };
+ } catch {
+ ElMessage.error("瀹℃壒鎿嶄綔澶辫触");
+ return { ok: false };
+ } finally {
+ approveSubmitting.value = false;
+ }
+ }
+
+ async function submitApprove(result) {
+ const row = approveDialog.row;
+ if (!row?.id) return { ok: false };
+ if (result === "rejected" && !(approveOpinion.value || "").trim()) {
+ return { needOpinion: true };
+ }
+ if (approveSubmitting.value) return { ok: false };
+ approveSubmitting.value = true;
+ try {
+ await approveApprovalInstance(
+ buildApproveInstanceDto(row, result, approveOpinion.value)
+ );
+ approveDialog.visible = false;
+ await fetchApprovalList();
+ if (detailDialog.visible && detailRow.value?.id === row.id) {
+ const hit = tableData.value.find((r) => r.id === row.id);
+ if (hit) detailRow.value = { ...hit };
+ else detailDialog.visible = false;
+ }
+ return { ok: true, result };
+ } catch {
+ ElMessage.error("瀹℃壒鎿嶄綔澶辫触");
+ return { ok: false };
+ } finally {
+ approveSubmitting.value = false;
+ }
+ }
+
+ function approvalActionLabel(result) {
+ if (result === "approved") return "閫氳繃";
+ if (result === "rejected") return "椹冲洖";
+ return "寰呭鐞�";
+ }
+
+ return {
+ Search,
+ APPROVAL_TYPE_OPTIONS,
+ APPROVAL_STATUS_SEARCH_OPTIONS,
+ searchBusinessTypeOptions,
+ loadSearchBusinessTypeOptions,
+ approvalTypeLabel,
+ approvalStatusLabel,
+ approvalStatusTagType,
+ approvalActionLabel,
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ tableColumn,
+ detailDialog,
+ detailRow,
+ reimburseDialog,
+ approveDialog,
+ approveOpinion,
+ approveSubmitting,
+ submitReimburseApprove,
+ isReimburseApprovalInstance,
+ submitDialog,
+ isSubmitEdit,
+ submitDialogTitle,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitBusinessTypeOptions,
+ submitTemplateCards,
+ selectedBusinessType,
+ selectedBusinessTypeLabel,
+ businessTypeLabel,
+ countTemplatesByBusinessType,
+ submitTemplatesLoading,
+ handleQuery,
+ resetSearch,
+ pagination,
+ resetSubmitDialogState,
+ openSubmitDialog,
+ openEditDialog,
+ onBusinessTypePick,
+ onTemplatePick,
+ backToBusinessTypePick,
+ backToTemplatePick,
+ submitInstanceForm,
+ submitNewApproval,
+ submitApprove,
+ openDetail,
+ openApprove,
+ fetchApprovalList,
+ };
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceFormConfigTable.js b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceFormConfigTable.js
new file mode 100644
index 0000000..d6bec18
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceFormConfigTable.js
@@ -0,0 +1,116 @@
+import { computed } from "vue";
+import { businessApprovalStatusLabel, businessApprovalStatusTagType, formatFieldDisplayValue, resolveInstanceFormFields } from "../approve-list/approveListConstants.js";
+import { INSTANCE_NO_SEARCH_MODULE_KEYS, INSTANCE_NO_TABLE_COLUMN } from "./approvalInstanceListSearch.js";
+
+/** 鍒楄〃/璇︽儏涓嶅洖鏄句负鐙珛鍒楃殑濉姤椤� key锛堥伩鍏嶈鐩栧疄渚嬬郴缁熷瓧娈碉級 */
+const DEFAULT_EXCLUDE_KEYS = new Set(["summary", "status", "approvalStatus", "approvalstatus", "instanceStatus", "publishStatus", "newsStatus"]);
+
+/** enrich 鍚庡繀椤讳繚鐣欑殑瀹炰緥瀛楁锛堜笉琚� formConfig 閾哄钩瑕嗙洊锛� */
+const PRESERVE_INSTANCE_FIELDS = [
+ "id",
+ "approvalStatus",
+ "statusRaw",
+ "status",
+ "instanceNo",
+ "templateId",
+ "templateName",
+ "businessType",
+ "businessId",
+ "businessName",
+ "applicantId",
+ "applicantNo",
+ "applicantName",
+ "createTime",
+ "applyTime",
+ "finishTime",
+ "title",
+ "isApprove",
+ "unread",
+ "currentLevel",
+ "newsStatus",
+ "storageBlobVOList",
+ "storageBlobDTOs",
+];
+
+/**
+ * 浠庤鏁版嵁 formConfig 瑙f瀽瀛楁瀹氫箟涓庡~鎶ュ�硷紝骞堕摵骞冲埌琛屼笂渚涗富琛� prop 缁戝畾锛堝睍绀虹敤鏍煎紡鍖栧�硷級
+ */
+export function enrichInstanceRowFromFormConfig(row, caches) {
+ const { fields, formPayload, templateSnapshot } = resolveInstanceFormFields(row);
+ const formDisplay = {};
+ const displayRow = {
+ ...row,
+ formFieldDefs: fields,
+ formPayload,
+ templateSnapshot: row.templateSnapshot || templateSnapshot,
+ formDisplay,
+ };
+
+ for (const f of fields) {
+ if (!f?.key || DEFAULT_EXCLUDE_KEYS.has(f.key)) continue;
+ const val = formPayload[f.key];
+ let text = formatFieldDisplayValue(f, val, caches);
+ if (text === String(val) && row?.applicantName && (f.label === "鐢宠浜�" || f.key === "applicant" || f.key === "applicantName")) {
+ const idMatch = String(val) === String(row.applicantId) || String(val) === String(row.applicantNo);
+ if (idMatch) text = row.applicantName;
+ }
+ formDisplay[f.key] = text;
+ displayRow[f.key] = text;
+ }
+
+ for (const key of PRESERVE_INSTANCE_FIELDS) {
+ if (row[key] !== undefined) displayRow[key] = row[key];
+ }
+
+ return displayRow;
+}
+
+/**
+ * 浠庡垪琛ㄩ琛� formConfig 鐢熸垚涓昏〃鍔ㄦ�佸垪锛坙abel 鍙栬嚜妯℃澘瀛楁 label锛�
+ */
+export function getFormConfigFieldColumns(firstRow, { excludeKeys = DEFAULT_EXCLUDE_KEYS } = {}) {
+ const fields = (firstRow?.formFieldDefs || []).filter(f => f?.key && !excludeKeys.has(f.key));
+ return fields.map(f => ({
+ label: f.label || f.key,
+ prop: f.key,
+ minWidth: f.type === "textarea" ? 200 : f.type === "datetimerange" ? 160 : 120,
+ showOverflowTooltip: true,
+ }));
+}
+
+/**
+ * 涓氬姟鐢宠涓昏〃鍒楋細鍥哄畾鍒� + formConfig 鍔ㄦ�佸垪 + 瀹℃壒鐘舵�� + 鎿嶄綔
+ */
+export function buildInstanceTableColumns(tableDataRef, buildTableActions, options = {}) {
+ const { moduleKey, excludeKeys = DEFAULT_EXCLUDE_KEYS, beforeFormColumns = [], extraColumns = [], afterFormColumns = [], actionWidth = 260 } = options;
+
+ const leadingCols = moduleKey && INSTANCE_NO_SEARCH_MODULE_KEYS.has(moduleKey) ? [INSTANCE_NO_TABLE_COLUMN] : [];
+
+ return computed(() => {
+ const formCols = getFormConfigFieldColumns(tableDataRef.value?.[0], { excludeKeys });
+ return [
+ ...leadingCols,
+ ...beforeFormColumns,
+ ...formCols,
+ ...extraColumns,
+ ...afterFormColumns,
+ { label: "鍒涘缓鏃堕棿", prop: "createTime", width: 170 },
+ {
+ label: "瀹℃壒鐘舵��",
+ prop: "approvalStatus",
+ width: 110,
+ dataType: "tag",
+ formatData: v => businessApprovalStatusLabel(v),
+ formatType: v => businessApprovalStatusTagType(v),
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: actionWidth,
+ operation: buildTableActions(),
+ },
+ ];
+ });
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceListSearch.js b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceListSearch.js
new file mode 100644
index 0000000..80dda5c
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceListSearch.js
@@ -0,0 +1,158 @@
+import dayjs from "dayjs";
+import { APPROVAL_MODULE_KEYS } from "./approvalModuleRegistry.js";
+
+/** 鏀寔瀹℃壒鍗曞彿鏌ヨ/涓昏〃灞曠ず鐨勫鎵圭敵璇锋ā鍧� */
+export const INSTANCE_NO_SEARCH_MODULE_KEYS = new Set([
+ APPROVAL_MODULE_KEYS.REGULAR,
+ APPROVAL_MODULE_KEYS.TRANSFER,
+ APPROVAL_MODULE_KEYS.WORK_HANDOVER,
+ APPROVAL_MODULE_KEYS.LEAVE,
+ APPROVAL_MODULE_KEYS.OVERTIME,
+]);
+
+export const INSTANCE_NO_TABLE_COLUMN = {
+ label: "瀹℃壒鍗曞彿",
+ prop: "instanceNo",
+ width: 170,
+ showOverflowTooltip: true,
+};
+
+/** 鎵佸钩鍖栦负 Spring GET 鍙粦瀹氱殑 query锛坅pprovalInstanceDto.xxx锛屽嬁鐢ㄦ柟鎷彿锛� */
+export function appendDotNotationQuery(target, prefix, fields) {
+ if (!fields || typeof fields !== "object") return;
+ for (const [key, value] of Object.entries(fields)) {
+ if (value == null || value === "") continue;
+ target[`${prefix}.${key}`] = value;
+ }
+}
+
+function pickApplicantFromSearchForm(searchForm = {}) {
+ const out = {};
+ const sf = searchForm || {};
+ const name = (sf.applicantName || "").trim();
+ const kw = (sf.applicantKeyword || "").trim();
+ const id = sf.applicantId;
+
+ if (name) out.applicantName = name;
+ if (kw) {
+ out.applicantName = kw;
+ if (/^\d+$/.test(kw)) out.applicantId = Number(kw);
+ }
+ if (id != null && id !== "") {
+ out.applicantId = typeof id === "number" ? id : Number(id) || id;
+ }
+ return out;
+}
+
+function pickInstanceNoFromSearchForm(searchForm = {}) {
+ const no = (searchForm?.instanceNo || "").trim();
+ return no ? { instanceNo: no } : {};
+}
+
+/** 缁勮 approvalInstanceDto 鏌ヨ鐗囨锛堢敵璇蜂汉 + 瀹℃壒鍗曞彿 + 鐘舵�� + 鏃堕棿鑼冨洿锛� */
+export function buildApprovalInstanceSearchDto(searchForm = {}, extraParams = {}) {
+ const dto = {
+ ...(extraParams && typeof extraParams === "object" ? extraParams : {}),
+ };
+ Object.assign(dto, pickApplicantFromSearchForm(searchForm));
+ Object.assign(dto, pickInstanceNoFromSearchForm(searchForm));
+
+ // 瀹℃壒鐘舵��
+ if (searchForm?.status) {
+ dto.status = searchForm.status;
+ }
+
+ // 鍒涘缓鏃堕棿鑼冨洿
+ const range = searchForm?.createTimeRange;
+ if (Array.isArray(range) && range[0]) {
+ dto.createTimeStart = range[0] + (range[0].includes(":") ? "" : " 00:00:00");
+ }
+ if (Array.isArray(range) && range[1]) {
+ dto.createTimeEnd = range[1] + (range[1].includes(":") ? "" : " 23:59:59");
+ }
+
+ delete dto.createTime;
+ return dto;
+}
+
+function getRowPayloadValue(row, keys) {
+ const keyList = Array.isArray(keys) ? keys : [keys];
+ const payload = row?.formPayload || {};
+ for (const k of keyList) {
+ if (row?.[k] != null && row[k] !== "") return row[k];
+ if (payload[k] != null && payload[k] !== "") return payload[k];
+ }
+ return "";
+}
+
+function matchApplicantKeyword(row, keyword) {
+ const kw = (keyword || "").trim().toLowerCase();
+ if (!kw) return true;
+ const parts = [row?.applicantName, row?.applicantNo, row?.applicantId, getRowPayloadValue(row, ["applicant", "applicantName", "applicantId"])]
+ .filter(v => v != null && v !== "")
+ .map(v => String(v).toLowerCase());
+ return parts.some(p => p.includes(kw));
+}
+
+function matchApplicantId(row, applicantId) {
+ if (applicantId == null || applicantId === "") return true;
+ const id = String(applicantId);
+ if (row?.applicantId != null && String(row.applicantId) === id) return true;
+ const payloadApplicant = getRowPayloadValue(row, ["applicant", "applicantId", "applicantUserId"]);
+ return String(payloadApplicant) === id;
+}
+
+function matchSelectValue(row, keys, expected) {
+ if (!expected) return true;
+ const raw = getRowPayloadValue(row, keys);
+ return String(raw) === String(expected);
+}
+
+function matchInstanceNo(row, instanceNo) {
+ const kw = (instanceNo || "").trim().toLowerCase();
+ if (!kw) return true;
+ const parts = [row?.instanceNo, row?.bizId].filter(v => v != null && v !== "").map(v => String(v).toLowerCase());
+ return parts.some(p => p.includes(kw));
+}
+
+/** 鏄惁瀛樺湪鍒楄〃绛涢�夋潯浠讹紙鐢宠浜� / 瀹℃壒鍗曞彿 / 鐘舵�� / 鏃堕棿鑼冨洿锛� */
+export function hasActiveModuleSearch(moduleKey, searchForm = {}) {
+ const sf = searchForm || {};
+ if ((sf.instanceNo || "").trim()) return true;
+ if ((sf.applicantKeyword || "").trim()) return true;
+ if ((sf.applicantName || "").trim()) return true;
+ if (sf.applicantId != null && sf.applicantId !== "") return true;
+ if (sf.status) return true;
+ if (Array.isArray(sf.createTimeRange) && sf.createTimeRange.length === 2) return true;
+ return false;
+}
+
+/** 鎸夌敵璇蜂汉銆佸鎵瑰崟鍙枫�佺姸鎬併�佹椂闂磋寖鍥村仛鍓嶇鍏滃簳绛涢�� */
+export function filterInstanceRowsByModuleSearch(moduleKey, rows, searchForm = {}) {
+ const sf = searchForm || {};
+ const list = Array.isArray(rows) ? rows : [];
+ if (!hasActiveModuleSearch(moduleKey, sf)) return list;
+
+ return list.filter(row => {
+ // 瀹℃壒鍗曞彿
+ if (!matchInstanceNo(row, sf.instanceNo)) return false;
+ // 鐢宠浜�
+ if (!matchApplicantId(row, sf.applicantId)) return false;
+ if (!matchApplicantKeyword(row, sf.applicantKeyword || sf.applicantName)) return false;
+ // 鐘舵��
+ if (sf.status && String(row.statusRaw || row.status).toUpperCase() !== String(sf.status).toUpperCase()) {
+ return false;
+ }
+ // 鏃堕棿鑼冨洿
+ if (Array.isArray(sf.createTimeRange) && sf.createTimeRange.length === 2) {
+ const rowTime = row.createTime || row.applyTime;
+ if (rowTime) {
+ const t = dayjs(rowTime);
+ const start = dayjs(sf.createTimeRange[0] + " 00:00:00");
+ const end = dayjs(sf.createTimeRange[1] + " 23:59:59");
+ if (t.isBefore(start) || t.isAfter(end)) return false;
+ }
+ }
+ return true;
+ });
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalModuleRegistry.js b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalModuleRegistry.js
new file mode 100644
index 0000000..fd56eca
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalModuleRegistry.js
@@ -0,0 +1,152 @@
+/**
+ * 鍚勪笟鍔℃ā鍧椾笌瀹℃壒妯℃澘绫诲瀷鐨勬槧灏勶紙閰嶇疆鍖栧叆鍙o級
+ * businessType 涓庡悗绔� TypeEnums / listPage 绾﹀畾涓�鑷达紙鍐欐鏋氫妇鍊硷級
+ */
+export const APPROVAL_MODULE_KEYS = {
+ REGULAR: "regular",
+ TRANSFER: "transfer",
+ RESIGN: "resign",
+ WORK_HANDOVER: "work_handover",
+ LEAVE: "leave",
+ OVERTIME: "overtime",
+ TRAVEL_REIMBURSE: "travel_reimburse",
+ COST_REIMBURSE: "cost_reimburse",
+ ENTERPRISE_NEWS: "enterprise_news",
+};
+
+/** 瀹℃壒瀹炰緥 listPage / 淇濆瓨 浣跨敤鐨� businessType 鏋氫妇 */
+export const APPROVAL_BUSINESS_TYPE = {
+ [APPROVAL_MODULE_KEYS.REGULAR]: 10,
+ [APPROVAL_MODULE_KEYS.TRANSFER]: 11,
+ [APPROVAL_MODULE_KEYS.WORK_HANDOVER]: 13,
+ [APPROVAL_MODULE_KEYS.LEAVE]: 14,
+ [APPROVAL_MODULE_KEYS.OVERTIME]: 15,
+ [APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE]: 16,
+ [APPROVAL_MODULE_KEYS.COST_REIMBURSE]: 17,
+ [APPROVAL_MODULE_KEYS.ENTERPRISE_NEWS]: 18,
+};
+
+/** @type {Record<string, import('./approvalModuleRegistry.js').ApprovalModuleConfig>} */
+export const APPROVAL_MODULE_REGISTRY = {
+ [APPROVAL_MODULE_KEYS.REGULAR]: {
+ label: "杞鐢宠",
+ approvalType: "regular",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.REGULAR],
+ typeLabels: ["杞", "杞鐢宠"],
+ },
+ [APPROVAL_MODULE_KEYS.TRANSFER]: {
+ label: "璋冨矖鐢宠",
+ approvalType: "transfer",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.TRANSFER],
+ typeLabels: ["璋冨矖", "璋冨姩", "璋冨矖鐢宠", "璋冨姩鐢宠"],
+ },
+ [APPROVAL_MODULE_KEYS.RESIGN]: {
+ label: "绂昏亴鐢宠",
+ approvalType: "resign",
+ typeLabels: ["绂昏亴", "绂昏亴鐢宠", "绂昏亴瀹℃壒"],
+ },
+ [APPROVAL_MODULE_KEYS.WORK_HANDOVER]: {
+ label: "宸ヤ綔浜ゆ帴",
+ approvalType: "work_handover",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.WORK_HANDOVER],
+ typeLabels: ["宸ヤ綔浜ゆ帴", "浜ゆ帴", "宸ヤ綔浜ゆ帴瀹℃壒"],
+ },
+ [APPROVAL_MODULE_KEYS.LEAVE]: {
+ label: "璇峰亣鐢宠",
+ approvalType: "leave",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.LEAVE],
+ typeLabels: ["璇峰亣", "璇峰亣鐢宠", "璇峰亣瀹℃壒"],
+ },
+ [APPROVAL_MODULE_KEYS.OVERTIME]: {
+ label: "鍔犵彮鐢宠",
+ approvalType: "overtime",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.OVERTIME],
+ typeLabels: ["鍔犵彮", "鍔犵彮鐢宠", "鍔犵彮瀹℃壒"],
+ },
+ [APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE]: {
+ label: "宸梾鎶ラ攢",
+ approvalType: "travel_reimburse",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE],
+ typeLabels: ["宸梾", "宸梾鎶ラ攢", "鍑哄樊鎶ラ攢"],
+ },
+ [APPROVAL_MODULE_KEYS.COST_REIMBURSE]: {
+ label: "璐圭敤鎶ラ攢",
+ approvalType: "cost_reimburse",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.COST_REIMBURSE],
+ typeLabels: ["璐圭敤", "璐圭敤鎶ラ攢"],
+ },
+ [APPROVAL_MODULE_KEYS.ENTERPRISE_NEWS]: {
+ label: "浼佷笟鏂伴椈",
+ approvalType: "enterprise_news",
+ businessType: APPROVAL_BUSINESS_TYPE[APPROVAL_MODULE_KEYS.ENTERPRISE_NEWS],
+ typeLabels: ["浼佷笟鏂伴椈", "鏂伴椈", "鏂伴椈鍙戝竷"],
+ },
+};
+
+/**
+ * @typedef {object} ApprovalModuleConfig
+ * @property {string} label
+ * @property {string} [approvalType]
+ * @property {string|number} [businessType]
+ * @property {string[]} [typeLabels]
+ */
+
+export function getApprovalModuleConfig(moduleKey) {
+ if (!moduleKey) return null;
+ return APPROVAL_MODULE_REGISTRY[moduleKey] || null;
+}
+
+/** 鍒楄〃鏌ヨ businessType锛堜紭鍏堥厤缃灇涓撅紝涓嶅啀鍥為�� approvalType 瀛楃涓诧級 */
+export function getModuleListBusinessType(moduleKey) {
+ const cfg = getApprovalModuleConfig(moduleKey);
+ if (!cfg) return "";
+ if (cfg.businessType != null && cfg.businessType !== "") return cfg.businessType;
+ return APPROVAL_BUSINESS_TYPE[moduleKey] ?? "";
+}
+
+/** 浠� TypeEnums 瑙f瀽鏈ā鍧� businessType锛涘凡閰嶇疆鏋氫妇鏃剁洿鎺ヨ繑鍥� */
+export function resolveModuleBusinessType(moduleKey, typeOptions = []) {
+ const cfg = getApprovalModuleConfig(moduleKey);
+ if (!cfg) return null;
+
+ const fixed = getModuleListBusinessType(moduleKey);
+ if (fixed != null && fixed !== "") return fixed;
+
+ const labels = [cfg.label, ...(cfg.typeLabels || [])].filter(Boolean);
+ const hitByLabel = (typeOptions || []).find((opt) => {
+ const optLabel = String(opt?.label || opt?.name || "").trim();
+ if (!optLabel) return false;
+ return labels.some(
+ (l) => optLabel === l || optLabel.includes(l) || l.includes(optLabel)
+ );
+ });
+ if (hitByLabel?.value != null && hitByLabel.value !== "") return hitByLabel.value;
+
+ return cfg.approvalType || null;
+}
+
+/** 鍒楄〃/妯℃澘杩囨护鐢ㄧ殑 businessType 闆嗗悎 */
+export function getModuleMatchingBusinessTypes(moduleKey, typeOptions = []) {
+ const cfg = getApprovalModuleConfig(moduleKey);
+ if (!cfg) return [];
+
+ const fixed = getModuleListBusinessType(moduleKey);
+ if (fixed != null && fixed !== "") return [fixed];
+
+ const values = new Set();
+ const primary = resolveModuleBusinessType(moduleKey, typeOptions);
+ if (primary != null && primary !== "") values.add(primary);
+
+ const labels = [cfg.label, ...(cfg.typeLabels || [])].filter(Boolean);
+ for (const opt of typeOptions || []) {
+ const optLabel = String(opt?.label || opt?.name || "").trim();
+ if (!optLabel) continue;
+ const matched = labels.some(
+ (l) => optLabel === l || optLabel.includes(l) || l.includes(optLabel)
+ );
+ if (matched && opt.value != null && opt.value !== "") {
+ values.add(opt.value);
+ }
+ }
+ return [...values];
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalTemplateBindingUtils.js b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalTemplateBindingUtils.js
new file mode 100644
index 0000000..d68016f
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalTemplateBindingUtils.js
@@ -0,0 +1,91 @@
+import {
+ mapAttachmentsFromApi,
+ mapTemplateFromApi,
+ unwrapTemplateDetail,
+} from "../approve-template/approveTemplateConstants.js";
+import { buildSubmitTemplateFromRow } from "../approve-template/formConfigUtils.js";
+import {
+ createEmptySubmitForm,
+ validateSubmitFlowNodes,
+} from "../approve-list/approveListConstants.js";
+
+export function attachmentDisplayName(file) {
+ return (
+ file?.fileName ||
+ file?.originalFilename ||
+ file?.name ||
+ file?.blobName ||
+ "闄勪欢"
+ );
+}
+
+/** 鎺ュ彛璇︽儏 鈫� 鎻愪氦缁戝畾蹇収锛堝惈娴佺▼銆侀檮浠躲�佸~鎶ラ」锛� */
+export function buildTemplateBindingFromDetail(detailRow) {
+ const mapped = mapTemplateFromApi(unwrapTemplateDetail(detailRow));
+ const templateAttachments = mapAttachmentsFromApi(mapped);
+ const tpl = {
+ ...buildSubmitTemplateFromRow(mapped),
+ templateId: mapped.id,
+ businessType: mapped.businessType,
+ storageBlobDTOs: templateAttachments,
+ };
+ const base = createEmptySubmitForm(String(mapped.id ?? ""), tpl, mapped.flowNodes);
+ return {
+ templateId: mapped.id,
+ templateName: mapped.templateName || tpl.label || "",
+ businessType: mapped.businessType ?? "",
+ templateSnapshot: tpl,
+ formFieldDefs: tpl.fields || [],
+ formPayload: base.formPayload,
+ flowNodes: base.flowNodes,
+ templateAttachments: JSON.parse(JSON.stringify(templateAttachments)),
+ storageBlobDTOs: [],
+ };
+}
+
+/** 鏍规嵁妯℃澘 fields 鐢熸垚 el-form rules锛坧rop 涓� formPayload.xxx锛� */
+export function buildFormPayloadRules(fields = []) {
+ const rules = {};
+ (fields || []).forEach((f) => {
+ if (!f.required || !f.key) return;
+ const prop = `formPayload.${f.key}`;
+ if (f.type === "number") {
+ rules[prop] = [{ required: true, message: `璇峰~鍐�${f.label}`, trigger: "blur" }];
+ } else if (f.type === "datetimerange" || f.type === "date" || f.type === "select") {
+ rules[prop] = [{ required: true, message: `璇烽�夋嫨${f.label}`, trigger: "change" }];
+ } else {
+ rules[prop] = [{ required: true, message: `璇峰~鍐�${f.label}`, trigger: "blur" }];
+ }
+ });
+ return rules;
+}
+
+/** 鏍¢獙妯℃澘缁戝畾锛氬鎵规祦绋嬶紙闄勪欢閫夊~锛岀敱鐢ㄦ埛鑷涓婁紶锛� */
+export function validateTemplateBinding({ flowNodes }) {
+ const flowCheck = validateSubmitFlowNodes(flowNodes);
+ if (!flowCheck.ok) return flowCheck;
+ return { ok: true, nodes: flowCheck.nodes };
+}
+
+/** 鍚堝苟缁戝畾缁撴灉鍒颁笟鍔¤〃鍗曞璞★紙瀛楁鍚嶅彲鎸変笟鍔¤鐩栵級 */
+export function applyBindingToForm(target, binding, fieldMap = {}) {
+ if (!target || !binding) return target;
+ const map = {
+ templateId: "templateId",
+ templateName: "templateName",
+ businessType: "businessType",
+ templateSnapshot: "templateSnapshot",
+ formFieldDefs: "formFieldDefs",
+ formPayload: "formPayload",
+ flowNodes: "flowNodes",
+ templateAttachments: "templateAttachments",
+ storageBlobDTOs: "storageBlobDTOs",
+ ...fieldMap,
+ };
+ Object.entries(map).forEach(([srcKey, destKey]) => {
+ if (binding[srcKey] !== undefined) {
+ target[destKey] = binding[srcKey];
+ }
+ });
+ return target;
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue
new file mode 100644
index 0000000..2488216
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue
@@ -0,0 +1,123 @@
+<!-- 涓庡鎵瑰垪琛ㄨ鎯呭脊绐椾竴鑷� -->
+<template>
+ <el-dialog
+ v-model="visible"
+ :title="title"
+ width="920px"
+ append-to-body
+ destroy-on-close
+ class="approve-detail-dialog"
+ @closed="emit('closed')"
+ >
+ <div class="approve-detail-body">
+ <ApproveDetailPanel :row="row" />
+ <div class="detail-block">
+ <div class="detail-block-title">
+ 瀹℃壒娴佺▼锛坽{ row?.tasks?.length || row?.flowNodes?.length || 0 }} 椤癸級
+ </div>
+ <InstanceFlowDisplay :tasks="row?.tasks" :nodes="row?.flowNodes" />
+ </div>
+ <div class="detail-block">
+ <div class="detail-block-title">瀹℃壒璁板綍</div>
+ <el-timeline v-if="row?.approvalRecords?.length" class="approve-record-timeline">
+ <el-timeline-item
+ v-for="(rec, i) in row.approvalRecords"
+ :key="rec.id ?? i"
+ :type="rec.result === 'approved' ? 'success' : rec.result === 'rejected' ? 'danger' : 'primary'"
+ :timestamp="formatRecordTime(rec.time)"
+ placement="top"
+ >
+ <div class="record-item">
+ <span class="record-operator">{{ rec.operatorName || "鈥�" }}</span>
+ <el-tag
+ size="small"
+ :type="rec.result === 'approved' ? 'success' : rec.result === 'rejected' ? 'danger' : 'info'"
+ effect="plain"
+ >
+ {{ approvalActionLabel(rec.result) }}
+ </el-tag>
+ <p class="record-opinion">{{ rec.opinion || "鏃犳剰瑙�" }}</p>
+ </div>
+ </el-timeline-item>
+ </el-timeline>
+ <el-empty v-else description="鏆傛棤瀹℃壒璁板綍" :image-size="48" />
+ </div>
+ </div>
+ <template #footer>
+ <el-button v-if="canEditRow(row)" @click="emit('edit', row)">淇� 鏀�</el-button>
+ <el-button @click="visible = false">鍏� 闂�</el-button>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { computed } from "vue";
+import { canEditBusinessInstanceRow } from "../../approve-list/approveListConstants.js";
+import { formatDisplayTime } from "../../approve-template/approveTemplateConstants.js";
+import ApproveDetailPanel from "../../approve-list/components/ApproveDetailPanel.vue";
+import InstanceFlowDisplay from "../../approve-list/components/InstanceFlowDisplay.vue";
+
+function canEditRow(row) {
+ return canEditBusinessInstanceRow(row);
+}
+
+const props = defineProps({
+ modelValue: { type: Boolean, default: false },
+ row: { type: Object, default: () => ({}) },
+ title: { type: String, default: "瀹℃壒璇︽儏" },
+});
+
+const emit = defineEmits(["update:modelValue", "edit", "closed"]);
+
+const visible = computed({
+ get: () => props.modelValue,
+ set: (v) => emit("update:modelValue", v),
+});
+
+function approvalActionLabel(result) {
+ if (result === "approved") return "閫氳繃";
+ if (result === "rejected") return "椹冲洖";
+ return "寰呭鐞�";
+}
+
+function formatRecordTime(time) {
+ return formatDisplayTime(time) || "鈥�";
+}
+</script>
+
+<style scoped>
+.approve-detail-dialog :deep(.el-dialog__body) {
+ padding-top: 16px;
+ max-height: 70vh;
+ overflow-y: auto;
+}
+.approve-detail-body .detail-block {
+ margin-top: 20px;
+}
+.detail-block-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+ margin: 0 0 12px;
+ padding-left: 10px;
+ border-left: 3px solid var(--el-color-primary);
+ line-height: 1.4;
+}
+.approve-record-timeline {
+ padding-left: 4px;
+}
+.record-item {
+ padding: 4px 0 2px;
+}
+.record-operator {
+ font-weight: 600;
+ margin-right: 8px;
+ color: var(--el-text-color-primary);
+}
+.record-opinion {
+ margin: 8px 0 0;
+ font-size: 13px;
+ color: var(--el-text-color-regular);
+ line-height: 1.5;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue
new file mode 100644
index 0000000..53de9e1
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue
@@ -0,0 +1,112 @@
+<!-- 涓庡鎵瑰垪琛ㄦ彁浜�/淇敼寮圭獥锛堢涓夋锛変竴鑷� -->
+<template>
+ <el-dialog
+ v-model="visible"
+ :title="title"
+ width="720px"
+ append-to-body
+ destroy-on-close
+ class="approve-submit-dialog"
+ @closed="emit('closed')"
+ >
+ <el-form ref="innerFormRef" :model="form" :rules="rules" label-width="120px">
+ <el-form-item v-if="isEdit" label="瀹℃壒绫诲瀷">
+ <span class="approve-type-cell" :style="approvalTypeStyle(activeTemplate?.approvalType)">
+ {{ activeTemplate?.label || form.templateName || "鈥�" }}
+ </span>
+ </el-form-item>
+ <slot name="before" :form="form" :fields="fields" />
+ <ApprovalTemplateFormSection
+ :active-template="activeTemplate"
+ :fields="fields"
+ :form-payload="form.formPayload"
+ v-model:flow-nodes="form.flowNodes"
+ v-model:attachments="form.storageBlobDTOs"
+ :template-attachments="form.templateAttachments"
+ :user-options="userOptions"
+ :show-template-name="!isEdit"
+ :allow-change-template="false"
+ :flow-attachments-only="flowAttachmentsOnly"
+ :flow-only="flowOnly"
+ />
+ <slot name="after" :form="form" :fields="fields" />
+ </el-form>
+ <template #footer>
+ <el-button type="primary" :loading="saving" @click="handleSubmitClick">
+ {{ isEdit ? "淇� 瀛�" : "鎻� 浜�" }}
+ </el-button>
+ <el-button @click="visible = false">鍙� 娑�</el-button>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { computed, ref, watch } from "vue";
+import { ElMessage } from "element-plus";
+import { approvalTypeStyle } from "../../approve-list/approveListConstants.js";
+import ApprovalTemplateFormSection from "./ApprovalTemplateFormSection.vue";
+
+const innerFormRef = ref(null);
+
+const props = defineProps({
+ modelValue: { type: Boolean, default: false },
+ title: { type: String, default: "" },
+ form: { type: Object, required: true },
+ rules: { type: Object, default: () => ({}) },
+ fields: { type: Array, default: () => [] },
+ activeTemplate: { type: Object, default: null },
+ userOptions: { type: Array, default: () => [] },
+ isEdit: { type: Boolean, default: false },
+ saving: { type: Boolean, default: false },
+ formRef: { type: Object, default: null },
+ /** 濉姤椤圭敱 before 鎻掓Ы鍗曠嫭娓叉煋鏃惰涓� true */
+ flowAttachmentsOnly: { type: Boolean, default: false },
+ flowOnly: { type: Boolean, default: false },
+});
+
+const emit = defineEmits(["update:modelValue", "submit", "closed"]);
+
+const visible = computed({
+ get: () => props.modelValue,
+ set: (v) => emit("update:modelValue", v),
+});
+
+watch(
+ innerFormRef,
+ (el) => {
+ if (props.formRef) props.formRef.value = el;
+ },
+ { flush: "post" }
+);
+
+watch(visible, (v) => {
+ if (!v && props.formRef) props.formRef.value = null;
+});
+
+async function handleSubmitClick() {
+ if (!innerFormRef.value) {
+ ElMessage.warning("琛ㄥ崟鏈氨缁紝璇风◢鍚庡啀璇�");
+ return;
+ }
+ try {
+ await innerFormRef.value.validate();
+ } catch {
+ ElMessage.warning("璇峰畬鍠勮〃鍗曞繀濉」鍚庡啀淇濆瓨");
+ return;
+ }
+ emit("submit");
+}
+</script>
+
+<style scoped>
+.approve-type-cell {
+ display: inline-block;
+ padding: 2px 10px;
+ border-radius: 4px;
+ font-size: 13px;
+ line-height: 1.5;
+}
+.approve-submit-dialog :deep(.el-dialog__body) {
+ padding-top: 12px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue
new file mode 100644
index 0000000..409dd41
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue
@@ -0,0 +1,176 @@
+<!--
+ 涓氬姟妯″潡銆屾柊澧炪�嶆椂瀵煎叆瀹℃壒妯℃澘锛堝浐瀹� moduleKey锛屼粎灞曠ず璇ョ被鍨嬩笅妯℃澘锛�
+
+ 鐢ㄦ硶锛�
+ <ApprovalTemplateBindDialog
+ v-model:visible="visible"
+ module-key="regular"
+ @confirm="onTemplateBound"
+ />
+-->
+<template>
+ <el-dialog
+ v-model="dialogVisible"
+ :title="dialogTitle"
+ :width="step === formStep ? 720 : 640"
+ append-to-body
+ class="approval-template-bind-dialog"
+ @closed="onClosed"
+ >
+ <template v-if="step === 1">
+ <div v-loading="templatesLoading || confirming">
+ <ApprovalTemplatePicker
+ :cards="templateCards"
+ :loading="false"
+ :hint="pickerHint"
+ @pick="onPickTemplate"
+ />
+ </div>
+ </template>
+
+ <template v-else>
+ <div v-loading="templatesLoading">
+ <el-form
+ ref="formRef"
+ :model="bindingForm"
+ :rules="mergedRules"
+ label-width="120px"
+ >
+ <ApprovalTemplateFormSection
+ :active-template="activeTemplate"
+ :fields="formFields"
+ :form-payload="bindingForm.formPayload"
+ v-model:flow-nodes="bindingForm.flowNodes"
+ v-model:attachments="bindingForm.storageBlobDTOs"
+ :template-attachments="bindingForm.templateAttachments"
+ :user-options="flowUserOptions"
+ allow-change-template
+ @change-template="step = 1"
+ />
+ </el-form>
+ </div>
+ </template>
+
+ <template #footer>
+ <el-button v-if="step === formStep" type="primary" :loading="confirming" @click="onConfirm">
+ 纭� 瀹�
+ </el-button>
+ <el-button v-if="step === formStep" @click="step = 1">閲嶉�夋ā鏉�</el-button>
+ <el-button @click="dialogVisible = false">{{ step === 1 ? "鍙� 娑�" : "鍏� 闂�" }}</el-button>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { computed, ref, watch } from "vue";
+import { ElMessage } from "element-plus";
+import ApprovalTemplatePicker from "./ApprovalTemplatePicker.vue";
+import ApprovalTemplateFormSection from "./ApprovalTemplateFormSection.vue";
+import { useApprovalTemplateBinding } from "../useApprovalTemplateBinding.js";
+import { useFlowUserOptions } from "../useFlowUserOptions.js";
+import { getApprovalModuleConfig } from "../approvalModuleRegistry.js";
+
+const props = defineProps({
+ visible: { type: Boolean, default: false },
+ /** approvalModuleRegistry 涓殑 moduleKey */
+ moduleKey: { type: String, required: true },
+ /** 涓� true 鏃堕�夋ā鏉垮悗鐩存帴纭锛岃烦杩囥�岀‘璁ゅ鎵逛俊鎭�嶅~鎶ユ楠� */
+ skipFormConfirm: { type: Boolean, default: false },
+});
+
+const emit = defineEmits(["update:visible", "confirm", "closed"]);
+
+const dialogVisible = computed({
+ get: () => props.visible,
+ set: (v) => emit("update:visible", v),
+});
+
+const {
+ step,
+ bindingForm,
+ templateCards,
+ activeTemplate,
+ formFields,
+ formRules,
+ templatesLoading,
+ loadTemplates,
+ resetBinding,
+ pickTemplate,
+ validateBinding,
+ getBindingPayload,
+ moduleConfig,
+} = useApprovalTemplateBinding({ moduleKey: props.moduleKey, mode: "module" });
+
+const formStep = 2;
+const formRef = ref();
+const confirming = ref(false);
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+const mergedRules = computed(() => ({ ...formRules.value }));
+
+const dialogTitle = computed(() => {
+ const label = moduleConfig.value?.label || "瀹℃壒";
+ return step.value === 1 ? `閫夋嫨${label}妯℃澘` : `纭${label}瀹℃壒淇℃伅`;
+});
+
+const pickerHint = computed(
+ () => `璇烽�夋嫨銆�${moduleConfig.value?.label || "鈥�"}銆嶇被鍨嬩笅宸插惎鐢ㄧ殑瀹℃壒妯℃澘锛屽鎵规祦绋嬪皢鑷姩甯﹀叆銆俙
+);
+
+watch(
+ () => props.visible,
+ async (v) => {
+ if (!v) return;
+ resetBinding();
+ step.value = 1;
+ await Promise.all([loadTemplates(), loadFlowUsers()]);
+ const cfg = getApprovalModuleConfig(props.moduleKey);
+ if (!cfg) {
+ ElMessage.warning(`鏈厤缃ā鍧椼��${props.moduleKey}銆嶏紝璇锋鏌� approvalModuleRegistry`);
+ return;
+ }
+ if (!templateCards.value.length) {
+ ElMessage.warning(
+ `銆�${cfg.label}銆嶄笅鏆傛棤宸插惎鐢ㄧ殑瀹℃壒妯℃澘锛岃鍏堝湪瀹℃壒妯℃澘绠$悊涓垱寤哄苟鍚敤瀵瑰簲绫诲瀷鐨勬ā鏉縛
+ );
+ }
+ }
+);
+
+async function onPickTemplate(card) {
+ const ok = await pickTemplate(card);
+ if (!ok) return;
+ if (props.skipFormConfirm) {
+ step.value = 1;
+ await onConfirm();
+ return;
+ }
+ step.value = formStep;
+}
+
+async function onConfirm() {
+ confirming.value = true;
+ try {
+ const check = await validateBinding(props.skipFormConfirm ? null : formRef.value);
+ if (!check.ok) {
+ if (check.message) ElMessage.warning(check.message);
+ return;
+ }
+ emit("confirm", { ...getBindingPayload(), flowNodes: check.nodes });
+ dialogVisible.value = false;
+ } finally {
+ confirming.value = false;
+ }
+}
+
+function onClosed() {
+ resetBinding();
+ emit("closed");
+}
+</script>
+
+<style scoped>
+.approval-template-bind-dialog :deep(.el-dialog__body) {
+ padding-top: 12px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateFormSection.vue b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateFormSection.vue
new file mode 100644
index 0000000..d6e7073
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplateFormSection.vue
@@ -0,0 +1,122 @@
+<!-- 妯℃澘缁戝畾琛ㄥ崟鍖猴細濉姤椤� + 瀹℃壒娴佺▼ + 闄勪欢锛堥』鎸傚湪澶栧眰 el-form 涓嬶級 -->
+<template>
+ <template v-if="activeTemplate">
+ <el-form-item
+ v-if="showTemplateName && !hideTemplateName && !flowAttachmentsOnly && !flowOnly"
+ label="瀹℃壒妯℃澘"
+ >
+ <span class="template-name">{{ activeTemplate.label }}</span>
+ <el-button v-if="allowChangeTemplate" type="primary" link class="ml12" @click="emit('change-template')">
+ 鏇存崲妯℃澘
+ </el-button>
+ </el-form-item>
+
+ <FormPayloadFields
+ v-if="!hideFormFields && !flowAttachmentsOnly && !flowOnly"
+ :fields="fields"
+ :form-payload="formPayload"
+ />
+
+ <el-form-item label="瀹℃壒娴佺▼" required>
+ <TemplateFlowEditor
+ v-model="flowNodesModel"
+ :user-options="userOptions"
+ :readonly="!flowEditable"
+ />
+ <p class="section-tip">
+ {{
+ flowEditable
+ ? "娴佺▼涓庡鎵逛汉鐢辨ā鏉块缃紝鍙寜闇�寰皟鑺傜偣瀹℃壒浜恒��"
+ : "娴佺▼涓庡鎵逛汉鐢辨墍閫夋ā鏉垮浐瀹氾紝涓嶅彲淇敼銆�"
+ }}
+ </p>
+ </el-form-item>
+
+ <el-form-item v-if="!flowOnly && templateAttachments.length" label="妯℃澘鍙傝��">
+ <el-tag
+ v-for="(f, i) in templateAttachments"
+ :key="`tpl-${i}`"
+ class="attachment-tag"
+ type="info"
+ effect="plain"
+ >
+ {{ attachmentDisplayName(f) }}
+ </el-tag>
+ <p class="section-tip">浠ヤ笂涓烘ā鏉块檮甯︽枃浠讹紝浠呬緵鍙傝�冿紱鎻愪氦闄勪欢璇峰湪涓嬫柟涓婁紶銆�</p>
+ </el-form-item>
+
+ <el-form-item v-if="!flowOnly" label="闄勪欢">
+ <FileUpload
+ v-model:file-list="attachmentsModel"
+ :limit="uploadLimit"
+ button-text="鐐瑰嚮閫夋嫨鏂囦欢"
+ />
+ <p class="section-tip">閫夊~锛屽彲涓婁紶涓庣敵璇风浉鍏崇殑璇存槑鏉愭枡銆�</p>
+ </el-form-item>
+ </template>
+ <el-empty v-else description="璇峰厛閫夋嫨瀹℃壒妯℃澘" :image-size="64" />
+</template>
+
+<script setup>
+import { computed } from "vue";
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+import TemplateFlowEditor from "../../approve-template/components/TemplateFlowEditor.vue";
+import FormPayloadFields from "../../approve-list/components/FormPayloadFields.vue";
+import { attachmentDisplayName } from "../approvalTemplateBindingUtils.js";
+
+const props = defineProps({
+ activeTemplate: { type: Object, default: null },
+ fields: { type: Array, default: () => [] },
+ formPayload: { type: Object, required: true },
+ flowNodes: { type: Array, default: () => [] },
+ /** 鐢ㄦ埛鑷涓婁紶鐨勯檮浠� */
+ attachments: { type: Array, default: () => [] },
+ /** 妯℃澘棰勭疆闄勪欢锛堝彧璇诲睍绀猴級 */
+ templateAttachments: { type: Array, default: () => [] },
+ userOptions: { type: Array, default: () => [] },
+ showTemplateName: { type: Boolean, default: true },
+ allowChangeTemplate: { type: Boolean, default: true },
+ /** 涓� true 鏃朵笉灞曠ず妯℃澘鑷畾涔夊~鎶ラ」锛堜粎淇濈暀瀹℃壒娴佺▼涓庨檮浠讹級 */
+ hideFormFields: { type: Boolean, default: false },
+ /** 涓� true 鏃朵笉灞曠ず瀹℃壒妯℃澘鍚嶇О琛岋紙鐢辩埗绾х疆椤跺睍绀猴級 */
+ hideTemplateName: { type: Boolean, default: false },
+ /** 涓� true 鏃朵粎灞曠ず瀹℃壒娴佺▼涓庨檮浠讹紙濉姤椤圭敱鐖剁骇鍗曠嫭娓叉煋锛� */
+ flowAttachmentsOnly: { type: Boolean, default: false },
+ /** 涓� true 鏃朵粎灞曠ず瀹℃壒娴佺▼锛堜笉灞曠ず妯℃澘濉姤椤广�侀檮浠剁瓑锛� */
+ flowOnly: { type: Boolean, default: false },
+ uploadLimit: { type: Number, default: 10 },
+ /** 涓� true 鏃跺彲缂栬緫妯℃澘棰勭疆鐨勫鎵逛汉锛堜粎瀹℃壒妯℃澘绠$悊椤典娇鐢級 */
+ flowEditable: { type: Boolean, default: false },
+});
+
+const emit = defineEmits(["update:flowNodes", "update:attachments", "change-template"]);
+
+const flowNodesModel = computed({
+ get: () => props.flowNodes,
+ set: (v) => emit("update:flowNodes", v),
+});
+
+const attachmentsModel = computed({
+ get: () => props.attachments,
+ set: (v) => emit("update:attachments", v),
+});
+</script>
+
+<style scoped>
+.template-name {
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+}
+.ml12 {
+ margin-left: 12px;
+}
+.section-tip {
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ margin: 8px 0 0;
+ line-height: 1.5;
+}
+.attachment-tag {
+ margin: 0 8px 8px 0;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplatePicker.vue b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplatePicker.vue
new file mode 100644
index 0000000..8adfebc
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/components/ApprovalTemplatePicker.vue
@@ -0,0 +1,85 @@
+<!-- 瀹℃壒妯℃澘鍗$墖閫夋嫨锛堟寜 businessType 杩囨护锛� -->
+<template>
+ <div class="approval-template-picker">
+ <p v-if="hint" class="picker-hint">{{ hint }}</p>
+ <div v-loading="loading" class="template-grid">
+ <div
+ v-for="card in cards"
+ :key="card.key || card.id"
+ class="template-card"
+ @click="emit('pick', card)"
+ >
+ <span class="template-card-type" :style="typeStyle(card.approvalType)">
+ {{ card.label }}
+ </span>
+ <span class="template-card-desc">{{ card.summaryPlaceholder }}</span>
+ </div>
+ <el-empty
+ v-if="!loading && !cards.length"
+ :description="emptyText"
+ :image-size="80"
+ class="template-empty"
+ />
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { approvalTypeStyle } from "../../approve-list/approveListConstants.js";
+
+defineProps({
+ cards: { type: Array, default: () => [] },
+ loading: { type: Boolean, default: false },
+ hint: { type: String, default: "" },
+ emptyText: { type: String, default: "璇ョ被鍨嬩笅鏆傛棤鍙敤瀹℃壒妯℃澘" },
+});
+
+const emit = defineEmits(["pick"]);
+
+function typeStyle(approvalType) {
+ return approvalTypeStyle(approvalType);
+}
+</script>
+
+<style scoped>
+.picker-hint {
+ font-size: 13px;
+ color: var(--el-text-color-secondary);
+ margin: 0 0 16px;
+}
+.template-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+ gap: 12px;
+ min-height: 120px;
+}
+.template-empty {
+ grid-column: 1 / -1;
+}
+.template-card {
+ padding: 14px 16px;
+ border: 1px solid var(--el-border-color-lighter);
+ border-radius: var(--radius-md, 8px);
+ cursor: pointer;
+ transition: border-color 0.2s, box-shadow 0.2s;
+ background: var(--el-fill-color-blank);
+}
+.template-card:hover {
+ border-color: var(--el-color-primary);
+ box-shadow: var(--shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.06));
+}
+.template-card-type {
+ display: inline-block;
+ padding: 2px 8px;
+ border-radius: 4px;
+ font-size: 13px;
+ font-weight: 600;
+ margin-bottom: 8px;
+}
+.template-card-desc {
+ display: block;
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ line-height: 1.5;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalInstanceModule.js b/src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalInstanceModule.js
new file mode 100644
index 0000000..b474bb2
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalInstanceModule.js
@@ -0,0 +1,408 @@
+import {
+ deleteApprovalInstance,
+ listApprovalInstancePage,
+ saveApprovalInstance,
+ updateApprovalInstance,
+} from "@/api/officeProcessAutomation/approvalInstance.js";
+import useUserStore from "@/store/modules/user";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { computed, reactive, ref } from "vue";
+import {
+ applyBindingToForm,
+ buildFormPayloadRules,
+ validateTemplateBinding,
+} from "./approvalTemplateBindingUtils.js";
+import {
+ buildApprovalInstanceListParams,
+ buildEditFormFromInstanceRow,
+ buildInstanceDto,
+ canEditBusinessInstanceRow,
+ createEmptySubmitForm,
+ mapInstanceFromApi,
+ resolveInstanceFormFields,
+ unwrapInstancePage,
+} from "../approve-list/approveListConstants.js";
+import { fetchBusinessTypeOptions } from "../approve-template/approveTemplateConstants.js";
+import {
+ collectOptionSourcesFromFields,
+ fetchSelectOptionCaches,
+} from "../approve-template/selectOptionSource.js";
+import { enrichInstanceRowFromFormConfig } from "./approvalInstanceFormConfigTable.js";
+import {
+ filterInstanceRowsByModuleSearch,
+ hasActiveModuleSearch,
+} from "./approvalInstanceListSearch.js";
+import {
+ getApprovalModuleConfig,
+ getModuleListBusinessType,
+ resolveModuleBusinessType,
+} from "./approvalModuleRegistry.js";
+
+/**
+ * 涓氬姟鐢宠椤靛叡鐢細瀹℃壒瀹炰緥鍒楄〃鏌ヨ銆佹柊澧�/淇敼淇濆瓨銆佽鎯�/缂栬緫寮圭獥锛堜笌瀹℃壒鍒楄〃涓�鑷达級
+ *
+ * @param {object} options
+ * @param {string} options.moduleKey approvalModuleRegistry 涓殑 key
+ * @param {(row: object) => object} [options.enrichListRow] 鍒楄〃琛屽寮猴紙浠� formPayload 瑙f瀽灞曠ず瀛楁锛�
+ * @param {(base: object) => object} [options.buildExtraListParams] 杩藉姞鏌ヨ鍙傛暟
+ * @param {() => void} [options.beforeSave] 淇濆瓨鍓嶉挬瀛愶紙濡傚悓姝ヤ笟鍔″瓧娈靛埌 formPayload锛�
+ * @param {import('vue').ComputedRef|object} [options.extraFormRules] 棰濆琛ㄥ崟鏍¢獙
+ */
+export function useApprovalInstanceModule(options = {}) {
+ const {
+ moduleKey,
+ enrichListRow,
+ buildExtraListParams,
+ beforeSave,
+ extraFormRules,
+ } = options;
+
+ const userStore = useUserStore();
+ const moduleConfig = computed(() => getApprovalModuleConfig(moduleKey));
+ const businessTypeOptions = ref([]);
+
+ /** 鍒楄〃鏌ヨ businessType锛氫紭鍏� registry 鍐欐鏋氫妇锛屽啀鍥為�� TypeEnums */
+ const defaultListBusinessType = computed(() => {
+ const fixed = getModuleListBusinessType(moduleKey);
+ if (fixed != null && fixed !== "") return fixed;
+ const resolved = resolveModuleBusinessType(moduleKey, businessTypeOptions.value);
+ if (resolved != null && resolved !== "") return resolved;
+ return "";
+ });
+
+ async function loadBusinessTypeOptions() {
+ if (businessTypeOptions.value.length) return;
+ try {
+ businessTypeOptions.value = await fetchBusinessTypeOptions();
+ } catch {
+ businessTypeOptions.value = [];
+ }
+ }
+
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({ current: 1, size: 10, total: 0 });
+
+ const detailDialog = reactive({ visible: false });
+ const detailRow = ref({});
+
+ const submitDialog = reactive({ visible: false, mode: "add" });
+ const submitEditRow = ref(null);
+ const submitForm = reactive(createEmptySubmitForm(""));
+ const submitFormRef = ref();
+ const submitSaving = ref(false);
+
+ const templateBindVisible = ref(false);
+ const pendingTemplateBinding = ref(null);
+ /** 鏈�杩戜竴娆″垪琛ㄦ煡璇㈡潯浠讹紙淇濆瓨鍚庡埛鏂板垪琛ㄦ椂娌跨敤锛� */
+ let lastListSearchForm = null;
+
+ const isSubmitEdit = computed(() => submitDialog.mode === "edit");
+ const activeTemplate = computed(() => submitForm.templateSnapshot || null);
+ const submitFormFields = computed(() => {
+ const tplFields = activeTemplate.value?.fields;
+ if (tplFields?.length) return tplFields;
+ return submitForm.formFieldDefs || [];
+ });
+
+ const submitFormRules = computed(() => ({
+ ...buildFormPayloadRules(submitFormFields.value),
+ ...(extraFormRules?.value ?? extraFormRules ?? {}),
+ }));
+
+ const submitDialogTitle = computed(() => {
+ const label = moduleConfig.value?.label || "鐢宠";
+ if (submitDialog.mode === "edit") {
+ return `淇敼${activeTemplate.value?.label || submitForm.templateName || label}`;
+ }
+ return `鏂板${label}`;
+ });
+
+ function mapListRow(row, caches) {
+ const mapped = mapInstanceFromApi(row);
+ const fromFormConfig = enrichInstanceRowFromFormConfig(mapped, caches);
+ return enrichListRow ? enrichListRow(fromFormConfig) : fromFormConfig;
+ }
+
+ async function fetchList(searchForm = {}) {
+ await loadBusinessTypeOptions();
+ tableLoading.value = true;
+ try {
+ let extraParams = {};
+ if (buildExtraListParams) {
+ extraParams = buildExtraListParams(searchForm) || {};
+ }
+ const res = await listApprovalInstancePage(
+ buildApprovalInstanceListParams({
+ page,
+ searchForm,
+ businessType: defaultListBusinessType.value,
+ extraParams,
+ })
+ );
+ const { records, total } = unwrapInstancePage(res);
+ const mapped = records.map(mapInstanceFromApi);
+ const allFields = [];
+ for (const row of mapped) {
+ const { fields } = resolveInstanceFormFields(row);
+ allFields.push(...fields);
+ }
+ const caches = await fetchSelectOptionCaches(
+ collectOptionSourcesFromFields(allFields)
+ );
+ let rows = mapped.map((row) => mapListRow(row, caches));
+ if (hasActiveModuleSearch(moduleKey, searchForm)) {
+ rows = filterInstanceRowsByModuleSearch(moduleKey, rows, searchForm);
+ }
+ tableData.value = rows;
+ page.total = hasActiveModuleSearch(moduleKey, searchForm)
+ ? rows.length
+ : total;
+ } catch {
+ tableData.value = [];
+ page.total = 0;
+ ElMessage.error(`${moduleConfig.value?.label || "鐢宠"}鍒楄〃鍔犺浇澶辫触`);
+ } finally {
+ tableLoading.value = false;
+ }
+ }
+
+ function handleQuery(searchForm) {
+ lastListSearchForm = searchForm;
+ page.current = 1;
+ return fetchList(searchForm);
+ }
+
+ /** 杩涘叆椤甸潰锛氬厛鎷� TypeEnums 瑙f瀽 businessType锛屽啀鏌ュ垪琛� */
+ async function initModuleList(searchForm) {
+ await loadBusinessTypeOptions();
+ return handleQuery(searchForm);
+ }
+
+ function pagination({ page: p, limit }, searchForm) {
+ page.current = p;
+ page.size = limit;
+ return fetchList(searchForm);
+ }
+
+ function openDetail(row) {
+ detailRow.value = { ...row };
+ detailDialog.visible = true;
+ }
+
+ function openEdit(row) {
+ if (!canEditBusinessInstanceRow(row)) {
+ ElMessage.warning("杩涜涓垨宸插畬鎴愮殑瀹℃壒涓嶅彲淇敼");
+ return;
+ }
+ if (!row?.id) {
+ ElMessage.warning("鏃犳硶淇敼锛氱己灏戝鎵瑰疄渚� ID");
+ return;
+ }
+ submitDialog.mode = "edit";
+ submitEditRow.value = { ...row };
+ Object.assign(submitForm, buildEditFormFromInstanceRow(row));
+ submitDialog.visible = true;
+ }
+
+ function openEditFromDetail() {
+ const row = detailRow.value;
+ detailDialog.visible = false;
+ openEdit(row);
+ }
+
+ function resetSubmitForm() {
+ Object.assign(submitForm, createEmptySubmitForm(""));
+ submitEditRow.value = null;
+ }
+
+ function openAddWithTemplate() {
+ submitDialog.visible = false;
+ pendingTemplateBinding.value = null;
+ templateBindVisible.value = true;
+ }
+
+ function onTemplateBound(binding) {
+ pendingTemplateBinding.value = binding;
+ }
+
+ function onTemplateBindClosed() {
+ const binding = pendingTemplateBinding.value;
+ if (!binding) return;
+ pendingTemplateBinding.value = null;
+ openAddFromBinding(binding);
+ }
+
+ function openAddFromBinding(binding) {
+ resetSubmitForm();
+ applyBindingToForm(submitForm, binding);
+ submitDialog.mode = "add";
+ submitEditRow.value = null;
+ submitDialog.visible = true;
+ }
+
+ function closeSubmitDialog() {
+ submitDialog.visible = false;
+ }
+
+ async function submitInstanceForm(options = {}) {
+ const { skipValidate = false } = options;
+ if (!skipValidate) {
+ if (!submitFormRef.value?.validate) {
+ ElMessage.warning("琛ㄥ崟鏈氨缁紝璇峰叧闂脊绐楀悗閲嶈瘯");
+ return false;
+ }
+ try {
+ await submitFormRef.value.validate();
+ } catch {
+ ElMessage.warning("璇峰畬鍠勮〃鍗曞繀濉」鍚庡啀淇濆瓨");
+ return false;
+ }
+ }
+ if (!activeTemplate.value) {
+ ElMessage.warning("鏈姞杞藉鎵规ā鏉匡紝鏃犳硶淇濆瓨");
+ return false;
+ }
+ const bindingCheck = validateTemplateBinding({ flowNodes: submitForm.flowNodes });
+ if (!bindingCheck.ok) {
+ ElMessage.warning(bindingCheck.message);
+ return false;
+ }
+ if (!submitForm.templateId) {
+ ElMessage.warning("缂哄皯妯℃澘 ID锛屾棤娉曟彁浜�");
+ return false;
+ }
+ if (beforeSave) {
+ try {
+ await beforeSave(submitForm, { isEdit: isSubmitEdit.value, editRow: submitEditRow.value });
+ } catch {
+ return false;
+ }
+ }
+ if (submitSaving.value) return false;
+ submitSaving.value = true;
+ try {
+ const dto = buildInstanceDto({
+ submitForm,
+ activeTemplate: activeTemplate.value,
+ userStore,
+ flowNodes: bindingCheck.nodes,
+ existingRow: isSubmitEdit.value ? submitEditRow.value : null,
+ });
+ if (isSubmitEdit.value) {
+ await updateApprovalInstance(dto);
+ } else {
+ await saveApprovalInstance(dto);
+ }
+ submitDialog.visible = false;
+ if (!isSubmitEdit.value) page.current = 1;
+ await fetchList(lastListSearchForm ?? {});
+ if (detailDialog.visible && detailRow.value?.id === submitForm.instanceId) {
+ const hit = tableData.value.find((r) => r.id === submitForm.instanceId);
+ if (hit) detailRow.value = { ...hit };
+ else detailDialog.visible = false;
+ }
+ return true;
+ } catch {
+ ElMessage.error(isSubmitEdit.value ? "淇濆瓨澶辫触" : "鎻愪氦澶辫触");
+ return false;
+ } finally {
+ submitSaving.value = false;
+ }
+ }
+
+ async function removeInstance(row) {
+ if (row?.id == null || row.id === "") {
+ ElMessage.warning("鏃犳硶鍒犻櫎锛氱己灏戝鎵瑰疄渚� ID");
+ return;
+ }
+ const title = row.title || row.templateName || row.instanceNo || "璇ュ鎵�";
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゅ鎵广��${title}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+ "鍒犻櫎纭",
+ {
+ type: "warning",
+ confirmButtonText: "纭畾鍒犻櫎",
+ cancelButtonText: "鍙栨秷",
+ distinguishCancelAndClose: true,
+ autofocus: false,
+ }
+ );
+ } catch {
+ return;
+ }
+ try {
+ await deleteApprovalInstance([row.id]);
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ if (detailDialog.visible && detailRow.value?.id === row.id) {
+ detailDialog.visible = false;
+ }
+ if (submitDialog.visible && submitEditRow.value?.id === row.id) {
+ submitDialog.visible = false;
+ }
+ await fetchList(lastListSearchForm ?? {});
+ } catch {
+ /* 閿欒鐢辨嫤鎴櫒鎻愮ず */
+ }
+ }
+
+ /** 鏋勫缓鏍囧噯鎿嶄綔鍒楋細璇︽儏銆佷慨鏀广�佸垹闄わ紙涓庡鎵瑰垪琛ㄤ竴鑷达級 */
+ function buildTableActions(extraOperations = []) {
+ return [
+ { name: "璇︽儏", type: "text", clickFun: (row) => openDetail(row) },
+ {
+ name: "淇敼",
+ type: "text",
+ disabled: (row) => !canEditBusinessInstanceRow(row),
+ clickFun: (row) => openEdit(row),
+ },
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ clickFun: (row) => removeInstance(row),
+ },
+ ...extraOperations,
+ ];
+ }
+
+ return {
+ moduleConfig,
+ defaultListBusinessType,
+ tableData,
+ tableLoading,
+ page,
+ detailDialog,
+ detailRow,
+ submitDialog,
+ submitEditRow,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ isSubmitEdit,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitDialogTitle,
+ templateBindVisible,
+ pendingTemplateBinding,
+ fetchList,
+ handleQuery,
+ initModuleList,
+ pagination,
+ openDetail,
+ openEdit,
+ openEditFromDetail,
+ openAddWithTemplate,
+ onTemplateBound,
+ onTemplateBindClosed,
+ openAddFromBinding,
+ closeSubmitDialog,
+ resetSubmitForm,
+ submitInstanceForm,
+ removeInstance,
+ buildTableActions,
+ loadBusinessTypeOptions,
+ canEditBusinessInstanceRow,
+ };
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalTemplateBinding.js b/src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalTemplateBinding.js
new file mode 100644
index 0000000..d49ec53
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/useApprovalTemplateBinding.js
@@ -0,0 +1,259 @@
+import {
+ getApprovalTemplateDetail,
+ listApprovalTemplate,
+ TEMPLATE_TYPE_CUSTOM,
+} from "@/api/officeProcessAutomation/approvalTemplate.js";
+import { computed, reactive, ref } from "vue";
+import { ElMessage } from "element-plus";
+import {
+ fetchBusinessTypeOptions,
+ mapEnabledFromApi,
+ unwrapTemplateList,
+} from "../approve-template/approveTemplateConstants.js";
+import {
+ createEmptySubmitForm,
+ mapSubmitTemplateCard,
+ matchBusinessTypeValue,
+} from "../approve-list/approveListConstants.js";
+import {
+ getApprovalModuleConfig,
+ getModuleMatchingBusinessTypes,
+ resolveModuleBusinessType,
+} from "./approvalModuleRegistry.js";
+import {
+ buildFormPayloadRules,
+ buildTemplateBindingFromDetail,
+ validateTemplateBinding,
+} from "./approvalTemplateBindingUtils.js";
+
+/**
+ * 瀹℃壒妯℃澘缁戝畾锛堜笟鍔℃ā鍧楀浐瀹氱被鍨� / 瀹℃壒鍒楄〃閫氱敤锛�
+ *
+ * @param {object} options
+ * @param {string} [options.moduleKey] 涓氬姟妯″潡 key锛岃 approvalModuleRegistry
+ * @param {string|number} [options.businessType] 鐩存帴鎸囧畾绫诲瀷锛堜紭鍏堢骇楂樹簬 moduleKey锛�
+ * @param {'module'|'universal'} [options.mode] module=浠呮湰绫诲瀷妯℃澘锛泆niversal=闇�鍏堥�夌被鍨�
+ */
+export function useApprovalTemplateBinding(options = {}) {
+ const { moduleKey = null, businessType: fixedBusinessType = null, mode = moduleKey ? "module" : "universal" } =
+ options;
+
+ const isUniversal = mode === "universal" && !moduleKey && fixedBusinessType == null;
+
+ const allTemplates = ref([]);
+ const businessTypeOptions = ref([]);
+ const selectedBusinessType = ref(fixedBusinessType ?? "");
+ const templatesLoading = ref(false);
+ const step = ref(isUniversal ? 1 : 1);
+
+ const bindingForm = reactive(createEmptySubmitForm(""));
+
+ const moduleConfig = computed(() => getApprovalModuleConfig(moduleKey));
+
+ const resolvedBusinessType = computed(() => {
+ if (fixedBusinessType != null && fixedBusinessType !== "") return fixedBusinessType;
+ if (selectedBusinessType.value != null && selectedBusinessType.value !== "") {
+ return selectedBusinessType.value;
+ }
+ if (moduleKey) {
+ return resolveModuleBusinessType(moduleKey, businessTypeOptions.value);
+ }
+ return "";
+ });
+
+ const matchingBusinessTypes = computed(() => {
+ if (fixedBusinessType != null && fixedBusinessType !== "") return [fixedBusinessType];
+ if (isUniversal) {
+ const t = selectedBusinessType.value;
+ return t != null && t !== "" ? [t] : [];
+ }
+ if (moduleKey) {
+ return getModuleMatchingBusinessTypes(moduleKey, businessTypeOptions.value);
+ }
+ const t = resolvedBusinessType.value;
+ return t != null && t !== "" ? [t] : [];
+ });
+
+ const templateCards = computed(() => {
+ const types = matchingBusinessTypes.value;
+ if (!types.length) return [];
+ return allTemplates.value.filter((card) =>
+ types.some(
+ (t) =>
+ matchBusinessTypeValue(card.businessType, t) ||
+ matchBusinessTypeValue(card.approvalType, t)
+ )
+ );
+ });
+
+ const activeTemplate = computed(() => bindingForm.templateSnapshot || null);
+
+ const formFields = computed(() => {
+ const tplFields = activeTemplate.value?.fields;
+ if (tplFields?.length) return tplFields;
+ return bindingForm.formFieldDefs || [];
+ });
+
+ const formRules = computed(() => buildFormPayloadRules(formFields.value));
+
+ const hasTemplateBound = computed(() => Boolean(activeTemplate.value?.templateId || bindingForm.templateId));
+
+ function businessTypeLabel(type) {
+ if (type == null || type === "") return "";
+ const hit = businessTypeOptions.value.find((x) => matchBusinessTypeValue(x.value, type));
+ return hit?.label || moduleConfig.value?.label || "";
+ }
+
+ const selectedBusinessTypeLabel = computed(() => businessTypeLabel(resolvedBusinessType.value));
+
+ function countTemplatesByBusinessType(type) {
+ const types =
+ moduleKey && !fixedBusinessType
+ ? getModuleMatchingBusinessTypes(moduleKey, businessTypeOptions.value)
+ : [type];
+ return allTemplates.value.filter((card) =>
+ types.some(
+ (t) =>
+ matchBusinessTypeValue(card.businessType, t) ||
+ matchBusinessTypeValue(card.approvalType, t)
+ )
+ ).length;
+ }
+
+ async function loadTemplates() {
+ templatesLoading.value = true;
+ try {
+ const [typeOptions, customRes] = await Promise.all([
+ fetchBusinessTypeOptions(),
+ listApprovalTemplate(TEMPLATE_TYPE_CUSTOM),
+ ]);
+ businessTypeOptions.value = typeOptions;
+ allTemplates.value = unwrapTemplateList(customRes)
+ .filter((row) => mapEnabledFromApi(row.enabled))
+ .map(mapSubmitTemplateCard);
+
+ if (moduleKey && !fixedBusinessType) {
+ const resolved = resolveModuleBusinessType(moduleKey, typeOptions);
+ if (resolved != null && resolved !== "") selectedBusinessType.value = resolved;
+ }
+ } catch {
+ businessTypeOptions.value = [];
+ allTemplates.value = [];
+ ElMessage.error("鍔犺浇瀹℃壒妯℃澘澶辫触");
+ } finally {
+ templatesLoading.value = false;
+ }
+ }
+
+ function resetBinding() {
+ step.value = isUniversal ? 1 : 1;
+ if (!fixedBusinessType && !moduleKey) selectedBusinessType.value = "";
+ else if (moduleKey) {
+ selectedBusinessType.value =
+ fixedBusinessType ?? resolveModuleBusinessType(moduleKey, businessTypeOptions.value) ?? "";
+ }
+ Object.assign(bindingForm, createEmptySubmitForm(""));
+ }
+
+ function pickBusinessType(type) {
+ if (!countTemplatesByBusinessType(type)) {
+ ElMessage.warning("璇ョ被鍨嬩笅鏆傛棤鍙敤瀹℃壒妯℃澘");
+ return;
+ }
+ selectedBusinessType.value = type;
+ step.value = 2;
+ }
+
+ function backToBusinessTypePick() {
+ selectedBusinessType.value = "";
+ step.value = 1;
+ }
+
+ function backToTemplatePick() {
+ step.value = isUniversal ? 2 : 1;
+ }
+
+ async function pickTemplate(card) {
+ if (!card?.id) return false;
+ templatesLoading.value = true;
+ try {
+ const res = await getApprovalTemplateDetail(card.id);
+ const applied = buildTemplateBindingFromDetail(res);
+ Object.assign(bindingForm, {
+ templateKey: String(card.id),
+ ...applied,
+ });
+ step.value = isUniversal ? 3 : 2;
+ return true;
+ } catch {
+ ElMessage.error("鍔犺浇妯℃澘璇︽儏澶辫触");
+ return false;
+ } finally {
+ templatesLoading.value = false;
+ }
+ }
+
+ /** 鐩存帴浠ヨ鎯呰缁戝畾锛堢紪杈戝洖鏄撅級 */
+ function applyBindingState(state) {
+ if (!state) return;
+ Object.assign(bindingForm, createEmptySubmitForm(""), state);
+ step.value = isUniversal ? 3 : 2;
+ }
+
+ async function validateBinding(formRef) {
+ if (formRef?.validate) {
+ try {
+ await formRef.validate();
+ } catch {
+ return { ok: false };
+ }
+ }
+ if (!hasTemplateBound.value) {
+ return { ok: false, message: "璇烽�夋嫨瀹℃壒妯℃澘" };
+ }
+ return validateTemplateBinding({ flowNodes: bindingForm.flowNodes });
+ }
+
+ function getBindingPayload() {
+ return {
+ templateId: bindingForm.templateId,
+ templateName: bindingForm.templateName,
+ businessType: bindingForm.businessType ?? resolvedBusinessType.value,
+ templateSnapshot: bindingForm.templateSnapshot,
+ formFieldDefs: bindingForm.formFieldDefs,
+ formPayload: bindingForm.formPayload,
+ flowNodes: bindingForm.flowNodes,
+ templateAttachments: bindingForm.templateAttachments,
+ storageBlobDTOs: bindingForm.storageBlobDTOs,
+ };
+ }
+
+ return {
+ isUniversal,
+ moduleConfig,
+ step,
+ bindingForm,
+ allTemplates,
+ businessTypeOptions,
+ selectedBusinessType,
+ resolvedBusinessType,
+ selectedBusinessTypeLabel,
+ templateCards,
+ activeTemplate,
+ formFields,
+ formRules,
+ hasTemplateBound,
+ templatesLoading,
+ loadTemplates,
+ resetBinding,
+ pickBusinessType,
+ backToBusinessTypePick,
+ backToTemplatePick,
+ pickTemplate,
+ applyBindingState,
+ validateBinding,
+ getBindingPayload,
+ countTemplatesByBusinessType,
+ businessTypeLabel,
+ };
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-shared/useFlowUserOptions.js b/src/views/officeProcessAutomation/ApproveManage/approve-shared/useFlowUserOptions.js
new file mode 100644
index 0000000..2788ac7
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-shared/useFlowUserOptions.js
@@ -0,0 +1,35 @@
+import { ref } from "vue";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+
+function unwrapArray(payload) {
+ if (Array.isArray(payload)) return payload;
+ if (payload?.data && Array.isArray(payload.data)) return payload.data;
+ if (payload?.rows && Array.isArray(payload.rows)) return payload.rows;
+ return [];
+}
+
+function isActiveUser(u) {
+ if (u.delFlag === "2" || u.delFlag === 2) return false;
+ if (u.status == null) return true;
+ return String(u.status) === "0";
+}
+
+/** 瀹℃壒娴佺▼閫変汉涓嬫媺锛堟ā鏉�/瀹炰緥鍏辩敤锛� */
+export function useFlowUserOptions() {
+ const flowUserOptions = ref([]);
+ const loading = ref(false);
+
+ async function loadFlowUsers() {
+ loading.value = true;
+ try {
+ const res = await userListNoPageByTenantId();
+ flowUserOptions.value = unwrapArray(res).filter(isActiveUser);
+ } catch {
+ flowUserOptions.value = [];
+ } finally {
+ loading.value = false;
+ }
+ }
+
+ return { flowUserOptions, loading, loadFlowUsers };
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
new file mode 100644
index 0000000..727f896
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
@@ -0,0 +1,355 @@
+import dayjs from "dayjs";
+import { getTypeEnums } from "@/api/basicData/enum.js";
+import {
+ TEMPLATE_TYPE_BUILTIN,
+ TEMPLATE_TYPE_CUSTOM,
+} from "@/api/officeProcessAutomation/approvalTemplate.js";
+import { APPROVAL_TYPE_OPTIONS } from "../approve-list/approveListConstants.js";
+import {
+ buildFormConfigJson,
+ createEmptyFormConfigData,
+ parseFormConfigToData,
+ validateFormConfigData,
+} from "./formConfigUtils.js";
+
+export function unwrapEnumList(data) {
+ if (Array.isArray(data)) return data;
+ if (!data || typeof data !== "object") return [];
+ if (Array.isArray(data.TypeEnums)) return data.TypeEnums;
+ if (Array.isArray(data.typeEnums)) return data.typeEnums;
+ const nested = Object.values(data).find((v) => Array.isArray(v));
+ return nested || [];
+}
+
+export function normalizeBusinessTypeOptions(data) {
+ return unwrapEnumList(data)
+ .map((item) => {
+ const rawValue = item?.value ?? item?.code ?? item?.businessType ?? item?.dictValue ?? item?.key;
+ if (rawValue == null || rawValue === "") return null;
+ const num = Number(rawValue);
+ const value =
+ typeof rawValue === "number" || (Number.isFinite(num) && String(rawValue).trim() !== "")
+ ? num
+ : rawValue;
+ const label =
+ item?.label ?? item?.name ?? item?.desc ?? item?.dictLabel ?? item?.text ?? String(value);
+ return { label, value };
+ })
+ .filter(Boolean);
+}
+
+export async function fetchBusinessTypeOptions() {
+ try {
+ const res = await getTypeEnums();
+ return normalizeBusinessTypeOptions(res?.data);
+ } catch {
+ return [];
+ }
+}
+
+/** 鏄惁涓虹郴缁熷唴缃ā鏉匡紙templateType === 0锛� */
+export function isBuiltinTemplate(row) {
+ return Number(row?.templateType) === TEMPLATE_TYPE_BUILTIN;
+}
+
+/** 鑺傜偣鍐呭鎵规柟寮忥細浼氱 / 鎴栫 */
+export const NODE_SIGN_MODE_OPTIONS = [
+ { value: "countersign", label: "浼氱", desc: "鏈妭鐐规墍鏈夊鎵逛汉鍧囬渶閫氳繃" },
+ { value: "or_sign", label: "鎴栫", desc: "鏈妭鐐逛换涓�瀹℃壒浜洪�氳繃鍗冲彲" },
+];
+
+function parseFormConfig(formConfig) {
+ if (!formConfig) return {};
+ if (typeof formConfig === "object") return formConfig;
+ try {
+ return JSON.parse(formConfig);
+ } catch {
+ return {};
+ }
+}
+
+function resolveDefaultMode(row, cfg, nodes) {
+ let mode = cfg.approvalMode || cfg.defaultMode;
+ if (!mode && nodes.length) {
+ const t = String(nodes[0]?.approveType || "").toUpperCase();
+ mode = t === "OR" ? "or_sign" : "parallel";
+ }
+ const m = String(mode || "").toLowerCase();
+ if (m === "or" || m === "or_sign") return "or_sign";
+ return "parallel";
+}
+
+/** 灏嗘帴鍙h繑鍥炵殑妯℃澘杞负銆岀郴缁熷父鐢ㄥ鎵广�嶅崱鐗囨暟鎹� */
+export function mapBuiltinCardFromApi(row) {
+ const cfg = parseFormConfig(row?.formConfig);
+ const fields = cfg.fields || cfg.formFields || [];
+ const nodes = row?.nodes || row?.flowNodes || [];
+ return {
+ key: String(row?.id ?? row?.templateName ?? ""),
+ id: row?.id,
+ approvalType: cfg.approvalType || row?.approvalType || "",
+ label: row?.templateName || row?.name || "鈥�",
+ summary: (row?.description || "").trim() || cfg.summaryPlaceholder || "绯荤粺棰勭疆濉姤瀛楁",
+ fieldCount: fields.length,
+ defaultMode: resolveDefaultMode(row, cfg, nodes),
+ };
+}
+
+export function unwrapTemplateList(payload) {
+ const data = payload?.data ?? payload;
+ if (Array.isArray(data)) return data;
+ if (Array.isArray(data?.records)) return data.records;
+ if (Array.isArray(data?.list)) return data.list;
+ return [];
+}
+
+/** 鍚庣 approveType 鈫� 椤甸潰 signMode */
+export function mapSignModeFromApi(approveType) {
+ const t = String(approveType || "").toUpperCase();
+ return t === "OR" ? "or_sign" : "countersign";
+}
+
+/** 椤甸潰 signMode 鈫� 鍚庣 approveType */
+export function mapSignModeToApi(signMode) {
+ return signMode === "or_sign" ? "OR" : "AND";
+}
+
+/** 椤甸潰 enabled 鈫� 鍚庣 enabled锛�1 鍚敤锛�0 鍋滅敤锛� */
+export function mapEnabledToApi(enabled) {
+ return enabled !== false ? "1" : "0";
+}
+
+/** 鍚庣 nodes 鈫� 椤甸潰 flowNodes锛堜繚鐣� id 渚涗慨鏀规彁浜わ級 */
+export function mapNodesFromApi(nodes) {
+ const list = Array.isArray(nodes) ? nodes : [];
+ return list.map((n, i) => ({
+ id: n.id,
+ templateId: n.templateId,
+ nodeOrder: n.levelNo ?? i + 1,
+ signMode: mapSignModeFromApi(n.approveType ?? n.signMode),
+ approvers: (n.approvers || [])
+ .filter((a) => a?.approverId != null && a.approverId !== "")
+ .map((a) => ({
+ id: a.id,
+ nodeId: a.nodeId,
+ templateId: a.templateId,
+ approverId: a.approverId,
+ approverName: a.approverName || "",
+ })),
+ }));
+}
+
+/** enabled锛�1 鍚敤锛�0 鍋滅敤 */
+export function mapEnabledFromApi(enabled) {
+ return enabled === "1" || enabled === 1 || enabled === true;
+}
+
+/** 鍏煎澶氱鍚庣鏃堕棿瀛楁鍚嶅苟鏍煎紡鍖栧睍绀� */
+export function pickTemplateTimes(row) {
+ const rawCreated =
+ row?.createdTime ?? row?.createTime ?? row?.gmtCreate ?? row?.created_at ?? "";
+ const rawUpdated =
+ row?.updatedTime ?? row?.updateTime ?? row?.gmtModified ?? row?.modifyTime ?? row?.updated_at ?? "";
+ const createdTime = normalizeTimeValue(rawCreated);
+ const updatedTime = normalizeTimeValue(rawUpdated);
+ return { createdTime, updatedTime, createTime: createdTime, updateTime: updatedTime };
+}
+
+function normalizeTimeValue(val) {
+ if (val == null || val === "") return "";
+ if (Array.isArray(val) && val.length >= 3) {
+ const [y, m, d, h = 0, min = 0, s = 0] = val;
+ return dayjs(new Date(y, m - 1, d, h, min, s)).format("YYYY-MM-DD HH:mm:ss");
+ }
+ if (typeof val === "number") {
+ const d = val > 1e12 ? dayjs(val) : dayjs.unix(val);
+ return d.isValid() ? d.format("YYYY-MM-DD HH:mm:ss") : "";
+ }
+ const s = String(val).trim();
+ if (!s) return "";
+ const parsed = dayjs(s.includes("T") ? s : s.replace(/-/g, "/"));
+ return parsed.isValid() ? parsed.format("YYYY-MM-DD HH:mm:ss") : s;
+}
+
+export function formatDisplayTime(val) {
+ const t = normalizeTimeValue(val);
+ return t || "鈥�";
+}
+
+/** 璇︽儏鎺ュ彛 data 瑙e寘 */
+export function unwrapTemplateDetail(res) {
+ const data = res?.data ?? res;
+ if (!data || typeof data !== "object") return {};
+ if (data.templateName != null || data.id != null) return data;
+ if (data.approvalTemplateVo) return data.approvalTemplateVo;
+ if (data.records && data.records[0]) return data.records[0];
+ return data;
+}
+
+/** 鍚庣闄勪欢瀛楁 鈫� 椤甸潰 storageBlobDTOs */
+export function mapAttachmentsFromApi(row) {
+ const list =
+ row?.storageBlobDTOs ||
+ row?.storageBlobDTOS ||
+ row?.storageBlobVOS ||
+ row?.storageBlobVOList ||
+ row?.attachmentList ||
+ [];
+ return Array.isArray(list) ? list : [];
+}
+
+/** 鍒嗛〉鍒楄〃椤� 鈫� 椤甸潰琛屾暟鎹紙涓昏〃 + 鑺傜偣锛� */
+export function mapTemplateFromApi(row) {
+ if (!row) return {};
+ const flowNodes = mapNodesFromApi(row.nodes || row.flowNodes);
+ const times = pickTemplateTimes(row);
+ return {
+ id: row.id,
+ templateName: row.templateName || "",
+ description: row.description || "",
+ enabled: mapEnabledFromApi(row.enabled),
+ enabledRaw: row.enabled,
+ templateType: row.templateType != null ? Number(row.templateType) : undefined,
+ businessType: row.businessType ?? "",
+ formConfig: row.formConfig,
+ formConfigData: parseFormConfigToData(row.formConfig),
+ storageBlobDTOs: mapAttachmentsFromApi(row),
+ createdUser: row.createdUser,
+ createdUserName: row.createdUserName,
+ ...times,
+ flowNodes,
+ nodes: row.nodes || row.flowNodes,
+ };
+}
+
+/** 琛ㄥ崟鏁版嵁 鈫� 鎻愪氦 DTO锛圓pprovalTemplateDto锛� */
+export function mapTemplateToApi(form) {
+ const nodes = normalizeFlowNodes(form.flowNodes);
+ const templateId = form.id || null;
+ const dto = {
+ templateName: (form.templateName || "").trim(),
+ description: (form.description || "").trim(),
+ enabled: mapEnabledToApi(form.enabled),
+ templateType:
+ form.templateType != null ? Number(form.templateType) : TEMPLATE_TYPE_CUSTOM,
+ businessType: form.businessType ?? "",
+ formConfig: buildFormConfigJson(form.formConfigData),
+ nodes: nodes.map((n, i) => {
+ const node = {
+ levelNo: n.nodeOrder ?? i + 1,
+ approveType: mapSignModeToApi(n.signMode),
+ approvers: n.approvers.map((a, idx) => {
+ const approver = {
+ approverId: a.approverId,
+ approverName: a.approverName || "",
+ sortNo: idx + 1,
+ };
+ if (a.id != null) approver.id = a.id;
+ if (a.nodeId != null) approver.nodeId = a.nodeId;
+ if (a.templateId != null) approver.templateId = a.templateId;
+ else if (templateId) approver.templateId = templateId;
+ return approver;
+ }),
+ };
+ if (n.id != null) node.id = n.id;
+ if (n.templateId != null) node.templateId = n.templateId;
+ else if (templateId) node.templateId = templateId;
+ return node;
+ }),
+ };
+ if (templateId) dto.id = templateId;
+ const attachments = Array.isArray(form.storageBlobDTOs) ? form.storageBlobDTOs : [];
+ if (attachments.length) dto.storageBlobDTOs = attachments;
+ return dto;
+}
+
+export function buildApprovalTemplateListParams({ page, searchForm }) {
+ const params = {
+ current: page.current,
+ size: page.size,
+ };
+ const kw = (searchForm?.keyword || "").trim();
+ if (kw) params.templateName = kw;
+ if (searchForm?.enabledOnly) params.enabled = "1";
+ return params;
+}
+
+export function nodeSignModeLabel(mode) {
+ return NODE_SIGN_MODE_OPTIONS.find((x) => x.value === mode)?.label || "鈥�";
+}
+
+export function approvalTypeLabel(type) {
+ return APPROVAL_TYPE_OPTIONS.find((x) => x.value === type)?.label || type || "鈥�";
+}
+
+export function createEmptyNode(order = 1) {
+ return {
+ nodeOrder: order,
+ signMode: "countersign",
+ approvers: [],
+ };
+}
+
+export function createEmptyTemplateForm() {
+ return {
+ id: "",
+ templateName: "",
+ description: "",
+ templateType: TEMPLATE_TYPE_CUSTOM,
+ lockedFormFieldUids: [],
+ businessType: "",
+ formConfig: "",
+ formConfigData: createEmptyFormConfigData(),
+ enabled: true,
+ flowNodes: [createEmptyNode(1)],
+ storageBlobDTOs: [],
+ };
+}
+
+export function normalizeFlowNodes(nodes) {
+ const list = Array.isArray(nodes) ? nodes : [];
+ return list.map((n, i) => ({
+ id: n.id,
+ templateId: n.templateId,
+ nodeOrder: i + 1,
+ signMode: n.signMode === "or_sign" ? "or_sign" : "countersign",
+ approvers: (n.approvers || [])
+ .filter((a) => a?.approverId != null && a.approverId !== "")
+ .map((a) => ({
+ id: a.id,
+ nodeId: a.nodeId,
+ templateId: a.templateId,
+ approverId: a.approverId,
+ approverName: a.approverName || "",
+ })),
+ }));
+}
+
+export function validateTemplateForm(form) {
+ const name = (form.templateName || "").trim();
+ if (!name) return { ok: false, message: "璇峰~鍐欐ā鏉垮悕绉�" };
+ if (form.businessType == null || form.businessType === "") {
+ return { ok: false, message: "璇烽�夋嫨妯℃澘绫诲瀷" };
+ }
+ const nodes = normalizeFlowNodes(form.flowNodes);
+ if (!nodes.length) return { ok: false, message: "璇疯嚦灏戦厤缃竴涓鎵硅妭鐐�" };
+ for (let i = 0; i < nodes.length; i++) {
+ if (!nodes[i].approvers.length) {
+ return { ok: false, message: `璇蜂负绗� ${i + 1} 涓妭鐐归�夋嫨鑷冲皯涓�鍚嶅鎵逛汉` };
+ }
+ }
+ const cfgCheck = validateFormConfigData(form.formConfigData);
+ if (!cfgCheck.ok) return cfgCheck;
+ return { ok: true, nodes, name };
+}
+
+export function flowNodesSummary(nodes) {
+ const list = normalizeFlowNodes(nodes);
+ if (!list.length) return "鈥�";
+ return list
+ .map((n, i) => {
+ const names = n.approvers.map((a) => a.approverName || "鏈懡鍚�").join("銆�") || "鏈厤缃�";
+ return `鑺傜偣${i + 1}(${nodeSignModeLabel(n.signMode)}:${names})`;
+ })
+ .join(" 鈫� ");
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/components/FormConfigEditor.vue b/src/views/officeProcessAutomation/ApproveManage/approve-template/components/FormConfigEditor.vue
new file mode 100644
index 0000000..6880f3f
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/components/FormConfigEditor.vue
@@ -0,0 +1,857 @@
+<!-- 瀹℃壒妯℃澘锛氬彲閰嶇疆濉姤椤癸紝搴忓垪鍖栧埌 formConfig -->
+<template>
+ <div class="fce">
+ <div class="fce-hint">
+ <span class="fce-hint-label">濉姤鎻愮ず</span>
+ <el-input
+ v-model="inner.summaryPlaceholder"
+ placeholder="濡傦細璇峰~鍐欐姤閿�浜嬬敱銆侀噾棰濈瓑"
+ maxlength="200"
+ show-word-limit
+ @input="emitOut"
+ />
+ </div>
+
+ <div class="fce-panel">
+ <div class="fce-toolbar">
+ <div class="fce-toolbar-left">
+ <span class="fce-title">濉姤椤归厤缃�</span>
+ <el-tag v-if="inner.fields.length" size="small" type="info" effect="plain">
+ 鍏� {{ inner.fields.length }} 椤�
+ </el-tag>
+ </div>
+ <div class="fce-toolbar-actions">
+ <el-dropdown
+ trigger="click"
+ :disabled="disableImport"
+ @visible-change="onImportDropdownVisible"
+ @command="importFromTemplate"
+ >
+ <el-button size="small" :loading="templateImportLoading" :disabled="disableImport">
+ 浠庡凡鏈夋ā鏉垮鍏�
+ </el-button>
+ <template #dropdown>
+ <el-dropdown-menu>
+ <el-dropdown-item v-if="!templateImportOptions.length" disabled>
+ 鏆傛棤鍏朵粬瀹℃壒妯℃澘
+ </el-dropdown-item>
+ <el-dropdown-item
+ v-for="t in templateImportOptions"
+ :key="t.id"
+ :command="t.id"
+ >
+ <span>{{ t.label }}</span>
+ <el-tag v-if="!t.enabled" size="small" type="info" class="import-tag">宸插仠鐢�</el-tag>
+ </el-dropdown-item>
+ </el-dropdown-menu>
+ </template>
+ </el-dropdown>
+ <el-button type="primary" size="small" :icon="Plus" @click="addField">娣诲姞濉姤椤�</el-button>
+ </div>
+ </div>
+
+ <el-empty
+ v-if="!inner.fields.length"
+ class="fce-empty"
+ description="鏆傛棤濉姤椤癸紝鍙坊鍔犳垨浠庡凡鏈夊鎵规ā鏉垮鍏�"
+ :image-size="72"
+ />
+
+ <div v-else class="fce-list">
+ <div
+ v-for="(field, index) in inner.fields"
+ :key="field._uid"
+ class="fce-card"
+ :class="{
+ 'fce-card--required': field.required,
+ 'fce-card--locked': isFieldLocked(field),
+ }"
+ >
+ <div class="fce-card-badge">{{ index + 1 }}</div>
+
+ <div class="fce-card-head">
+ <div class="fce-card-title">
+ <span class="fce-card-name">{{ field.label || `濉姤椤� ${index + 1}` }}</span>
+ <el-tag size="small" effect="light" type="primary">{{ typeLabel(field.type) }}</el-tag>
+ <el-tag v-if="field.required" size="small" type="danger" effect="plain">蹇呭~</el-tag>
+ <el-tag v-if="isFieldLocked(field)" size="small" type="info" effect="plain">鍐呯疆椤�</el-tag>
+ </div>
+ <div v-if="!isFieldLocked(field)" class="fce-card-btns">
+ <el-tooltip content="涓婄Щ" placement="top">
+ <el-button circle size="small" :disabled="index === 0" @click="moveField(index, -1)">
+ <el-icon><Top /></el-icon>
+ </el-button>
+ </el-tooltip>
+ <el-tooltip content="涓嬬Щ" placement="top">
+ <el-button
+ circle
+ size="small"
+ :disabled="index >= inner.fields.length - 1"
+ @click="moveField(index, 1)"
+ >
+ <el-icon><Bottom /></el-icon>
+ </el-button>
+ </el-tooltip>
+ <el-tooltip content="鍒犻櫎" placement="top">
+ <el-button circle size="small" type="danger" plain @click="removeField(index)">
+ <el-icon><Delete /></el-icon>
+ </el-button>
+ </el-tooltip>
+ </div>
+ </div>
+
+ <div class="fce-section">
+ <span class="fce-section-title">鍩虹淇℃伅</span>
+ <el-row :gutter="16">
+ <el-col :span="8">
+ <el-form-item label="鏄剧ず鍚嶇О" required class="fce-field-item">
+ <el-input
+ v-model="field.label"
+ placeholder="濡傦細鎶ラ攢璇存槑"
+ maxlength="50"
+ :disabled="isFieldLocked(field)"
+ @input="emitOut"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="瀛楁鏍囪瘑" required class="fce-field-item">
+ <el-input
+ v-model="field.key"
+ placeholder="濡傦細summary"
+ maxlength="50"
+ :disabled="isFieldLocked(field)"
+ @input="emitOut"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鎺т欢绫诲瀷" class="fce-field-item">
+ <el-select
+ v-model="field.type"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ @change="onTypeChange(field)"
+ >
+ <el-option
+ v-for="t in FORM_FIELD_TYPE_OPTIONS"
+ :key="t.value"
+ :label="t.label"
+ :value="t.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </div>
+
+ <div class="fce-section">
+ <span class="fce-section-title">鏍¢獙涓庢牸寮�</span>
+ <el-row :gutter="16" align="middle">
+ <el-col :span="8">
+ <el-form-item label="鏄惁蹇呭~" class="fce-field-item fce-field-item--switch">
+ <el-switch
+ v-model="field.required"
+ inline-prompt
+ active-text="蹇呭~"
+ inactive-text="閫夊~"
+ :disabled="isFieldLocked(field)"
+ @change="emitOut"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col v-if="field.type === 'textarea'" :span="8">
+ <el-form-item label="琛屾暟" class="fce-field-item">
+ <el-input-number
+ v-model="field.rows"
+ :min="1"
+ :max="10"
+ controls-position="right"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ @change="emitOut"
+ />
+ </el-form-item>
+ </el-col>
+ <template v-if="field.type === 'number'">
+ <el-col :span="8">
+ <el-form-item label="鏈�灏忓��" class="fce-field-item">
+ <el-input-number
+ v-model="field.min"
+ controls-position="right"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ @change="emitOut"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="灏忔暟浣�" class="fce-field-item">
+ <el-input-number
+ v-model="field.precision"
+ :min="0"
+ :max="4"
+ controls-position="right"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ @change="emitOut"
+ />
+ </el-form-item>
+ </el-col>
+ </template>
+ </el-row>
+ </div>
+
+ <div class="fce-section fce-section--default">
+ <span class="fce-section-title">榛樿鍊�</span>
+ <p class="fce-section-desc">閫夋嫨璇ユā鏉挎彁浜ゅ鎵规椂锛屽皢鑷姩棰勫~浠ヤ笅鍐呭锛堢敤鎴蜂粛鍙慨鏀癸級</p>
+ <el-input
+ v-if="field.type === 'text' || field.type === 'textarea'"
+ v-model="field.defaultValue"
+ :type="field.type === 'textarea' ? 'textarea' : 'text'"
+ :rows="field.type === 'textarea' ? 2 : undefined"
+ :placeholder="defaultPlaceholder(field)"
+ :disabled="isFieldLocked(field)"
+ clearable
+ @input="emitOut"
+ />
+ <el-input-number
+ v-else-if="field.type === 'number'"
+ v-model="field.defaultValue"
+ :min="field.min"
+ :precision="field.precision ?? 0"
+ controls-position="right"
+ placeholder="閫夊~"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ @change="emitOut"
+ />
+ <el-date-picker
+ v-else-if="field.type === 'date'"
+ v-model="field.defaultValue"
+ type="date"
+ placeholder="閫夊~"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ clearable
+ @change="emitOut"
+ />
+ <el-date-picker
+ v-else-if="field.type === 'datetimerange'"
+ v-model="field.defaultValue"
+ type="datetimerange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫椂闂�"
+ end-placeholder="缁撴潫鏃堕棿"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ clearable
+ @change="emitOut"
+ />
+ <el-select
+ v-else-if="field.type === 'select'"
+ v-model="field.defaultValue"
+ placeholder="閫夊~"
+ style="width: 100%"
+ clearable
+ filterable
+ :loading="optionSourceLoading"
+ :disabled="isFieldLocked(field)"
+ @change="emitOut"
+ >
+ <el-option
+ v-for="o in resolvedSelectOptions(field)"
+ :key="String(o.value)"
+ :label="o.label || o.value"
+ :value="o.value"
+ />
+ </el-select>
+ </div>
+
+ <div v-if="field.type === 'select'" class="fce-section fce-section--options">
+ <span class="fce-section-title">涓嬫媺閫夐」</span>
+ <el-row :gutter="16" class="fce-source-row">
+ <el-col :span="12">
+ <el-form-item label="閫夐」鏉ユ簮" class="fce-field-item">
+ <el-select
+ v-model="field.optionSource"
+ style="width: 100%"
+ :disabled="isFieldLocked(field)"
+ @change="onOptionSourceChange(field)"
+ >
+ <el-option
+ v-for="s in SELECT_OPTION_SOURCE_OPTIONS"
+ :key="s.value"
+ :label="s.label"
+ :value="s.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <p v-if="isDynamicOptionSource(field.optionSource)" class="fce-source-tip">
+ {{ optionSourceDesc(field.optionSource) }}銆傛彁浜ゅ鎵规椂灏嗚嚜鍔ㄥ姞杞芥渶鏂版暟鎹紝鏃犻渶鎵嬪姩缁存姢閫夐」銆�
+ </p>
+ <template v-if="!isDynamicOptionSource(field.optionSource)">
+ <div class="fce-options-head">
+ <span class="fce-section-subtitle">鎵嬪姩閫夐」</span>
+ <el-button
+ type="primary"
+ link
+ size="small"
+ :icon="Plus"
+ :disabled="isFieldLocked(field)"
+ @click="addOption(field)"
+ >
+ 娣诲姞閫夐」
+ </el-button>
+ </div>
+ <div
+ v-for="(opt, oi) in field.options"
+ :key="oi"
+ class="fce-option-row"
+ >
+ <span class="fce-option-index">{{ oi + 1 }}</span>
+ <el-input
+ v-model="opt.label"
+ placeholder="鏄剧ず鏂囨湰"
+ :disabled="isFieldLocked(field)"
+ @input="emitOut"
+ />
+ <el-input
+ v-model="opt.value"
+ placeholder="閫夐」鍊�"
+ class="fce-option-value"
+ :disabled="isFieldLocked(field)"
+ @input="emitOut"
+ />
+ <el-button
+ type="danger"
+ link
+ :icon="Delete"
+ :disabled="isFieldLocked(field) || field.options.length <= 1"
+ @click="removeOption(field, oi)"
+ />
+ </div>
+ </template>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { Bottom, Delete, Plus, Top } from "@element-plus/icons-vue";
+import {
+ getApprovalTemplateDetail,
+ listApprovalTemplate,
+ TEMPLATE_TYPE_BUILTIN,
+ TEMPLATE_TYPE_CUSTOM,
+} from "@/api/officeProcessAutomation/approvalTemplate.js";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { computed, reactive, ref, watch } from "vue";
+import {
+ mapEnabledFromApi,
+ unwrapTemplateDetail,
+ unwrapTemplateList,
+} from "../approveTemplateConstants.js";
+import {
+ FORM_FIELD_TYPE_OPTIONS,
+ createEmptyFormConfigData,
+ createEmptyFormField,
+ formFieldTypeLabel,
+ parseFormConfigToData,
+} from "../formConfigUtils.js";
+import {
+ SELECT_OPTION_SOURCE,
+ SELECT_OPTION_SOURCE_OPTIONS,
+ isDynamicOptionSource,
+} from "../selectOptionSource.js";
+import { useSelectOptionSources } from "../useSelectOptionSources.js";
+
+const props = defineProps({
+ modelValue: { type: Object, default: () => createEmptyFormConfigData() },
+ /** 缂栬緫褰撳墠妯℃澘鏃舵帓闄よ嚜韬紝閬垮厤浠庤嚜宸卞鍏� */
+ excludeTemplateId: { type: [String, Number], default: null },
+ /** 绂佺敤銆屼粠宸叉湁妯℃澘瀵煎叆銆� */
+ disableImport: { type: Boolean, default: false },
+ /** 绯荤粺鍐呯疆妯℃澘缂栬緫鏃讹紝鎵撳紑寮圭獥鍗冲瓨鍦ㄧ殑濉姤椤� _uid锛屼笉鍙敼鍒� */
+ lockedFieldUids: { type: Array, default: () => [] },
+});
+
+const emit = defineEmits(["update:modelValue"]);
+
+const inner = reactive(createEmptyFormConfigData());
+
+const { loading: optionSourceLoading, ensureForFields, getOptions } = useSelectOptionSources();
+
+const templateImportOptions = ref([]);
+const templateImportLoading = ref(false);
+
+const lockedUidSet = computed(
+ () => new Set((props.lockedFieldUids || []).filter(Boolean))
+);
+
+function isFieldLocked(field) {
+ return field?._uid != null && lockedUidSet.value.has(field._uid);
+}
+
+function typeLabel(type) {
+ return formFieldTypeLabel(type);
+}
+
+function defaultPlaceholder(field) {
+ const name = field.label || "璇ュ瓧娈�";
+ return `閫夊~锛岄�夋嫨妯℃澘鏃跺皢棰勫~${name}`;
+}
+
+function optionSourceDesc(source) {
+ return SELECT_OPTION_SOURCE_OPTIONS.find((x) => x.value === source)?.desc || "";
+}
+
+function resolvedSelectOptions(field) {
+ if (field.type !== "select") return [];
+ return getOptions(field);
+}
+
+function syncFromProps(v) {
+ const src = v || createEmptyFormConfigData();
+ inner.summaryPlaceholder = src.summaryPlaceholder || "";
+ inner.fields = (src.fields || []).map((f) => ({
+ ...createEmptyFormField(),
+ ...f,
+ _uid: f._uid || createEmptyFormField()._uid,
+ optionSource: f.optionSource || SELECT_OPTION_SOURCE.STATIC,
+ options: (f.options || [{ label: "", value: "" }]).map((o) => ({ ...o })),
+ }));
+ ensureForFields(inner.fields);
+}
+
+function emitOut() {
+ emit("update:modelValue", {
+ summaryPlaceholder: inner.summaryPlaceholder,
+ fields: inner.fields.map((f) => ({
+ _uid: f._uid,
+ key: f.key,
+ label: f.label,
+ type: f.type,
+ required: f.required,
+ rows: f.rows,
+ min: f.min,
+ precision: f.precision,
+ defaultValue: cloneDefaultValue(f),
+ optionSource: f.optionSource || SELECT_OPTION_SOURCE.STATIC,
+ options: (f.options || []).map((o) => ({ label: o.label, value: o.value })),
+ })),
+ });
+}
+
+function cloneDefaultValue(f) {
+ if (f.type === "datetimerange" && Array.isArray(f.defaultValue)) {
+ return [...f.defaultValue];
+ }
+ return f.defaultValue;
+}
+
+watch(
+ () => props.modelValue,
+ (v) => syncFromProps(v),
+ { deep: true, immediate: true }
+);
+
+function addField() {
+ inner.fields.push(createEmptyFormField());
+ ensureForFields(inner.fields);
+ emitOut();
+}
+
+function removeField(index) {
+ if (isFieldLocked(inner.fields[index])) return;
+ inner.fields.splice(index, 1);
+ emitOut();
+}
+
+function moveField(index, delta) {
+ if (isFieldLocked(inner.fields[index])) return;
+ const next = index + delta;
+ if (next < 0 || next >= inner.fields.length) return;
+ if (isFieldLocked(inner.fields[next])) return;
+ const t = inner.fields[index];
+ inner.fields[index] = inner.fields[next];
+ inner.fields[next] = t;
+ emitOut();
+}
+
+function resetDefaultValueForType(field) {
+ if (field.type === "number") field.defaultValue = undefined;
+ else if (field.type === "datetimerange") field.defaultValue = [];
+ else field.defaultValue = "";
+}
+
+function onTypeChange(field) {
+ if (field.type === "select") {
+ if (!field.optionSource) field.optionSource = SELECT_OPTION_SOURCE.STATIC;
+ if (!field.options || !field.options.length) {
+ field.options = [{ label: "", value: "" }];
+ }
+ ensureForFields(inner.fields);
+ }
+ resetDefaultValueForType(field);
+ emitOut();
+}
+
+function onOptionSourceChange(field) {
+ field.defaultValue = "";
+ if (!isDynamicOptionSource(field.optionSource) && (!field.options || !field.options.length)) {
+ field.options = [{ label: "", value: "" }];
+ }
+ ensureForFields(inner.fields);
+ emitOut();
+}
+
+function addOption(field) {
+ field.options.push({ label: "", value: "" });
+ emitOut();
+}
+
+function removeOption(field, oi) {
+ if (field.options.length <= 1) return;
+ field.options.splice(oi, 1);
+ emitOut();
+}
+
+async function loadTemplateImportOptions() {
+ templateImportLoading.value = true;
+ try {
+ const [customRes, builtinRes] = await Promise.all([
+ listApprovalTemplate(TEMPLATE_TYPE_CUSTOM),
+ listApprovalTemplate(TEMPLATE_TYPE_BUILTIN),
+ ]);
+ const excludeId =
+ props.excludeTemplateId != null && props.excludeTemplateId !== ""
+ ? String(props.excludeTemplateId)
+ : "";
+ templateImportOptions.value = [...unwrapTemplateList(customRes), ...unwrapTemplateList(builtinRes)]
+ .filter((row) => row?.id != null && String(row.id) !== excludeId)
+ .map((row) => ({
+ id: row.id,
+ label: row.templateName || `妯℃澘 #${row.id}`,
+ enabled: mapEnabledFromApi(row.enabled),
+ }));
+ } catch {
+ templateImportOptions.value = [];
+ ElMessage.error("鍔犺浇瀹℃壒妯℃澘鍒楄〃澶辫触");
+ } finally {
+ templateImportLoading.value = false;
+ }
+}
+
+function onImportDropdownVisible(visible) {
+ if (props.disableImport) return;
+ if (visible) loadTemplateImportOptions();
+}
+
+async function importFromTemplate(templateId) {
+ if (!templateId) return;
+ if (inner.fields.length) {
+ try {
+ await ElMessageBox.confirm("灏嗚鐩栧綋鍓嶅~鎶ラ」閰嶇疆锛屾槸鍚︾户缁紵", "浠庢ā鏉垮鍏�", {
+ type: "warning",
+ confirmButtonText: "缁х画瀵煎叆",
+ cancelButtonText: "鍙栨秷",
+ });
+ } catch {
+ return;
+ }
+ }
+ templateImportLoading.value = true;
+ try {
+ const res = await getApprovalTemplateDetail(templateId);
+ const row = unwrapTemplateDetail(res);
+ const data = parseFormConfigToData(row?.formConfig);
+ if (!data.fields?.length) {
+ ElMessage.warning("璇ユā鏉挎湭閰嶇疆濉姤椤�");
+ return;
+ }
+ syncFromProps(data);
+ emitOut();
+ ElMessage.success(`宸插鍏ャ��${row.templateName || "妯℃澘"}銆嶇殑濉姤椤筦);
+ } catch {
+ ElMessage.error("鍔犺浇妯℃澘璇︽儏澶辫触");
+ } finally {
+ templateImportLoading.value = false;
+ }
+}
+</script>
+
+<style scoped>
+.fce {
+ width: 100%;
+}
+
+.fce-hint {
+ padding: 14px 16px;
+ margin-bottom: 14px;
+ border-radius: 10px;
+ background: linear-gradient(135deg, var(--el-color-primary-light-9) 0%, var(--el-fill-color-blank) 100%);
+ border: 1px solid var(--el-color-primary-light-7);
+}
+
+.fce-hint-label {
+ display: block;
+ font-size: 13px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+ margin-bottom: 8px;
+}
+
+.fce-panel {
+ padding: 16px;
+ border-radius: 12px;
+ background: var(--el-fill-color-lighter);
+ border: 1px solid var(--el-border-color-lighter);
+}
+
+.fce-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ gap: 12px;
+ margin-bottom: 16px;
+}
+
+.fce-toolbar-left {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.fce-title {
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+}
+
+.fce-toolbar-actions {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+.import-tag {
+ margin-left: 8px;
+ vertical-align: middle;
+}
+
+.fce-empty {
+ padding: 24px 0;
+}
+
+.fce-list {
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+}
+
+.fce-card {
+ position: relative;
+ padding: 16px 16px 12px;
+ border-radius: 12px;
+ background: var(--el-bg-color);
+ border: 1px solid var(--el-border-color-lighter);
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
+ transition: border-color 0.2s, box-shadow 0.2s;
+}
+
+.fce-card:hover {
+ border-color: var(--el-color-primary-light-5);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
+}
+
+.fce-card--required {
+ border-left: 3px solid var(--el-color-danger-light-3);
+}
+
+.fce-card--locked {
+ background: var(--el-fill-color-light);
+}
+
+.fce-card-badge {
+ position: absolute;
+ top: -10px;
+ left: 16px;
+ min-width: 22px;
+ height: 22px;
+ padding: 0 6px;
+ border-radius: 11px;
+ background: var(--el-color-primary);
+ color: #fff;
+ font-size: 12px;
+ font-weight: 700;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 2px 6px rgba(var(--el-color-primary-rgb), 0.35);
+}
+
+.fce-card-head {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 14px;
+ padding-top: 4px;
+}
+
+.fce-card-title {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 8px;
+ min-width: 0;
+}
+
+.fce-card-name {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+}
+
+.fce-card-btns {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ flex-shrink: 0;
+}
+
+.fce-section {
+ margin-bottom: 12px;
+ padding-bottom: 12px;
+ border-bottom: 1px dashed var(--el-border-color-extra-light);
+}
+
+.fce-section:last-child {
+ margin-bottom: 0;
+ padding-bottom: 0;
+ border-bottom: none;
+}
+
+.fce-section-title {
+ display: block;
+ font-size: 12px;
+ font-weight: 600;
+ color: var(--el-text-color-secondary);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ margin-bottom: 10px;
+}
+
+.fce-section-desc {
+ margin: -6px 0 10px;
+ font-size: 12px;
+ color: var(--el-text-color-placeholder);
+ line-height: 1.5;
+}
+
+.fce-section--default {
+ padding: 12px 14px;
+ border-radius: 8px;
+ background: var(--el-fill-color-lighter);
+ border-bottom: none;
+ margin-bottom: 0;
+}
+
+.fce-section--default .fce-section-title {
+ margin-bottom: 4px;
+ color: var(--el-color-primary);
+ text-transform: none;
+ letter-spacing: 0;
+ font-size: 13px;
+}
+
+.fce-section--options {
+ padding-top: 4px;
+ border-bottom: none;
+ margin-bottom: 0;
+}
+
+.fce-field-item {
+ margin-bottom: 0;
+}
+
+.fce-field-item :deep(.el-form-item__label) {
+ font-size: 13px;
+ color: var(--el-text-color-regular);
+}
+
+.fce-field-item--switch :deep(.el-form-item__content) {
+ line-height: 32px;
+}
+
+.fce-options-head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 10px;
+}
+
+.fce-options-head .fce-section-title,
+.fce-options-head .fce-section-subtitle {
+ margin-bottom: 0;
+}
+
+.fce-section-subtitle {
+ font-size: 12px;
+ font-weight: 600;
+ color: var(--el-text-color-secondary);
+}
+
+.fce-source-row {
+ margin-bottom: 4px;
+}
+
+.fce-source-tip {
+ margin: 0 0 10px;
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ line-height: 1.5;
+}
+
+.fce-option-row {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 8px;
+ padding: 8px 10px;
+ border-radius: 8px;
+ background: var(--el-fill-color-lighter);
+}
+
+.fce-option-row:last-child {
+ margin-bottom: 0;
+}
+
+.fce-option-index {
+ flex-shrink: 0;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ background: var(--el-color-info-light-8);
+ color: var(--el-text-color-secondary);
+ font-size: 11px;
+ font-weight: 600;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.fce-option-value {
+ width: 140px;
+ flex-shrink: 0;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/components/TemplateFlowEditor.vue b/src/views/officeProcessAutomation/ApproveManage/approve-template/components/TemplateFlowEditor.vue
new file mode 100644
index 0000000..78304ea
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/components/TemplateFlowEditor.vue
@@ -0,0 +1,399 @@
+<!-- 瀹℃壒妯℃澘锛氬彲閰嶇疆鑺傜偣鏁帮紝姣忚妭鐐瑰浜� + 浼氱/鎴栫 -->
+<template>
+ <div class="tfe">
+ <div v-if="innerList.length" class="tfe-flow">
+ <div v-for="(item, index) in innerList" :key="item._uid" class="tfe-flow-item">
+ <div class="tfe-card" :class="{ 'tfe-card--empty': !item.approvers?.length }">
+ <div class="tfe-badge">{{ index + 1 }}</div>
+ <div class="tfe-head">
+ <span class="tfe-level">{{ levelText(index) }}</span>
+ <el-radio-group
+ v-if="!readonly"
+ v-model="item.signMode"
+ size="small"
+ @change="emitOut"
+ >
+ <el-radio-button value="countersign">浼氱</el-radio-button>
+ <el-radio-button value="or_sign">鎴栫</el-radio-button>
+ </el-radio-group>
+ <el-tag v-else size="small" type="info" effect="plain">
+ {{ signModeLabel(item.signMode) }}
+ </el-tag>
+ </div>
+ <p class="tfe-mode-tip">{{ signModeTip(item.signMode) }}</p>
+ <div v-if="!readonly" class="tfe-select">
+ <el-select
+ v-model="item.approverIds"
+ multiple
+ collapse-tags
+ collapse-tags-tooltip
+ :max-collapse-tags="2"
+ filterable
+ placeholder="璇烽�夋嫨瀹℃壒浜猴紙鍙閫夛級"
+ style="width: 100%"
+ @change="(ids) => onApproversChange(ids, item)"
+ >
+ <el-option
+ v-for="u in userOptions"
+ :key="String(u.userId ?? u.id)"
+ :label="optionLabel(u)"
+ :value="u.userId ?? u.id"
+ />
+ </el-select>
+ </div>
+ <div v-if="item.approvers?.length" class="tfe-chips" :class="{ 'tfe-chips--readonly': readonly }">
+ <el-tag
+ v-for="a in item.approvers"
+ :key="String(a.approverId)"
+ size="small"
+ type="info"
+ effect="plain"
+ >
+ {{ a.approverName || "鈥�" }}
+ </el-tag>
+ </div>
+ <div v-if="!readonly" class="tfe-actions">
+ <el-button type="primary" circle size="small" :disabled="index === 0" title="鍓嶇Щ" @click="moveLeft(index)">
+ <el-icon><ArrowLeft /></el-icon>
+ </el-button>
+ <el-button
+ type="primary"
+ circle
+ size="small"
+ :disabled="index === innerList.length - 1"
+ title="鍚庣Щ"
+ @click="moveRight(index)"
+ >
+ <el-icon><ArrowRight /></el-icon>
+ </el-button>
+ <el-button type="danger" circle size="small" title="鍒犻櫎鑺傜偣" @click="remove(index)">
+ <el-icon><Delete /></el-icon>
+ </el-button>
+ </div>
+ <p v-else-if="!item.approvers?.length" class="tfe-empty-approver">鏆傛棤瀹℃壒浜�</p>
+ </div>
+ <div v-if="index < innerList.length - 1" class="tfe-conn">
+ <div class="tfe-conn-line"></div>
+ <el-icon class="tfe-conn-icon"><ArrowRight /></el-icon>
+ </div>
+ </div>
+
+ <div v-if="!readonly" class="tfe-add-wrap">
+ <div v-if="innerList.length" class="tfe-conn">
+ <div class="tfe-conn-line"></div>
+ <el-icon class="tfe-conn-icon"><ArrowRight /></el-icon>
+ </div>
+ <div class="tfe-add-card" @click="addNode">
+ <div class="tfe-add-icon"><el-icon :size="26"><Plus /></el-icon></div>
+ <span>鏂板鑺傜偣</span>
+ </div>
+ </div>
+ </div>
+
+ <div v-else class="tfe-empty">
+ <el-icon :size="44" color="#c0c4cc"><User /></el-icon>
+ <p>鏆傛棤瀹℃壒鑺傜偣</p>
+ <el-button v-if="!readonly" type="primary" @click="addNode">娣诲姞绗竴涓妭鐐�</el-button>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ArrowLeft, ArrowRight, Delete, Plus, User } from "@element-plus/icons-vue";
+import { ref, watch } from "vue";
+import { NODE_SIGN_MODE_OPTIONS, normalizeFlowNodes } from "../approveTemplateConstants.js";
+
+const props = defineProps({
+ modelValue: { type: Array, default: () => [] },
+ userOptions: { type: Array, default: () => [] },
+ /** 閫夋嫨妯℃澘鍚庣敵璇峰満鏅細浠呭睍绀猴紝涓嶅彲鏀瑰鎵逛汉/鑺傜偣 */
+ readonly: { type: Boolean, default: false },
+});
+
+const emit = defineEmits(["update:modelValue"]);
+
+const innerList = ref([]);
+
+function signModeTip(mode) {
+ return NODE_SIGN_MODE_OPTIONS.find((x) => x.value === mode)?.desc || "";
+}
+
+function signModeLabel(mode) {
+ return (
+ NODE_SIGN_MODE_OPTIONS.find((x) => x.value === mode)?.label ||
+ (mode === "or_sign" ? "鎴栫" : "浼氱")
+ );
+}
+
+function levelText(i) {
+ const t = ["绗竴绾�", "绗簩绾�", "绗笁绾�", "绗洓绾�", "绗簲绾�", "绗叚绾�", "绗竷绾�", "绗叓绾�"];
+ return t[i] || `绗�${i + 1}绾;
+}
+
+function optionLabel(u) {
+ const nick = u.nickName || "";
+ const un = u.userName || "";
+ if (nick && un && nick !== un) return `${nick}锛�${un}锛塦;
+ return nick || un || `鐢ㄦ埛${u.userId ?? u.id ?? ""}`;
+}
+
+function newUid() {
+ return `n_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
+}
+
+function mapIn(rows) {
+ const normalized = normalizeFlowNodes(rows);
+ return normalized.map((n) => ({
+ _uid: newUid(),
+ id: n.id,
+ templateId: n.templateId,
+ nodeOrder: n.nodeOrder,
+ signMode: n.signMode,
+ approverIds: n.approvers.map((a) => a.approverId),
+ approvers: [...n.approvers],
+ }));
+}
+
+function publicShape(rows) {
+ return normalizeFlowNodes(
+ (rows || []).map((r) => ({
+ id: r.id,
+ templateId: r.templateId,
+ nodeOrder: r.nodeOrder,
+ signMode: r.signMode,
+ approvers: r.approvers || [],
+ }))
+ );
+}
+
+function emitOut() {
+ emit("update:modelValue", publicShape(innerList.value));
+}
+
+watch(
+ () => props.modelValue,
+ (v) => {
+ const next = publicShape(v || []);
+ if (JSON.stringify(next) === JSON.stringify(publicShape(innerList.value))) return;
+ innerList.value = mapIn(v || []);
+ },
+ { deep: true, immediate: true }
+);
+
+function findUser(id) {
+ if (id == null || id === "") return null;
+ return props.userOptions.find((u) => String(u.userId ?? u.id) === String(id)) ?? null;
+}
+
+function onApproversChange(ids, row) {
+ const idList = Array.isArray(ids) ? ids : [];
+ const prevById = new Map((row.approvers || []).map((a) => [String(a.approverId), a]));
+ row.approverIds = idList;
+ row.approvers = idList.map((id) => {
+ const prev = prevById.get(String(id));
+ const u = findUser(id);
+ const item = {
+ approverId: id,
+ approverName: u ? u.nickName || u.userName || "" : prev?.approverName || "",
+ };
+ if (prev?.id != null) item.id = prev.id;
+ if (prev?.nodeId != null) item.nodeId = prev.nodeId;
+ else if (row.id != null) item.nodeId = row.id;
+ if (prev?.templateId != null) item.templateId = prev.templateId;
+ else if (row.templateId != null) item.templateId = row.templateId;
+ return item;
+ });
+ emitOut();
+}
+
+function addNode() {
+ if (props.readonly) return;
+ innerList.value.push({
+ _uid: newUid(),
+ nodeOrder: innerList.value.length + 1,
+ signMode: "countersign",
+ approverIds: [],
+ approvers: [],
+ });
+ emitOut();
+}
+
+function remove(index) {
+ if (props.readonly) return;
+ innerList.value.splice(index, 1);
+ emitOut();
+}
+
+function moveLeft(index) {
+ if (props.readonly) return;
+ if (index < 1) return;
+ const t = innerList.value[index];
+ innerList.value[index] = innerList.value[index - 1];
+ innerList.value[index - 1] = t;
+ emitOut();
+}
+
+function moveRight(index) {
+ if (props.readonly) return;
+ if (index >= innerList.value.length - 1) return;
+ const t = innerList.value[index];
+ innerList.value[index] = innerList.value[index + 1];
+ innerList.value[index + 1] = t;
+ emitOut();
+}
+</script>
+
+<style scoped>
+.tfe {
+ width: 100%;
+}
+.tfe-flow {
+ display: flex;
+ align-items: flex-start;
+ flex-wrap: nowrap;
+ overflow-x: auto;
+ padding: 6px 0 10px;
+}
+.tfe-flow-item {
+ display: flex;
+ align-items: center;
+}
+.tfe-card {
+ width: 248px;
+ flex-shrink: 0;
+ border: 2px solid var(--el-border-color);
+ border-radius: 12px;
+ padding: 14px 12px 12px;
+ position: relative;
+ background: var(--el-bg-color);
+}
+.tfe-card--empty {
+ border-style: dashed;
+ background: var(--el-fill-color-lighter);
+}
+.tfe-badge {
+ position: absolute;
+ top: -8px;
+ left: 12px;
+ width: 22px;
+ height: 22px;
+ border-radius: 50%;
+ background: var(--el-color-primary);
+ color: #fff;
+ font-size: 12px;
+ font-weight: 700;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.tfe-head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ margin: 8px 0 4px;
+}
+.tfe-level {
+ font-size: 13px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+}
+.tfe-mode-tip {
+ font-size: 11px;
+ color: var(--el-text-color-secondary);
+ margin: 0 0 10px;
+ line-height: 1.4;
+ min-height: 30px;
+}
+.tfe-select {
+ margin-bottom: 8px;
+}
+.tfe-chips {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ margin-bottom: 8px;
+ min-height: 24px;
+}
+.tfe-chips--readonly {
+ margin-top: 4px;
+ margin-bottom: 0;
+}
+.tfe-empty-approver {
+ font-size: 12px;
+ color: var(--el-text-color-placeholder);
+ margin: 4px 0 0;
+}
+.tfe-actions {
+ display: flex;
+ justify-content: center;
+ gap: 8px;
+ padding-top: 10px;
+ border-top: 1px solid var(--el-border-color-lighter);
+}
+.tfe-conn {
+ display: flex;
+ align-items: center;
+ width: 40px;
+ flex-shrink: 0;
+ align-self: center;
+}
+.tfe-conn-line {
+ flex: 1;
+ height: 2px;
+ background: var(--el-border-color);
+}
+.tfe-conn-icon {
+ font-size: 14px;
+ color: var(--el-text-color-placeholder);
+ margin-left: -2px;
+}
+.tfe-add-wrap {
+ display: flex;
+ align-items: center;
+}
+.tfe-add-card {
+ width: 120px;
+ min-height: 200px;
+ flex-shrink: 0;
+ border: 2px dashed var(--el-border-color);
+ border-radius: 12px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
+ cursor: pointer;
+ color: var(--el-text-color-regular);
+ font-size: 13px;
+ background: var(--el-fill-color-lighter);
+ transition: border-color 0.2s, background 0.2s;
+}
+.tfe-add-card:hover {
+ border-color: var(--el-color-primary);
+ background: var(--el-color-primary-light-9);
+ color: var(--el-color-primary);
+}
+.tfe-add-icon {
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ background: var(--el-color-primary);
+ color: #fff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.tfe-empty {
+ text-align: center;
+ padding: 28px 16px;
+ border: 1px dashed var(--el-border-color);
+ border-radius: 12px;
+ background: var(--el-fill-color-lighter);
+}
+.tfe-empty p {
+ margin: 10px 0 14px;
+ color: var(--el-text-color-secondary);
+ font-size: 14px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js
new file mode 100644
index 0000000..c1f66bd
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js
@@ -0,0 +1,301 @@
+import { mapAttachmentsFromApi } from "./approveTemplateConstants.js";
+import {
+ isDynamicOptionSource,
+ SELECT_OPTION_SOURCE,
+ selectOptionSourceLabel,
+} from "./selectOptionSource.js";
+
+export { selectOptionSourceLabel };
+
+/** 濉姤椤圭被鍨嬶紙涓庡鎵规彁浜ら〉 field.type 涓�鑷达級 */
+export const FORM_FIELD_TYPE_OPTIONS = [
+ { value: "text", label: "鍗曡鏂囨湰" },
+ { value: "textarea", label: "澶氳鏂囨湰" },
+ { value: "number", label: "鏁板瓧" },
+ { value: "date", label: "鏃ユ湡" },
+ { value: "datetimerange", label: "鏃ユ湡鏃堕棿鑼冨洿" },
+ { value: "select", label: "涓嬫媺閫夋嫨" },
+];
+
+/** 甯哥敤棰勮锛堝璐圭敤鎶ラ攢锛� */
+export const FORM_CONFIG_PRESETS = [
+ {
+ key: "cost_reimburse",
+ label: "璐圭敤鎶ラ攢",
+ summaryPlaceholder: "璇峰~鍐欐姤閿�浜嬬敱銆侀噾棰濈瓑",
+ fields: [
+ { key: "summary", label: "鎶ラ攢璇存槑", type: "textarea", required: true, rows: 3 },
+ { key: "amount", label: "鎶ラ攢閲戦(鍏�)", type: "number", required: true, min: 0, precision: 2 },
+ ],
+ },
+ {
+ key: "travel_reimburse",
+ label: "宸梾鎶ラ攢",
+ summaryPlaceholder: "鍑哄樊琛岀▼涓庤垂鐢ㄨ鏄�",
+ fields: [
+ { key: "summary", label: "宸梾璇存槑", type: "textarea", required: true, rows: 3 },
+ { key: "amount", label: "鎶ラ攢閲戦(鍏�)", type: "number", required: true, min: 0, precision: 2 },
+ { key: "tripDays", label: "鍑哄樊澶╂暟", type: "number", required: false, min: 0, precision: 0 },
+ ],
+ },
+ {
+ key: "leave",
+ label: "璇峰亣鐢宠",
+ summaryPlaceholder: "璇峰~鍐欒鍋囩被鍨嬩笌鏃堕棿",
+ fields: [
+ {
+ key: "leaveType",
+ label: "璇峰亣绫诲瀷",
+ type: "select",
+ required: true,
+ options: [
+ { label: "骞村亣", value: "annual" },
+ { label: "鐥呭亣", value: "sick" },
+ { label: "浜嬪亣", value: "personal" },
+ { label: "璋冧紤", value: "compensatory" },
+ ],
+ },
+ { key: "summary", label: "璇峰亣浜嬬敱", type: "textarea", required: true, rows: 2 },
+ { key: "dateRange", label: "璇峰亣鏃堕棿", type: "datetimerange", required: true },
+ ],
+ },
+];
+
+function newFieldUid() {
+ return `f_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
+}
+
+export function createEmptyFormField() {
+ return {
+ _uid: newFieldUid(),
+ key: "",
+ label: "",
+ type: "text",
+ required: true,
+ rows: 3,
+ min: 0,
+ precision: 0,
+ defaultValue: "",
+ optionSource: SELECT_OPTION_SOURCE.STATIC,
+ options: [{ label: "", value: "" }],
+ };
+}
+
+/** 瑙f瀽鍗曢」榛樿鍊硷紙渚涙彁浜ら〉 formPayload 鍒濆鍖栵級 */
+export function resolveFieldDefaultValue(field) {
+ const type = field?.type || "text";
+ const dv = field?.defaultValue;
+ if (dv === undefined || dv === null || dv === "") {
+ if (type === "number") return undefined;
+ if (type === "datetimerange") return [];
+ return "";
+ }
+ if (type === "number") {
+ const n = Number(dv);
+ return Number.isNaN(n) ? undefined : n;
+ }
+ if (type === "datetimerange") {
+ return Array.isArray(dv) ? [...dv] : [];
+ }
+ return dv;
+}
+
+function hasDefaultValue(field) {
+ const type = field?.type || "text";
+ const dv = field?.defaultValue;
+ if (dv === undefined || dv === null) return false;
+ if (type === "number") return dv !== "" && !Number.isNaN(Number(dv));
+ if (type === "datetimerange") return Array.isArray(dv) && dv.length === 2;
+ if (type === "select") return dv !== "";
+ return String(dv).trim() !== "";
+}
+
+/** 鏍规嵁瀛楁瀹氫箟鐢熸垚 formPayload 鍒濆鍊硷紙鍚粯璁ゅ�硷級 */
+export function buildFormPayloadFromFields(fields) {
+ const payload = {};
+ (fields || []).forEach((f) => {
+ const key = (f.key || "").trim();
+ if (!key) return;
+ payload[key] = resolveFieldDefaultValue(f);
+ });
+ return payload;
+}
+
+export function createEmptyFormConfigData() {
+ return {
+ summaryPlaceholder: "",
+ fields: [],
+ };
+}
+
+function parseFormConfigRaw(formConfig) {
+ if (!formConfig) return {};
+ if (typeof formConfig === "object") return formConfig;
+ try {
+ return JSON.parse(formConfig);
+ } catch {
+ return {};
+ }
+}
+
+function normalizeDefaultValueFromApi(f) {
+ const type = f.type || "text";
+ if (f.defaultValue === undefined || f.defaultValue === null) {
+ if (type === "number") return undefined;
+ if (type === "datetimerange") return [];
+ return "";
+ }
+ if (type === "datetimerange" && Array.isArray(f.defaultValue)) {
+ return [...f.defaultValue];
+ }
+ return f.defaultValue;
+}
+
+/** 鎺ュ彛 formConfig 鈫� 缂栬緫鍣ㄦ暟鎹� */
+export function parseFormConfigToData(formConfig) {
+ const raw = parseFormConfigRaw(formConfig);
+ const fields = (raw.fields || raw.formFields || []).map((f) => ({
+ _uid: newFieldUid(),
+ key: f.key || "",
+ label: f.label || "",
+ type: f.type || "text",
+ required: f.required !== false,
+ rows: f.rows ?? 3,
+ min: f.min ?? 0,
+ precision: f.precision ?? 0,
+ defaultValue: normalizeDefaultValueFromApi(f),
+ optionSource: f.optionSource || SELECT_OPTION_SOURCE.STATIC,
+ options: (f.options || []).length
+ ? f.options.map((o) => ({ label: o.label || "", value: o.value ?? "" }))
+ : [{ label: "", value: "" }],
+ }));
+ return {
+ summaryPlaceholder: raw.summaryPlaceholder || "",
+ fields,
+ };
+}
+
+/** 缂栬緫鍣ㄦ暟鎹� 鈫� 鎻愪氦鐢� JSON 瀛楃涓� */
+export function buildFormConfigJson(formConfigData) {
+ const data = formConfigData || createEmptyFormConfigData();
+ const fields = (data.fields || []).map((f) => {
+ const item = {
+ key: (f.key || "").trim(),
+ label: (f.label || "").trim(),
+ type: f.type || "text",
+ required: f.required !== false,
+ };
+ if (item.type === "textarea") item.rows = Number(f.rows) || 3;
+ if (item.type === "number") {
+ item.min = f.min ?? 0;
+ item.precision = f.precision ?? 0;
+ }
+ if (item.type === "select") {
+ const source = f.optionSource || SELECT_OPTION_SOURCE.STATIC;
+ item.optionSource = source;
+ if (!isDynamicOptionSource(source)) {
+ item.options = (f.options || [])
+ .filter((o) => (o.label || "").trim() || (o.value !== "" && o.value != null))
+ .map((o) => ({ label: (o.label || "").trim(), value: o.value }));
+ }
+ }
+ if (hasDefaultValue(f)) {
+ item.defaultValue =
+ f.type === "datetimerange" && Array.isArray(f.defaultValue)
+ ? f.defaultValue
+ : f.defaultValue;
+ }
+ return item;
+ });
+ const payload = {
+ summaryPlaceholder: (data.summaryPlaceholder || "").trim(),
+ fields,
+ };
+ return JSON.stringify(payload);
+}
+
+export function applyFormConfigPreset(presetKey) {
+ const preset = FORM_CONFIG_PRESETS.find((p) => p.key === presetKey);
+ if (!preset) return createEmptyFormConfigData();
+ return parseFormConfigToData({
+ summaryPlaceholder: preset.summaryPlaceholder,
+ fields: preset.fields,
+ });
+}
+
+export function validateFormConfigData(formConfigData) {
+ const fields = formConfigData?.fields || [];
+ if (!fields.length) {
+ return { ok: true };
+ }
+ const keys = new Set();
+ for (let i = 0; i < fields.length; i++) {
+ const f = fields[i];
+ const key = (f.key || "").trim();
+ const label = (f.label || "").trim();
+ if (!key) return { ok: false, message: `璇峰~鍐欑 ${i + 1} 涓~鎶ラ」鐨勫瓧娈垫爣璇哷 };
+ if (!label) return { ok: false, message: `璇峰~鍐欑 ${i + 1} 涓~鎶ラ」鐨勬樉绀哄悕绉癭 };
+ if (keys.has(key)) return { ok: false, message: `瀛楁鏍囪瘑銆�${key}銆嶉噸澶嶏紝璇蜂慨鏀筦 };
+ keys.add(key);
+ if (f.type === "select") {
+ const source = f.optionSource || SELECT_OPTION_SOURCE.STATIC;
+ if (isDynamicOptionSource(source)) continue;
+ const opts = (f.options || []).filter((o) => (o.label || "").trim() && o.value !== "" && o.value != null);
+ if (!opts.length) return { ok: false, message: `璇蜂负銆�${label}銆嶉厤缃嚦灏戜竴涓笅鎷夐�夐」` };
+ }
+ }
+ return { ok: true };
+}
+
+export function formFieldTypeLabel(type) {
+ return FORM_FIELD_TYPE_OPTIONS.find((x) => x.value === type)?.label || type || "鈥�";
+}
+
+export function formatDefaultValueDisplay(field) {
+ const dv = field?.defaultValue;
+ if (dv === undefined || dv === null || dv === "") return "鈥�";
+ if (field?.type === "datetimerange" && Array.isArray(dv)) {
+ return dv.length === 2 ? `${dv[0]} ~ ${dv[1]}` : "鈥�";
+ }
+ if (field?.type === "select") {
+ if (isDynamicOptionSource(field.optionSource)) {
+ return `${selectOptionSourceLabel(field.optionSource)}锛�${String(dv)}`;
+ }
+ const opt = (field.options || []).find((o) => String(o.value) === String(dv));
+ return opt?.label || String(dv);
+ }
+ return String(dv);
+}
+
+/** 灏嗗悗绔ā鏉胯杞负鎻愪氦椤垫ā鏉跨粨鏋勶紙鍚� fields 榛樿鍊笺�侀檮浠讹級 */
+export function buildSubmitTemplateFromRow(row) {
+ const cfg = parseFormConfigToData(row?.formConfig);
+ const fields = (cfg.fields || []).map(({ _uid, ...rest }) => ({
+ ...rest,
+ key: rest.key,
+ label: rest.label,
+ type: rest.type,
+ required: rest.required,
+ rows: rest.rows,
+ min: rest.min,
+ precision: rest.precision,
+ defaultValue: rest.defaultValue,
+ optionSource: rest.optionSource,
+ options: rest.options,
+ }));
+ return {
+ label: row?.templateName || "瀹℃壒",
+ businessType: row?.businessType ?? cfg.approvalType ?? "",
+ approvalType: cfg.approvalType || "",
+ summaryPlaceholder: cfg.summaryPlaceholder || "",
+ approvalMode: cfg.approvalMode || "parallel",
+ fields,
+ storageBlobDTOs: mapAttachmentsFromApi(row),
+ };
+}
+
+export function formConfigFieldsSummary(formConfigData) {
+ const fields = formConfigData?.fields || [];
+ if (!fields.length) return "鈥�";
+ return fields.map((f) => f.label || f.key || "鏈懡鍚�").join("銆�");
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/index.vue b/src/views/officeProcessAutomation/ApproveManage/approve-template/index.vue
new file mode 100644
index 0000000..d094c13
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/index.vue
@@ -0,0 +1,819 @@
+<!--OA妯″潡锛氬鎵规ā鏉�-->
+
+<template>
+
+ <div class="app-container approve-template-page">
+
+ <div class="search_form mb20">
+
+ <div class="search_fields">
+
+ <span class="search_title">妯℃澘鍚嶇О锛�</span>
+
+ <el-input
+
+ v-model="searchForm.keyword"
+
+ style="width: 220px"
+
+ placeholder="鎼滅储鍚嶇О鎴栬鏄�"
+
+ clearable
+
+ :prefix-icon="Search"
+
+ @keyup.enter="handleQuery"
+
+ />
+
+ <el-checkbox v-model="searchForm.enabledOnly" class="ml12" @change="handleQuery">
+
+ 浠呮樉绀哄惎鐢�
+
+ </el-checkbox>
+
+ <el-button type="primary" :icon="Search" class="ml10" @click="handleQuery">鎼滅储</el-button>
+
+ <el-button :icon="RefreshRight" @click="resetSearch">閲嶇疆</el-button>
+
+ </div>
+
+ <div class="search_actions">
+
+ <el-button type="primary" :icon="Plus" @click="openFormDialog('add')">鏂板缓妯℃澘</el-button>
+
+ </div>
+
+ </div>
+
+
+
+ <div class="table_list">
+
+ <PIMTable
+
+ rowKey="id"
+
+ :column="tableColumn"
+
+ :tableData="tableData"
+
+ :page="page"
+
+ :isSelection="false"
+
+ :tableLoading="tableLoading"
+
+ :total="page.total"
+
+ @pagination="pagination"
+
+ />
+
+ </div>
+
+
+
+ <!-- 鏂板缓 / 缂栬緫 -->
+
+ <el-dialog
+
+ v-model="formDialog.visible"
+
+ :title="formDialog.title"
+
+ width="1020px"
+
+ append-to-body
+
+ destroy-on-close
+
+ class="template-form-dialog"
+
+ @closed="onFormDialogClosed"
+
+ >
+
+ <el-form
+
+ v-if="formDialog.visible"
+
+ ref="formRef"
+
+ :model="form"
+
+ :rules="formRules"
+
+ label-width="100px"
+
+ >
+
+ <el-row :gutter="20">
+
+ <el-col :span="8">
+
+ <el-form-item label="妯℃澘鍚嶇О" prop="templateName">
+
+ <el-input
+ v-model="form.templateName"
+ placeholder="濡傦細椤圭洰绔嬮」瀹℃壒"
+ maxlength="50"
+ show-word-limit
+ :disabled="isEditingBuiltin"
+ />
+
+ </el-form-item>
+
+ </el-col>
+
+ <el-col :span="8">
+
+ <el-form-item label="妯℃澘绫诲瀷" prop="businessType">
+
+ <el-select
+ v-model="form.businessType"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ :disabled="isEditingBuiltin"
+ >
+
+ <el-option
+
+ v-for="opt in templateTypeOptions"
+
+ :key="`tpl-type-${opt.value}`"
+
+ :label="opt.label"
+
+ :value="opt.value"
+
+ />
+
+ </el-select>
+
+ </el-form-item>
+
+ </el-col>
+
+ <el-col :span="8">
+
+ <el-form-item label="鍚敤鐘舵��">
+
+ <el-switch v-model="form.enabled" active-text="鍚敤" inactive-text="鍋滅敤" />
+
+ </el-form-item>
+
+ </el-col>
+
+ </el-row>
+
+ <el-form-item label="妯℃澘璇存槑">
+
+ <el-input
+
+ v-model="form.description"
+
+ type="textarea"
+
+ :rows="2"
+
+ placeholder="绠�瑕佽鏄庤妯℃澘鐨勯�傜敤鍦烘櫙"
+
+ maxlength="200"
+
+ show-word-limit
+
+ />
+
+ </el-form-item>
+
+ <el-form-item label="濉姤閰嶇疆">
+
+ <FormConfigEditor
+ v-model="form.formConfigData"
+ :exclude-template-id="form.id"
+ :disable-import="isEditingBuiltin"
+ :locked-field-uids="isEditingBuiltin ? form.lockedFormFieldUids : []"
+ />
+
+ <p class="flow-tip">閰嶇疆鎻愪氦瀹℃壒鏃堕渶濉啓鐨勮〃鍗曢」锛屼繚瀛樺悗鍐欏叆 formConfig锛圝SON锛夈��</p>
+
+ </el-form-item>
+
+ <el-form-item label="瀹℃壒娴佺▼" required>
+
+ <TemplateFlowEditor v-model="form.flowNodes" :user-options="flowUserOptions" />
+
+ <p class="flow-tip">
+
+ 鎸夐『搴忔祦杞細鍙负姣忎釜鑺傜偣娣诲姞澶氬悕瀹℃壒浜猴紱浼氱闇�鍏ㄩ儴閫氳繃锛屾垨绛句换涓�浜洪�氳繃鍗冲彲杩涘叆涓嬩竴鑺傜偣銆�
+
+ </p>
+
+ </el-form-item>
+
+ <el-form-item label="闄勪欢">
+
+ <div class="upload-block">
+
+ <FileUpload v-model:file-list="form.storageBlobDTOs" :limit="10" button-text="鐐瑰嚮閫夋嫨鏂囦欢" />
+
+ </div>
+
+ <p class="flow-tip">鍙笂浼犳ā鏉胯鏄庢枃妗c�佸埗搴︽枃浠剁瓑锛堥�夊~锛夈��</p>
+
+ </el-form-item>
+
+ </el-form>
+
+ <template #footer>
+
+ <el-button type="primary" @click="onSubmitForm">淇� 瀛�</el-button>
+
+ <el-button @click="formDialog.visible = false">鍙� 娑�</el-button>
+
+ </template>
+
+ </el-dialog>
+
+
+
+ <!-- 璇︽儏 -->
+
+ <el-dialog v-model="detailDialog.visible" title="妯℃澘璇︽儏" width="880px" append-to-body destroy-on-close>
+
+ <div v-loading="detailLoading" class="detail-dialog-body">
+
+ <el-descriptions :column="2" border>
+
+ <el-descriptions-item label="妯℃澘鍚嶇О">{{ detailRow.templateName }}</el-descriptions-item>
+
+ <el-descriptions-item label="妯℃澘绫诲瀷">{{ templateTypeLabel(detailRow.businessType) }}</el-descriptions-item>
+
+ <el-descriptions-item label="鐘舵��">
+
+ <el-tag :type="detailRow.enabled !== false ? 'success' : 'info'" size="small">
+
+ {{ detailRow.enabled !== false ? "鍚敤" : "鍋滅敤" }}
+
+ </el-tag>
+
+ </el-descriptions-item>
+
+ <el-descriptions-item label="璇存槑" :span="2">{{ detailRow.description || "鈥�" }}</el-descriptions-item>
+
+ <el-descriptions-item label="濉姤鎻愮ず" :span="2">
+
+ {{ detailFormConfig.summaryPlaceholder || "鈥�" }}
+
+ </el-descriptions-item>
+
+ <el-descriptions-item label="鍒涘缓浜�">{{ detailRow.createdUserName || "鈥�" }}</el-descriptions-item>
+
+ <el-descriptions-item label="鍒涘缓鏃堕棿">{{ formatDisplayTime(detailRow.createdTime) }}</el-descriptions-item>
+
+ <el-descriptions-item label="鏇存柊鏃堕棿">{{ formatDisplayTime(detailRow.updatedTime) }}</el-descriptions-item>
+
+ </el-descriptions>
+
+ <el-divider content-position="left">濉姤椤癸紙{{ detailFormConfig.fields?.length || 0 }} 椤癸級</el-divider>
+
+ <el-table
+
+ v-if="detailFormConfig.fields?.length"
+
+ :data="detailFormConfig.fields"
+
+ border
+
+ size="small"
+
+ class="mb16"
+
+ >
+
+ <el-table-column prop="label" label="鏄剧ず鍚嶇О" min-width="120" />
+
+ <el-table-column prop="key" label="瀛楁鏍囪瘑" min-width="100" />
+
+ <el-table-column label="绫诲瀷" width="100">
+
+ <template #default="{ row }">{{ formFieldTypeLabel(row.type) }}</template>
+
+ </el-table-column>
+
+ <el-table-column label="閫夐」鏉ユ簮" width="100">
+
+ <template #default="{ row }">
+
+ {{ row.type === 'select' ? selectOptionSourceLabel(row.optionSource) : '鈥�' }}
+
+ </template>
+
+ </el-table-column>
+
+ <el-table-column label="蹇呭~" width="70" align="center">
+
+ <template #default="{ row }">{{ row.required !== false ? "鏄�" : "鍚�" }}</template>
+
+ </el-table-column>
+
+ <el-table-column label="榛樿鍊�" min-width="120" show-overflow-tooltip>
+
+ <template #default="{ row }">{{ formatDefaultValueDisplay(row) }}</template>
+
+ </el-table-column>
+
+ </el-table>
+
+ <el-empty v-else description="鏈厤缃~鎶ラ」" :image-size="48" class="mb16" />
+
+ <el-divider content-position="left">瀹℃壒娴佺▼锛坽{ detailRow.flowNodes?.length || 0 }} 涓妭鐐癸級</el-divider>
+
+ <div v-if="detailRow.flowNodes?.length" class="detail-flow">
+
+ <div v-for="(node, index) in detailRow.flowNodes" :key="index" class="detail-node">
+
+ <div class="detail-node-head">
+
+ <span class="detail-node-order">鑺傜偣 {{ index + 1 }}</span>
+
+ <el-tag size="small" :type="node.signMode === 'or_sign' ? 'warning' : 'primary'">
+
+ {{ nodeSignModeLabel(node.signMode) }}
+
+ </el-tag>
+
+ </div>
+
+ <div class="detail-approvers">
+
+ <el-tag
+
+ v-for="a in node.approvers"
+
+ :key="String(a.approverId)"
+
+ class="detail-approver-tag"
+
+ effect="plain"
+
+ >
+
+ {{ a.approverName || "鈥�" }}
+
+ </el-tag>
+
+ <span v-if="!node.approvers?.length" class="text-muted">鏈厤缃鎵逛汉</span>
+
+ </div>
+
+ <el-icon v-if="index < detailRow.flowNodes.length - 1" class="detail-arrow"><ArrowRight /></el-icon>
+
+ </div>
+
+ </div>
+
+ <el-empty v-else description="鏆傛棤娴佺▼鑺傜偣" :image-size="60" />
+
+ <el-divider content-position="left">闄勪欢锛坽{ detailAttachments.length }} 涓級</el-divider>
+
+ <template v-if="detailAttachments.length">
+
+ <el-tag
+
+ v-for="(f, i) in detailAttachments"
+
+ :key="i"
+
+ class="detail-attachment-tag"
+
+ type="info"
+
+ effect="plain"
+
+ >
+
+ {{ attachmentDisplayName(f) }}
+
+ </el-tag>
+
+ </template>
+
+ <el-empty v-else description="鏆傛棤闄勪欢" :image-size="48" />
+
+ </div>
+
+ <template #footer>
+
+ <el-button @click="detailDialog.visible = false">鍏� 闂�</el-button>
+
+ <el-button type="primary" @click="editFromDetail">缂� 杈�</el-button>
+
+ </template>
+
+ </el-dialog>
+
+ </div>
+
+</template>
+
+
+
+<script setup>
+
+import { ArrowRight, Plus, RefreshRight } from "@element-plus/icons-vue";
+
+import { ElMessage } from "element-plus";
+
+import { computed, nextTick, onMounted, ref } from "vue";
+
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+
+import FormConfigEditor from "./components/FormConfigEditor.vue";
+
+import TemplateFlowEditor from "./components/TemplateFlowEditor.vue";
+
+import { formatDisplayTime, mapAttachmentsFromApi } from "./approveTemplateConstants.js";
+
+import { formatDefaultValueDisplay, formFieldTypeLabel, parseFormConfigToData } from "./formConfigUtils.js";
+import { selectOptionSourceLabel } from "./selectOptionSource.js";
+
+import { useApproveTemplate } from "./useApproveTemplate.js";
+
+
+
+const {
+
+ Search,
+
+ templateTypeOptions,
+
+ loadTemplateTypeOptions,
+
+ templateTypeLabel,
+
+ nodeSignModeLabel,
+
+ searchForm,
+
+ tableLoading,
+
+ page,
+
+ tableData,
+
+ tableColumn,
+
+ formDialog,
+
+ form,
+
+ formRef,
+
+ formRules,
+
+ isEditingBuiltin,
+
+ detailDialog,
+
+ detailRow,
+
+ detailLoading,
+
+ fetchTemplateList,
+
+ handleQuery,
+
+ resetSearch,
+
+ pagination,
+
+ openFormDialog,
+
+ openDetail,
+
+ submitForm,
+
+} = useApproveTemplate();
+
+
+
+const flowUserOptions = ref([]);
+
+
+
+const detailFormConfig = computed(() =>
+
+ parseFormConfigToData(detailRow.value?.formConfigData ?? detailRow.value?.formConfig)
+
+);
+
+
+
+const detailAttachments = computed(() => mapAttachmentsFromApi(detailRow.value));
+
+
+
+function attachmentDisplayName(file) {
+
+ if (!file) return "鏈懡鍚�";
+
+ return file.name || file.originalFilename || file.fileName || "鏈懡鍚�";
+
+}
+
+
+
+function unwrapArray(payload) {
+
+ if (Array.isArray(payload)) return payload;
+
+ if (payload?.data && Array.isArray(payload.data)) return payload.data;
+
+ if (payload?.rows && Array.isArray(payload.rows)) return payload.rows;
+
+ return [];
+
+}
+
+
+
+function isActiveUser(u) {
+
+ if (u.delFlag === "2" || u.delFlag === 2) return false;
+
+ if (u.status == null) return true;
+
+ return String(u.status) === "0";
+
+}
+
+
+
+async function loadUsers() {
+
+ try {
+
+ const res = await userListNoPageByTenantId();
+
+ flowUserOptions.value = unwrapArray(res).filter(isActiveUser);
+
+ } catch {
+
+ flowUserOptions.value = [];
+
+ }
+
+}
+
+
+
+async function onSubmitForm() {
+
+ const ret = await submitForm();
+
+ if (ret?.message) {
+
+ ElMessage.warning(ret.message);
+
+ return;
+
+ }
+
+ if (ret?.ok) ElMessage.success("淇濆瓨鎴愬姛");
+
+}
+
+
+
+function onFormDialogClosed() {
+
+ formRef.value?.resetFields?.();
+
+}
+
+
+
+async function editFromDetail() {
+
+ const row = detailRow.value;
+
+ detailDialog.visible = false;
+
+ await nextTick();
+
+ openFormDialog("edit", row);
+
+}
+
+
+
+onMounted(() => {
+
+ loadUsers();
+
+ loadTemplateTypeOptions();
+
+ fetchTemplateList();
+
+});
+
+</script>
+
+
+
+<style scoped>
+
+.mb20 {
+
+ margin-bottom: 20px;
+
+}
+
+.mb16 {
+
+ margin-bottom: 16px;
+
+}
+
+.mb16.el-empty {
+
+ padding: 8px 0;
+
+}
+
+.ml10 {
+
+ margin-left: 10px;
+
+}
+
+.ml12 {
+
+ margin-left: 12px;
+
+}
+
+.search_form {
+
+ display: flex;
+
+ flex-wrap: wrap;
+
+ align-items: center;
+
+ justify-content: space-between;
+
+ gap: 12px;
+
+}
+
+.search_fields {
+
+ display: flex;
+
+ flex-wrap: wrap;
+
+ align-items: center;
+
+ gap: 4px;
+
+}
+
+.search_actions {
+
+ display: flex;
+
+ gap: 8px;
+
+}
+
+.flow-tip {
+
+ font-size: 12px;
+
+ color: var(--el-text-color-secondary);
+
+ margin: 8px 0 0;
+
+ line-height: 1.5;
+
+}
+
+.detail-flow {
+
+ display: flex;
+
+ flex-wrap: wrap;
+
+ align-items: flex-start;
+
+ gap: 8px;
+
+}
+
+.detail-node {
+
+ position: relative;
+
+ min-width: 180px;
+
+ max-width: 240px;
+
+ padding: 12px;
+
+ border: 1px solid var(--el-border-color-lighter);
+
+ border-radius: 8px;
+
+ background: var(--el-fill-color-lighter);
+
+}
+
+.detail-node-head {
+
+ display: flex;
+
+ align-items: center;
+
+ justify-content: space-between;
+
+ margin-bottom: 8px;
+
+}
+
+.detail-node-order {
+
+ font-weight: 600;
+
+ font-size: 13px;
+
+}
+
+.detail-approvers {
+
+ display: flex;
+
+ flex-wrap: wrap;
+
+ gap: 4px;
+
+}
+
+.detail-approver-tag {
+
+ margin: 0;
+
+}
+
+.detail-arrow {
+
+ position: absolute;
+
+ right: -20px;
+
+ top: 50%;
+
+ transform: translateY(-50%);
+
+ color: var(--el-text-color-placeholder);
+
+}
+
+.detail-dialog-body {
+
+ min-height: 120px;
+
+}
+
+.upload-block {
+
+ width: 100%;
+
+}
+
+.detail-attachment-tag {
+
+ margin: 0 8px 8px 0;
+
+}
+
+.text-muted {
+
+ font-size: 12px;
+
+ color: var(--el-text-color-placeholder);
+
+}
+
+.template-form-dialog :deep(.el-dialog__body) {
+
+ padding-top: 8px;
+
+}
+
+</style>
+
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/selectOptionSource.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/selectOptionSource.js
new file mode 100644
index 0000000..99706b4
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/selectOptionSource.js
@@ -0,0 +1,140 @@
+import { deptTreeSelect, userListNoPageByTenantId } from "@/api/system/user.js";
+
+/** 涓嬫媺閫夐」鏉ユ簮锛堝啓鍏� formConfig锛屾彁浜ら〉鎸夋潵婧愭媺鍙栨暟鎹級 */
+export const SELECT_OPTION_SOURCE = {
+ STATIC: "static",
+ USER: "user",
+ DEPT: "dept",
+};
+
+export const SELECT_OPTION_SOURCE_OPTIONS = [
+ { value: SELECT_OPTION_SOURCE.STATIC, label: "鎵嬪姩閰嶇疆", desc: "鍦ㄦā鏉夸腑鑷畾涔夐�夐」鏂囨湰涓庡��" },
+ { value: SELECT_OPTION_SOURCE.USER, label: "浜哄憳鍒楄〃", desc: "浠庣郴缁熺敤鎴蜂腑閫夋嫨锛屽�间负鐢ㄦ埛 ID" },
+ { value: SELECT_OPTION_SOURCE.DEPT, label: "閮ㄩ棬鍒楄〃", desc: "浠庣粍缁囨灦鏋勪腑閫夋嫨锛屽�间负閮ㄩ棬 ID" },
+];
+
+export function selectOptionSourceLabel(source) {
+ return SELECT_OPTION_SOURCE_OPTIONS.find((x) => x.value === source)?.label || "鈥�";
+}
+
+export function isDynamicOptionSource(source) {
+ return source === SELECT_OPTION_SOURCE.USER || source === SELECT_OPTION_SOURCE.DEPT;
+}
+
+function unwrapArray(payload) {
+ if (Array.isArray(payload)) return payload;
+ if (payload?.data && Array.isArray(payload.data)) return payload.data;
+ if (payload?.rows && Array.isArray(payload.rows)) return payload.rows;
+ return [];
+}
+
+function isActiveUser(u) {
+ if (u.delFlag === "2" || u.delFlag === 2) return false;
+ if (u.status == null) return true;
+ return String(u.status) === "0";
+}
+
+/** 鐢ㄦ埛 鈫� 涓嬫媺 option */
+export function mapUserToSelectOption(u) {
+ const value = u.userId ?? u.id;
+ return {
+ label: u.nickName || u.userName || `鐢ㄦ埛${value}`,
+ value,
+ };
+}
+
+/** 閮ㄩ棬鏍戞媿骞充负涓嬫媺 option */
+export function flattenDeptToSelectOptions(nodes, result = []) {
+ (nodes || []).forEach((node) => {
+ const value = node.id ?? node.deptId ?? node.value;
+ if (value != null && value !== "") {
+ result.push({
+ label: node.label ?? node.deptName ?? node.name ?? String(value),
+ value,
+ });
+ }
+ if (node.children?.length) flattenDeptToSelectOptions(node.children, result);
+ });
+ return result;
+}
+
+function filterDisabledDept(deptList) {
+ if (!Array.isArray(deptList)) return [];
+ return deptList.filter((dept) => {
+ if (dept.disabled) return false;
+ if (dept.children?.length) {
+ dept.children = filterDisabledDept(dept.children);
+ }
+ return true;
+ });
+}
+
+/** 鎸夊瓧娈甸厤缃В鏋愪笅鎷� options锛堥渶浼犲叆宸插姞杞界殑缂撳瓨锛� */
+export function resolveFieldSelectOptions(field, caches = {}) {
+ const source = field?.optionSource || SELECT_OPTION_SOURCE.STATIC;
+ if (source === SELECT_OPTION_SOURCE.USER) {
+ return (caches.users || []).map(mapUserToSelectOption);
+ }
+ if (source === SELECT_OPTION_SOURCE.DEPT) {
+ return caches.deptOptions || [];
+ }
+ return (field?.options || []).filter((o) => o.value !== "" && o.value != null);
+}
+
+/** 鏍规嵁宸茶В鏋愮殑 options 鍙嶆煡灞曠ず鏂囨湰 */
+export function resolveSelectDisplayLabel(field, val, caches = {}) {
+ if (val == null || val === "") return "鈥�";
+ const options = resolveFieldSelectOptions(field, caches);
+ const hit = options.find((o) => String(o.value) === String(val));
+ return hit?.label || String(val);
+}
+
+/** 鍔犺浇浜哄憳 / 閮ㄩ棬缂撳瓨锛堝澶勫鐢級 */
+export async function fetchSelectOptionCaches(sources = []) {
+ const needUser = sources.includes(SELECT_OPTION_SOURCE.USER);
+ const needDept = sources.includes(SELECT_OPTION_SOURCE.DEPT);
+ const caches = { users: [], deptOptions: [] };
+
+ if (!needUser && !needDept) return caches;
+
+ const tasks = [];
+ if (needUser) {
+ tasks.push(
+ userListNoPageByTenantId()
+ .then((res) => {
+ caches.users = unwrapArray(res).filter(isActiveUser);
+ })
+ .catch(() => {
+ caches.users = [];
+ })
+ );
+ }
+ if (needDept) {
+ tasks.push(
+ deptTreeSelect()
+ .then((res) => {
+ let tree = unwrapArray(res);
+ tree = tree.length ? filterDisabledDept(JSON.parse(JSON.stringify(tree))) : [];
+ if (!tree.length) tree = unwrapArray(res);
+ caches.deptOptions = flattenDeptToSelectOptions(tree);
+ })
+ .catch(() => {
+ caches.deptOptions = [];
+ })
+ );
+ }
+
+ await Promise.all(tasks);
+ return caches;
+}
+
+/** 浠庡瓧娈靛垪琛ㄦ敹闆嗛渶瑕侀鍔犺浇鐨勫姩鎬佹潵婧� */
+export function collectOptionSourcesFromFields(fields) {
+ const set = new Set();
+ (fields || []).forEach((f) => {
+ if (f?.type === "select" && isDynamicOptionSource(f.optionSource)) {
+ set.add(f.optionSource);
+ }
+ });
+ return [...set];
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
new file mode 100644
index 0000000..61aa6c0
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
@@ -0,0 +1,334 @@
+import {
+ addApprovalTemplate,
+ deleteApprovalTemplate,
+ getApprovalTemplateDetail,
+ listApprovalTemplatePage,
+ TEMPLATE_TYPE_BUILTIN,
+ updateApprovalTemplate,
+} from "@/api/officeProcessAutomation/approvalTemplate.js";
+import { Search } from "@element-plus/icons-vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { computed, reactive, ref } from "vue";
+import {
+ buildApprovalTemplateListParams,
+ createEmptyTemplateForm,
+ fetchBusinessTypeOptions,
+ flowNodesSummary,
+ isBuiltinTemplate,
+ mapTemplateFromApi,
+ mapTemplateToApi,
+ nodeSignModeLabel,
+ formatDisplayTime,
+ unwrapTemplateDetail,
+ validateTemplateForm,
+} from "./approveTemplateConstants.js";
+import { parseFormConfigToData } from "./formConfigUtils.js";
+
+const FALLBACK_TEMPLATE_TYPE_OPTIONS = [
+ { value: 0, label: "绯荤粺鍐呯疆" },
+ { value: 1, label: "鑷畾涔�" },
+];
+
+function matchTemplateTypeValue(options, type) {
+ if (type == null || type === "") return false;
+ return options.some(
+ (x) => x.value === type || x.value === Number(type) || String(x.value) === String(type)
+ );
+}
+
+export function useApproveTemplate() {
+ const templateTypeOptions = ref([...FALLBACK_TEMPLATE_TYPE_OPTIONS]);
+
+ function templateTypeLabel(type) {
+ if (type == null || type === "") return "鈥�";
+ const hit = templateTypeOptions.value.find(
+ (x) => x.value === type || x.value === Number(type) || String(x.value) === String(type)
+ );
+ return hit?.label || "鈥�";
+ }
+
+ const searchForm = reactive({
+ keyword: "",
+ enabledOnly: false,
+ });
+
+ const tableLoading = ref(false);
+ const page = reactive({ current: 1, size: 10, total: 0 });
+ const tableData = ref([]);
+
+ const formDialog = reactive({ visible: false, title: "", mode: "add" });
+ const form = reactive(createEmptyTemplateForm());
+ const formRef = ref();
+
+ const isEditingBuiltin = computed(
+ () => formDialog.mode === "edit" && Number(form.templateType) === TEMPLATE_TYPE_BUILTIN
+ );
+
+ async function loadTemplateTypeOptions() {
+ try {
+ const list = await fetchBusinessTypeOptions();
+ templateTypeOptions.value = list.length ? list : [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
+ } catch {
+ templateTypeOptions.value = [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
+ }
+ if (!matchTemplateTypeValue(templateTypeOptions.value, form.businessType)) {
+ form.businessType = templateTypeOptions.value[0]?.value ?? "";
+ }
+ }
+
+ const detailDialog = reactive({ visible: false });
+ const detailRow = ref({});
+ const detailLoading = ref(false);
+
+ const formRules = {
+ templateName: [{ required: true, message: "璇疯緭鍏ユā鏉垮悕绉�", trigger: "blur" }],
+ businessType: [{ required: true, message: "璇烽�夋嫨妯℃澘绫诲瀷", trigger: "change" }],
+ };
+
+ const tableColumn = ref([
+ { label: "妯℃澘鍚嶇О", prop: "templateName", minWidth: 140 },
+ {
+ label: "妯℃澘绫诲瀷",
+ prop: "businessType",
+ width: 100,
+ align: "center",
+ formatData: (v) => templateTypeLabel(v),
+ },
+ { label: "璇存槑", prop: "description", minWidth: 160, showOverflowTooltip: true },
+ {
+ label: "鑺傜偣鏁�",
+ prop: "flowNodes",
+ width: 80,
+ align: "center",
+ formatData: (v) => (Array.isArray(v) ? v.length : 0),
+ },
+ {
+ label: "娴佺▼姒傝",
+ prop: "flowNodes",
+ minWidth: 220,
+ showOverflowTooltip: true,
+ formatData: (v) => flowNodesSummary(v),
+ },
+ {
+ label: "鐘舵��",
+ prop: "enabled",
+ width: 90,
+ align: "center",
+ dataType: "tag",
+ formatData: (v) => (v !== false ? "鍚敤" : "鍋滅敤"),
+ formatType: (v) => (v !== false ? "success" : "info"),
+ },
+ {
+ label: "鍒涘缓鏃堕棿",
+ prop: "createdTime",
+ width: 170,
+ showOverflowTooltip: true,
+ formatData: (v) => formatDisplayTime(v),
+ },
+ {
+ label: "鏇存柊鏃堕棿",
+ prop: "updatedTime",
+ width: 170,
+ showOverflowTooltip: true,
+ formatData: (v) => formatDisplayTime(v),
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 220,
+ operation: [
+ { name: "璇︽儏", type: "text", clickFun: (row) => openDetail(row) },
+ { name: "缂栬緫", type: "text", clickFun: (row) => openFormDialog("edit", row) },
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ link: true,
+ disabled: (row) => isBuiltinTemplate(row),
+ clickFun: (row) => removeTemplate(row),
+ },
+ ],
+ },
+ ]);
+
+ async function fetchTemplateList() {
+ tableLoading.value = true;
+ try {
+ const res = await listApprovalTemplatePage(
+ buildApprovalTemplateListParams({ page, searchForm })
+ );
+ const data = res?.data || {};
+ tableData.value = (data.records || []).map(mapTemplateFromApi);
+ page.total = Number(data.total || 0);
+ } catch {
+ tableData.value = [];
+ page.total = 0;
+ } finally {
+ tableLoading.value = false;
+ }
+ }
+
+ function handleQuery() {
+ page.current = 1;
+ fetchTemplateList();
+ }
+
+ function resetSearch() {
+ searchForm.keyword = "";
+ searchForm.enabledOnly = false;
+ handleQuery();
+ }
+
+ function pagination({ page: p, limit }) {
+ page.current = p;
+ page.size = limit;
+ fetchTemplateList();
+ }
+
+ function resetForm(row) {
+ const base = createEmptyTemplateForm();
+ if (!row) {
+ Object.assign(form, base);
+ return;
+ }
+ const formConfigData = JSON.parse(
+ JSON.stringify(row.formConfigData || parseFormConfigToData(row.formConfig))
+ );
+ const builtin = isBuiltinTemplate(row);
+ Object.assign(form, {
+ ...base,
+ id: row.id,
+ templateName: row.templateName || "",
+ description: row.description || "",
+ templateType: row.templateType != null ? Number(row.templateType) : base.templateType,
+ businessType: row.businessType ?? "",
+ formConfig: row.formConfig || "",
+ formConfigData,
+ lockedFormFieldUids: builtin
+ ? (formConfigData.fields || []).map((f) => f._uid).filter(Boolean)
+ : [],
+ enabled: row.enabled !== false,
+ flowNodes: JSON.parse(JSON.stringify(row.flowNodes || [base.flowNodes[0]])),
+ storageBlobDTOs: JSON.parse(JSON.stringify(row.storageBlobDTOs || [])),
+ });
+ }
+
+ function openFormDialog(mode, row) {
+ formDialog.mode = mode;
+ formDialog.title = mode === "add" ? "鏂板缓瀹℃壒妯℃澘" : "缂栬緫瀹℃壒妯℃澘";
+ resetForm(mode === "edit" ? row : null);
+ formDialog.visible = true;
+ }
+
+ async function openDetail(row) {
+ if (row?.id == null || row.id === "") {
+ ElMessage.warning("鏃犳硶鏌ョ湅璇︽儏锛氱己灏戞ā鏉� ID");
+ return;
+ }
+ detailDialog.visible = true;
+ detailLoading.value = true;
+ detailRow.value = {};
+ try {
+ const res = await getApprovalTemplateDetail(row.id);
+ detailRow.value = mapTemplateFromApi(unwrapTemplateDetail(res));
+ } catch {
+ detailDialog.visible = false;
+ } finally {
+ detailLoading.value = false;
+ }
+ }
+
+ async function submitForm() {
+ if (!formRef.value) return false;
+ try {
+ await formRef.value.validate();
+ } catch {
+ return false;
+ }
+ const validated = validateTemplateForm(form);
+ if (!validated.ok) {
+ return { message: validated.message };
+ }
+ if (formDialog.mode === "edit" && !form.id) {
+ return { message: "缂哄皯妯℃澘 ID锛屾棤娉曚繚瀛樹慨鏀�" };
+ }
+ const dto = mapTemplateToApi(form);
+ try {
+ if (formDialog.mode === "add") {
+ await addApprovalTemplate(dto);
+ } else {
+ await updateApprovalTemplate(dto);
+ }
+ } catch {
+ return false;
+ }
+ formDialog.visible = false;
+ page.current = 1;
+ await fetchTemplateList();
+ return { ok: true };
+ }
+
+ async function removeTemplate(row) {
+ if (isBuiltinTemplate(row)) {
+ ElMessage.warning("绯荤粺鍐呯疆妯℃澘涓嶅厑璁稿垹闄�");
+ return;
+ }
+ if (row?.id == null || row.id === "") {
+ ElMessage.warning("鏃犳硶鍒犻櫎锛氱己灏戞ā鏉� ID");
+ return;
+ }
+ const name = row.templateName || "鏈懡鍚嶆ā鏉�";
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゅ鎵规ā鏉裤��${name}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+ "鍒犻櫎纭",
+ {
+ type: "warning",
+ confirmButtonText: "纭畾鍒犻櫎",
+ cancelButtonText: "鍙栨秷",
+ distinguishCancelAndClose: true,
+ autofocus: false,
+ }
+ );
+ } catch {
+ return;
+ }
+ try {
+ await deleteApprovalTemplate([row.id]);
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ await fetchTemplateList();
+ } catch {
+ /* 閿欒鐢辨嫤鎴櫒鎻愮ず */
+ }
+ }
+
+ return {
+ Search,
+ templateTypeOptions,
+ loadTemplateTypeOptions,
+ templateTypeLabel,
+ fetchTemplateList,
+ nodeSignModeLabel,
+ flowNodesSummary,
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ tableColumn,
+ formDialog,
+ form,
+ formRef,
+ formRules,
+ isEditingBuiltin,
+ detailDialog,
+ detailRow,
+ detailLoading,
+ handleQuery,
+ resetSearch,
+ pagination,
+ openFormDialog,
+ openDetail,
+ submitForm,
+ };
+}
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/useSelectOptionSources.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/useSelectOptionSources.js
new file mode 100644
index 0000000..8397288
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/useSelectOptionSources.js
@@ -0,0 +1,45 @@
+import { reactive, ref } from "vue";
+import {
+ collectOptionSourcesFromFields,
+ fetchSelectOptionCaches,
+ resolveFieldSelectOptions,
+ resolveSelectDisplayLabel,
+} from "./selectOptionSource.js";
+
+/** 涓嬫媺鍔ㄦ�侀�夐」锛氫汉鍛� / 閮ㄩ棬缂撳瓨涓庤В鏋� */
+export function useSelectOptionSources() {
+ const loading = ref(false);
+ const caches = reactive({
+ users: [],
+ deptOptions: [],
+ });
+
+ async function ensureForFields(fields) {
+ const sources = collectOptionSourcesFromFields(fields);
+ if (!sources.length) return;
+ loading.value = true;
+ try {
+ const next = await fetchSelectOptionCaches(sources);
+ caches.users = next.users;
+ caches.deptOptions = next.deptOptions;
+ } finally {
+ loading.value = false;
+ }
+ }
+
+ function getOptions(field) {
+ return resolveFieldSelectOptions(field, caches);
+ }
+
+ function getDisplayLabel(field, val) {
+ return resolveSelectDisplayLabel(field, val, caches);
+ }
+
+ return {
+ loading,
+ caches,
+ ensureForFields,
+ getOptions,
+ getDisplayLabel,
+ };
+}
diff --git a/src/views/officeProcessAutomation/AttendManage/leave-apply/index.vue b/src/views/officeProcessAutomation/AttendManage/leave-apply/index.vue
new file mode 100644
index 0000000..4d800df
--- /dev/null
+++ b/src/views/officeProcessAutomation/AttendManage/leave-apply/index.vue
@@ -0,0 +1,325 @@
+<!--OA妯″潡锛氳鍋囩敵璇�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">瀹℃壒鍗曞彿锛�</span>
+ <el-input
+ v-model="searchForm.instanceNo"
+ style="width: 220px"
+ placeholder="璇疯緭鍏ュ鎵瑰崟鍙�"
+ clearable
+ @keyup.enter="onSearch"
+ />
+ <span class="search_title" style="margin-left: 12px">鐢宠浜猴細</span>
+ <el-input
+ v-model="searchForm.applicantKeyword"
+ style="width: 220px"
+ placeholder="濮撳悕鎴栫紪鍙�"
+ clearable
+ :prefix-icon="Search"
+ @keyup.enter="onSearch"
+ />
+ <el-button type="primary" style="margin-left: 10px" @click="onSearch">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" @click="openAddWithTemplate">鏂板璇峰亣鐢宠</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ @pagination="onPagination"
+ :total="page.total"
+ />
+ </div>
+
+ <ApprovalInstanceSubmitDialog
+ v-model="submitDialog.visible"
+ :title="submitDialogTitle"
+ :form="submitForm"
+ :rules="submitFormRules"
+ :fields="submitFormFields"
+ :active-template="activeTemplate"
+ :user-options="flowUserOptions"
+ :is-edit="isSubmitEdit"
+ :saving="submitSaving"
+ :form-ref="submitFormRef"
+ flow-attachments-only
+ @submit="onSubmit"
+ >
+ <template #before="{ form, fields }">
+ <FormPayloadFields :fields="displayTemplateFields(fields)" :form-payload="form.formPayload" />
+ <el-row :gutter="24">
+ <el-col :span="12">
+ <el-form-item label="鍋囨湡浣欓" prop="leaveBalanceDays">
+ <el-input-number
+ v-model="form.leaveBalanceDays"
+ :min="0"
+ :max="999"
+ :precision="2"
+ :step="0.5"
+ controls-position="right"
+ placeholder="澶�"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璇峰亣鏃堕暱">
+ <el-input :model-value="leaveDurationDisplay(form)" readonly placeholder="鏍规嵁妯℃澘涓鍋囨椂闂磋嚜鍔ㄨ绠�">
+ <template #append>澶�</template>
+ </el-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </template>
+ </ApprovalInstanceSubmitDialog>
+
+ <ApprovalTemplateBindDialog
+ v-model:visible="templateBindVisible"
+ :module-key="APPROVAL_MODULE_KEYS.LEAVE"
+ skip-form-confirm
+ @confirm="onTemplateBound"
+ @closed="onTemplateBindClosed"
+ />
+
+ <ApprovalInstanceDetailDialog
+ v-model="detailDialog.visible"
+ title="璇峰亣鐢宠璇︽儏"
+ :row="detailRow"
+ @edit="openEditFromDetail"
+ />
+ </div>
+</template>
+
+<script setup>
+import { Search } from "@element-plus/icons-vue";
+import dayjs from "dayjs";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { ElMessage } from "element-plus";
+import { computed, onMounted, reactive, ref, watch } from "vue";
+import FormPayloadFields from "../../ApproveManage/approve-list/components/FormPayloadFields.vue";
+import ApprovalInstanceDetailDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue";
+import ApprovalInstanceSubmitDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue";
+import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
+import { buildInstanceTableColumns } from "../../ApproveManage/approve-shared/approvalInstanceFormConfigTable.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { useApprovalInstanceModule } from "../../ApproveManage/approve-shared/useApprovalInstanceModule.js";
+import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
+import { SELECT_OPTION_SOURCE } from "../../ApproveManage/approve-template/selectOptionSource.js";
+
+const LEAVE_TYPE_OPTIONS = [
+ { label: "骞村亣", value: "annual" },
+ { label: "鐥呭亣", value: "sick" },
+ { label: "浜嬪亣", value: "personal" },
+ { label: "濠氬亣", value: "marriage" },
+ { label: "浜у亣", value: "maternity" },
+ { label: "鍝轰钩鍋�", value: "nursing" },
+ { label: "鎱板攣鍋�", value: "condolence" },
+ { label: "璋冧紤", value: "compensatory" },
+];
+
+function isLeaveBalanceField(field) {
+ const label = String(field?.label || "");
+ return label.includes("鍋囨湡浣欓") || field?.key === "leaveBalanceDays";
+}
+
+function isLeaveDurationField(field) {
+ const label = String(field?.label || "");
+ return label.includes("璇峰亣鏃堕暱") || field?.key === "leaveDurationDays";
+}
+
+function displayTemplateFields(fields = []) {
+ return (fields || []).filter((f) => !isLeaveBalanceField(f) && !isLeaveDurationField(f));
+}
+
+function findLeaveTimeTemplateField(fields = []) {
+ return (
+ fields.find((f) => f?.type === "datetimerange" && String(f?.label || "").includes("璇峰亣鏃堕棿")) ||
+ fields.find((f) => f?.type === "datetimerange" && f?.key === "dateRange") ||
+ fields.find((f) => f?.type === "datetimerange") ||
+ null
+ );
+}
+
+function findApplicantTemplateField(fields = []) {
+ return (
+ fields.find((f) => String(f?.label || "").includes("鐢宠浜�")) ||
+ fields.find((f) => f?.type === "select" && f?.optionSource === SELECT_OPTION_SOURCE.USER) ||
+ null
+ );
+}
+
+function resolveLeaveTimeRange(payload, leaveTimeField) {
+ if (!leaveTimeField?.key) return { start: "", end: "" };
+ const val = payload?.[leaveTimeField.key];
+ if (!Array.isArray(val) || val.length < 2) return { start: "", end: "" };
+ return { start: val[0] || "", end: val[1] || "" };
+}
+
+function computeLeaveDays(startStr, endStr) {
+ if (!startStr || !endStr) return null;
+ const t0 = dayjs(startStr);
+ const t1 = dayjs(endStr);
+ if (!t0.isValid() || !t1.isValid() || !t1.isAfter(t0)) return null;
+ const days = t1.diff(t0, "millisecond") / (24 * 60 * 60 * 1000);
+ return Math.round(days * 100) / 100;
+}
+
+function leaveDurationDisplay(form) {
+ const leaveTimeField = findLeaveTimeTemplateField(form.formFieldDefs);
+ const { start, end } = resolveLeaveTimeRange(form.formPayload, leaveTimeField);
+ const d = computeLeaveDays(start, end);
+ return d == null ? "" : String(d);
+}
+
+const searchForm = reactive({
+ instanceNo: "",
+ applicantKeyword: "",
+});
+
+function validateLeaveBeforeSave() {
+ const leaveTimeField = findLeaveTimeTemplateField(submitForm.formFieldDefs);
+ const { start, end } = resolveLeaveTimeRange(submitForm.formPayload, leaveTimeField);
+ if (computeLeaveDays(start, end) == null) {
+ ElMessage.warning("璇锋鏌ユā鏉夸腑鐨勮鍋囨椂闂达紝缁撴潫鏃堕棿椤绘櫄浜庡紑濮嬫椂闂�");
+ throw new Error("invalid leave time");
+ }
+}
+
+const mod = useApprovalInstanceModule({
+ moduleKey: APPROVAL_MODULE_KEYS.LEAVE,
+ beforeSave: validateLeaveBeforeSave,
+ extraFormRules: {
+ leaveBalanceDays: [{ required: true, message: "璇峰~鍐欏亣鏈熶綑棰�", trigger: "blur" }],
+ },
+});
+
+const {
+ tableData,
+ tableLoading,
+ page,
+ detailDialog,
+ detailRow,
+ submitDialog,
+ submitEditRow,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ isSubmitEdit,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitDialogTitle,
+ templateBindVisible,
+ handleQuery,
+ initModuleList,
+ pagination,
+ openAddWithTemplate,
+ onTemplateBound,
+ onTemplateBindClosed,
+ openEditFromDetail,
+ submitInstanceForm,
+ buildTableActions,
+} = mod;
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+const allUsersCache = ref([]);
+
+const applicantTemplateField = computed(() =>
+ findApplicantTemplateField(submitForm.formFieldDefs)
+);
+
+function unwrapArray(payload) {
+ if (Array.isArray(payload)) return payload;
+ if (payload && Array.isArray(payload.data)) return payload.data;
+ return [];
+}
+
+async function loadUserPool() {
+ try {
+ const res = await userListNoPageByTenantId();
+ allUsersCache.value = unwrapArray(res);
+ } catch {
+ allUsersCache.value = [];
+ }
+}
+
+watch(
+ () => submitDialog.visible,
+ (v) => {
+ if (!v) return;
+ if (submitForm.leaveBalanceDays == null && isSubmitEdit.value) {
+ submitForm.leaveBalanceDays =
+ submitEditRow.value?.formPayload?.leaveBalanceDays ??
+ submitEditRow.value?.leaveBalanceDays;
+ }
+ if (submitForm.leaveBalanceDays == null && !isSubmitEdit.value) {
+ submitForm.leaveBalanceDays = undefined;
+ }
+ }
+);
+
+watch(
+ () => {
+ const key = applicantTemplateField.value?.key;
+ return key ? submitForm.formPayload[key] : undefined;
+ },
+ async (uid) => {
+ if (!applicantTemplateField.value || !uid) return;
+ if (!allUsersCache.value.length) await loadUserPool();
+ }
+);
+
+const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, {
+ moduleKey: APPROVAL_MODULE_KEYS.LEAVE,
+});
+
+function onSearch() {
+ handleQuery(searchForm);
+}
+
+function resetSearch() {
+ searchForm.instanceNo = "";
+ searchForm.applicantKeyword = "";
+ onSearch();
+}
+
+function onPagination(obj) {
+ pagination(obj, searchForm);
+}
+
+async function onSubmit() {
+ const ok = await submitInstanceForm({ skipValidate: true });
+ if (ok) ElMessage.success(isSubmitEdit.value ? "淇敼鎴愬姛" : "鎻愪氦鎴愬姛");
+}
+
+onMounted(async () => {
+ loadFlowUsers();
+ await initModuleList(searchForm);
+});
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+</style>
diff --git a/src/views/officeProcessAutomation/AttendManage/overtime-apply/components/ApprovalFlowEditor.vue b/src/views/officeProcessAutomation/AttendManage/overtime-apply/components/ApprovalFlowEditor.vue
new file mode 100644
index 0000000..9e3ada5
--- /dev/null
+++ b/src/views/officeProcessAutomation/AttendManage/overtime-apply/components/ApprovalFlowEditor.vue
@@ -0,0 +1,360 @@
+<!-- 鍔犵彮鐢宠妯″潡鍐咃細鍙鍒犲鎵硅妭鐐癸紝姣忚妭鐐瑰繀閫� 1 浜� -->
+<template>
+ <div class="afe">
+ <div v-if="innerList.length" class="afe-flow">
+ <div v-for="(item, index) in innerList" :key="item._uid" class="afe-flow-item">
+ <div class="afe-card" :class="{ 'afe-card--empty': !item.approverId }">
+ <div class="afe-badge">{{ index + 1 }}</div>
+ <div class="afe-avatar-wrap">
+ <div
+ class="afe-avatar"
+ :class="{ 'afe-avatar--on': item.approverId }"
+ :style="item.approverId ? { backgroundColor: avatarColor(item.approverName) } : {}"
+ >
+ <span v-if="item.approverId">{{ (item.approverName || '?').charAt(0) }}</span>
+ <el-icon v-else :size="22"><User /></el-icon>
+ </div>
+ <div class="afe-level">{{ levelText(index) }}</div>
+ </div>
+ <div class="afe-select">
+ <el-select
+ v-model="item.approverId"
+ placeholder="璇烽�夋嫨瀹℃壒浜�"
+ filterable
+ clearable
+ style="width: 100%"
+ @change="(v) => onPick(v, item)"
+ >
+ <el-option
+ v-for="u in userOptions"
+ :key="String(u.userId ?? u.id)"
+ :label="optionLabel(u)"
+ :value="u.userId ?? u.id"
+ />
+ </el-select>
+ </div>
+ <div class="afe-actions">
+ <el-button type="primary" circle size="small" :disabled="index === 0" title="鍓嶇Щ" @click="moveLeft(index)">
+ <el-icon><ArrowLeft /></el-icon>
+ </el-button>
+ <el-button
+ type="primary"
+ circle
+ size="small"
+ :disabled="index === innerList.length - 1"
+ title="鍚庣Щ"
+ @click="moveRight(index)"
+ >
+ <el-icon><ArrowRight /></el-icon>
+ </el-button>
+ <el-button type="danger" circle size="small" title="鍒犻櫎鑺傜偣" @click="remove(index)">
+ <el-icon><Delete /></el-icon>
+ </el-button>
+ </div>
+ </div>
+ <div v-if="index < innerList.length - 1" class="afe-conn">
+ <div class="afe-conn-line"></div>
+ <el-icon class="afe-conn-icon"><ArrowRight /></el-icon>
+ </div>
+ </div>
+
+ <div class="afe-add-wrap">
+ <div class="afe-conn" v-if="innerList.length">
+ <div class="afe-conn-line"></div>
+ <el-icon class="afe-conn-icon"><ArrowRight /></el-icon>
+ </div>
+ <div class="afe-add-card" @click="addNode">
+ <div class="afe-add-icon"><el-icon :size="26"><Plus /></el-icon></div>
+ <span>鏂板鑺傜偣</span>
+ </div>
+ </div>
+ </div>
+
+ <div v-else class="afe-empty">
+ <el-icon :size="44" color="#c0c4cc"><User /></el-icon>
+ <p>鏆傛棤瀹℃壒鑺傜偣</p>
+ <el-button type="primary" @click="addNode">娣诲姞绗竴涓妭鐐�</el-button>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ArrowLeft, ArrowRight, Delete, Plus, User } from "@element-plus/icons-vue";
+import { ref, watch } from "vue";
+
+const props = defineProps({
+ modelValue: { type: Array, default: () => [] },
+ /** 涓庣埗椤� userList 缁撴瀯涓�鑷达細userId / id銆乶ickName銆乽serName */
+ userOptions: { type: Array, default: () => [] },
+});
+
+const emit = defineEmits(["update:modelValue"]);
+
+const innerList = ref([]);
+
+const palette = ["#409EFF", "#67C23A", "#E6A23C", "#F56C6C", "#9B59B6", "#1ABC9C"];
+
+function avatarColor(name) {
+ if (!name) return "#c0c4cc";
+ let h = 0;
+ for (let i = 0; i < name.length; i++) h = name.charCodeAt(i) + ((h << 5) - h);
+ return palette[Math.abs(h) % palette.length];
+}
+
+function levelText(i) {
+ const t = ["绗竴绾�", "绗簩绾�", "绗笁绾�", "绗洓绾�", "绗簲绾�", "绗叚绾�", "绗竷绾�", "绗叓绾�"];
+ return t[i] || `绗�${i + 1}绾;
+}
+
+function optionLabel(u) {
+ const nick = u.nickName || "";
+ const un = u.userName || "";
+ if (nick && un && nick !== un) return `${nick}锛�${un}锛塦;
+ return nick || un || `鐢ㄦ埛${u.userId ?? u.id ?? ""}`;
+}
+
+function newUid() {
+ return `n_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
+}
+
+function mapIn(rows) {
+ if (!Array.isArray(rows)) return [];
+ return rows.map((r, i) => ({
+ _uid: newUid(),
+ approverId: r.approverId ?? r.approver_id ?? null,
+ approverName: r.approverName ?? r.approver_name ?? "",
+ sortOrder: r.sortOrder ?? r.nodeOrder ?? i + 1,
+ nodeOrder: r.nodeOrder ?? r.sortOrder ?? i + 1,
+ roleName: r.roleName ?? "",
+ roleCode: r.roleCode ?? "",
+ }));
+}
+
+function publicShape(rows) {
+ const arr = Array.isArray(rows) ? rows : [];
+ return arr.map((r, i) => ({
+ approverId: r.approverId ?? null,
+ approverName: r.approverName ?? "",
+ roleName: r.roleName ?? "",
+ roleCode: r.roleCode ?? "",
+ sortOrder: i + 1,
+ }));
+}
+
+function emitOut() {
+ const out = innerList.value.map((r, i) => ({
+ approverId: r.approverId ?? null,
+ approverName: r.approverName ?? "",
+ sortOrder: i + 1,
+ nodeOrder: i + 1,
+ roleName: r.roleName ?? "",
+ roleCode: r.roleCode ?? "",
+ }));
+ emit("update:modelValue", out);
+}
+
+watch(
+ () => props.modelValue,
+ (v) => {
+ const next = publicShape(v || []);
+ if (JSON.stringify(next) === JSON.stringify(publicShape(innerList.value))) return;
+ innerList.value = mapIn(v || []);
+ },
+ { deep: true, immediate: true }
+);
+
+function findUser(id) {
+ if (id == null || id === "") return null;
+ return props.userOptions.find((u) => String(u.userId ?? u.id) === String(id)) ?? null;
+}
+
+function onPick(userId, row) {
+ if (!userId) {
+ row.approverName = "";
+ emitOut();
+ return;
+ }
+ const u = findUser(userId);
+ row.approverName = u ? u.nickName || u.userName || "" : "";
+ emitOut();
+}
+
+function addNode() {
+ innerList.value.push({
+ _uid: newUid(),
+ approverId: null,
+ approverName: "",
+ roleName: "",
+ roleCode: "",
+ });
+ emitOut();
+}
+
+function remove(index) {
+ innerList.value.splice(index, 1);
+ emitOut();
+}
+
+function moveLeft(index) {
+ if (index < 1) return;
+ const t = innerList.value[index];
+ innerList.value[index] = innerList.value[index - 1];
+ innerList.value[index - 1] = t;
+ emitOut();
+}
+
+function moveRight(index) {
+ if (index >= innerList.value.length - 1) return;
+ const t = innerList.value[index];
+ innerList.value[index] = innerList.value[index + 1];
+ innerList.value[index + 1] = t;
+ emitOut();
+}
+</script>
+
+<style scoped>
+.afe {
+ width: 100%;
+}
+.afe-flow {
+ display: flex;
+ align-items: flex-start;
+ flex-wrap: nowrap;
+ overflow-x: auto;
+ padding: 6px 0 10px;
+ gap: 0;
+}
+.afe-flow-item {
+ display: flex;
+ align-items: center;
+}
+.afe-card {
+ width: 200px;
+ flex-shrink: 0;
+ border: 2px solid var(--el-border-color);
+ border-radius: 12px;
+ padding: 14px 12px 12px;
+ position: relative;
+ background: var(--el-bg-color);
+}
+.afe-card--empty {
+ border-style: dashed;
+ background: var(--el-fill-color-lighter);
+}
+.afe-badge {
+ position: absolute;
+ top: -8px;
+ left: 12px;
+ width: 22px;
+ height: 22px;
+ border-radius: 50%;
+ background: var(--el-color-primary);
+ color: #fff;
+ font-size: 12px;
+ font-weight: 700;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.afe-avatar-wrap {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 6px 0 10px;
+}
+.afe-avatar {
+ width: 48px;
+ height: 48px;
+ border-radius: 50%;
+ background: var(--el-fill-color);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--el-text-color-placeholder);
+ margin-bottom: 6px;
+ font-size: 18px;
+ font-weight: 600;
+}
+.afe-avatar--on {
+ color: #fff;
+}
+.afe-level {
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+}
+.afe-select {
+ margin-bottom: 10px;
+}
+.afe-actions {
+ display: flex;
+ justify-content: center;
+ gap: 8px;
+ padding-top: 10px;
+ border-top: 1px solid var(--el-border-color-lighter);
+}
+.afe-conn {
+ display: flex;
+ align-items: center;
+ width: 40px;
+ flex-shrink: 0;
+ align-self: center;
+}
+.afe-conn-line {
+ flex: 1;
+ height: 2px;
+ background: var(--el-border-color);
+}
+.afe-conn-icon {
+ font-size: 14px;
+ color: var(--el-text-color-placeholder);
+ margin-left: -2px;
+}
+.afe-add-wrap {
+ display: flex;
+ align-items: center;
+}
+.afe-add-card {
+ width: 120px;
+ min-height: 168px;
+ flex-shrink: 0;
+ border: 2px dashed var(--el-border-color);
+ border-radius: 12px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
+ cursor: pointer;
+ color: var(--el-text-color-regular);
+ font-size: 13px;
+ background: var(--el-fill-color-lighter);
+ transition: border-color 0.2s, background 0.2s;
+}
+.afe-add-card:hover {
+ border-color: var(--el-color-primary);
+ background: var(--el-color-primary-light-9);
+ color: var(--el-color-primary);
+}
+.afe-add-icon {
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ background: var(--el-color-primary);
+ color: #fff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.afe-empty {
+ text-align: center;
+ padding: 28px 16px;
+ border: 1px dashed var(--el-border-color);
+ border-radius: 12px;
+ background: var(--el-fill-color-lighter);
+}
+.afe-empty p {
+ margin: 10px 0 14px;
+ color: var(--el-text-color-secondary);
+ font-size: 14px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue b/src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue
new file mode 100644
index 0000000..9b3d91e
--- /dev/null
+++ b/src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue
@@ -0,0 +1,260 @@
+<!--OA妯″潡锛氬姞鐝敵璇�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">瀹℃壒鍗曞彿锛�</span>
+ <el-input
+ v-model="searchForm.instanceNo"
+ style="width: 220px"
+ placeholder="璇疯緭鍏ュ鎵瑰崟鍙�"
+ clearable
+ @keyup.enter="onSearch"
+ />
+ <span class="search_title" style="margin-left: 12px">鐢宠浜猴細</span>
+ <el-input
+ v-model="searchForm.applicantKeyword"
+ style="width: 220px"
+ placeholder="濮撳悕鎴栫紪鍙�"
+ clearable
+ :prefix-icon="Search"
+ @keyup.enter="onSearch"
+ />
+ <el-button type="primary" style="margin-left: 10px" @click="onSearch">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div class="search_actions">
+ <el-button type="warning" plain @click="handleExport">瀵煎嚭</el-button>
+ <el-button type="primary" @click="openAddWithTemplate">鏂板鍔犵彮鐢宠</el-button>
+ </div>
+ </div>
+
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ @pagination="onPagination"
+ :total="page.total"
+ />
+ </div>
+
+ <ApprovalInstanceSubmitDialog
+ v-model="submitDialog.visible"
+ :title="submitDialogTitle"
+ :form="submitForm"
+ :rules="submitFormRules"
+ :fields="submitFormFields"
+ :active-template="activeTemplate"
+ :user-options="flowUserOptions"
+ :is-edit="isSubmitEdit"
+ :saving="submitSaving"
+ :form-ref="submitFormRef"
+ flow-attachments-only
+ @submit="onSubmit"
+ >
+ <template #before="{ form, fields }">
+ <FormPayloadFields :fields="displayTemplateFields(fields)" :form-payload="form.formPayload" />
+ <el-row :gutter="24">
+ <el-col :span="12">
+ <el-form-item label="鍔犵彮鏃堕暱">
+ <el-input :model-value="overtimeHoursDisplay(form)" readonly placeholder="鏍规嵁妯℃澘涓姞鐝椂闂磋嚜鍔ㄨ绠�">
+ <template #append>灏忔椂</template>
+ </el-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </template>
+ </ApprovalInstanceSubmitDialog>
+
+ <ApprovalTemplateBindDialog
+ v-model:visible="templateBindVisible"
+ :module-key="APPROVAL_MODULE_KEYS.OVERTIME"
+ skip-form-confirm
+ @confirm="onTemplateBound"
+ @closed="onTemplateBindClosed"
+ />
+
+ <ApprovalInstanceDetailDialog
+ v-model="detailDialog.visible"
+ title="鍔犵彮鐢宠璇︽儏"
+ :row="detailRow"
+ @edit="openEditFromDetail"
+ />
+ </div>
+</template>
+
+<script setup>
+import { Search } from "@element-plus/icons-vue";
+import dayjs from "dayjs";
+import { ElMessage } from "element-plus";
+import { getCurrentInstance, onMounted, reactive, ref } from "vue";
+import FormPayloadFields from "../../ApproveManage/approve-list/components/FormPayloadFields.vue";
+import ApprovalInstanceDetailDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue";
+import ApprovalInstanceSubmitDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue";
+import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
+import { buildInstanceTableColumns } from "../../ApproveManage/approve-shared/approvalInstanceFormConfigTable.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { useApprovalInstanceModule } from "../../ApproveManage/approve-shared/useApprovalInstanceModule.js";
+import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
+
+const OVERTIME_TYPE_OPTIONS = [
+ { label: "宸ヤ綔鏃ュ姞鐝�", value: "weekday" },
+ { label: "浼戞伅鏃ュ姞鐝�", value: "weekend" },
+ { label: "娉曞畾鑺傚亣鏃ュ姞鐝�", value: "holiday" },
+];
+
+function isOvertimeDurationField(field) {
+ const label = String(field?.label || "");
+ return label.includes("鍔犵彮鏃堕暱") || field?.key === "overtimeHours";
+}
+
+function displayTemplateFields(fields = []) {
+ return (fields || []).filter((f) => !isOvertimeDurationField(f));
+}
+
+function findOvertimeTimeTemplateField(fields = []) {
+ return (
+ fields.find((f) => f?.type === "datetimerange" && String(f?.label || "").includes("鍔犵彮鏃堕棿")) ||
+ fields.find((f) => f?.type === "datetimerange") ||
+ null
+ );
+}
+
+function resolveOvertimeTimeRange(payload, overtimeTimeField) {
+ if (!overtimeTimeField?.key) return { start: "", end: "" };
+ const val = payload?.[overtimeTimeField.key];
+ if (!Array.isArray(val) || val.length < 2) return { start: "", end: "" };
+ return { start: val[0] || "", end: val[1] || "" };
+}
+
+function computeOvertimeHours(startStr, endStr) {
+ if (!startStr || !endStr) return null;
+ const t0 = dayjs(startStr);
+ const t1 = dayjs(endStr);
+ if (!t0.isValid() || !t1.isValid() || !t1.isAfter(t0)) return null;
+ return Math.round((t1.diff(t0, "millisecond") / 3600000) * 100) / 100;
+}
+
+function overtimeHoursDisplay(form) {
+ const field = findOvertimeTimeTemplateField(form.formFieldDefs);
+ const { start, end } = resolveOvertimeTimeRange(form.formPayload, field);
+ const h = computeOvertimeHours(start, end);
+ return h == null ? "" : String(h);
+}
+
+const { proxy } = getCurrentInstance();
+
+const searchForm = reactive({
+ instanceNo: "",
+ applicantKeyword: "",
+});
+
+const mod = useApprovalInstanceModule({
+ moduleKey: APPROVAL_MODULE_KEYS.OVERTIME,
+ beforeSave: validateOvertimeBeforeSave,
+});
+
+const {
+ tableData,
+ tableLoading,
+ page,
+ detailDialog,
+ detailRow,
+ submitDialog,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ isSubmitEdit,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitDialogTitle,
+ templateBindVisible,
+ handleQuery,
+ initModuleList,
+ pagination,
+ openAddWithTemplate,
+ onTemplateBound,
+ onTemplateBindClosed,
+ openEditFromDetail,
+ submitInstanceForm,
+ buildTableActions,
+} = mod;
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+function validateOvertimeBeforeSave() {
+ const field = findOvertimeTimeTemplateField(submitForm.formFieldDefs);
+ const { start, end } = resolveOvertimeTimeRange(submitForm.formPayload, field);
+ if (computeOvertimeHours(start, end) == null) {
+ ElMessage.warning("璇锋鏌ユā鏉夸腑鐨勫姞鐝椂闂达紝缁撴潫鏃堕棿椤绘櫄浜庡紑濮嬫椂闂�");
+ throw new Error("invalid overtime time");
+ }
+}
+
+const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, {
+ moduleKey: APPROVAL_MODULE_KEYS.OVERTIME,
+});
+
+function onSearch() {
+ handleQuery(searchForm);
+}
+
+function resetSearch() {
+ searchForm.instanceNo = "";
+ searchForm.applicantKeyword = "";
+ onSearch();
+}
+
+function onPagination(obj) {
+ pagination(obj, searchForm);
+}
+
+async function onSubmit() {
+ const ok = await submitInstanceForm({ skipValidate: true });
+ if (ok) ElMessage.success(isSubmitEdit.value ? "淇敼鎴愬姛" : "鎻愪氦鎴愬姛");
+}
+
+function handleExport() {
+ const data = tableData.value;
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json;charset=utf-8" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `鍔犵彮鐢宠瀵煎嚭_${dayjs().format("YYYYMMDDHHmmss")}.json`;
+ a.click();
+ URL.revokeObjectURL(url);
+ proxy?.$modal?.msgSuccess?.(`宸插鍑� ${data.length} 鏉★紙褰撳墠椤靛垪琛ㄦ暟鎹級`);
+}
+
+onMounted(async () => {
+ loadFlowUsers();
+ await initModuleList(searchForm);
+});
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ContractManage/purchase-contract/index.vue b/src/views/officeProcessAutomation/ContractManage/purchase-contract/index.vue
new file mode 100644
index 0000000..d6d9ef4
--- /dev/null
+++ b/src/views/officeProcessAutomation/ContractManage/purchase-contract/index.vue
@@ -0,0 +1,12 @@
+<!--
+ 妯″潡涓枃鍚嶏細閲囪喘鍚堝悓
+ 鐩綍鏍囪瘑锛欳ontractManage/purchase-contract锛坧urchase-contract 鈫� 涓枃锛氶噰璐悎鍚岋級
+ 澶嶇敤椤甸潰锛欯/views/procurementManagement/procurementLedger/index.vue锛堥噰璐彴璐︼紱鏂囦欢鍚� index.vue 鈫� 鍏ュ彛椤碉級
+-->
+<template>
+ <ProcurementLedger />
+</template>
+
+<script setup>
+import ProcurementLedger from '@/views/procurementManagement/procurementLedger/index.vue'
+</script>
diff --git a/src/views/officeProcessAutomation/ContractManage/sale-contract/index.vue b/src/views/officeProcessAutomation/ContractManage/sale-contract/index.vue
new file mode 100644
index 0000000..6be106a
--- /dev/null
+++ b/src/views/officeProcessAutomation/ContractManage/sale-contract/index.vue
@@ -0,0 +1,12 @@
+<!--
+ 妯″潡涓枃鍚嶏細閿�鍞悎鍚�
+ 鐩綍鏍囪瘑锛欳ontractManage/sale-contract锛坰ale-contract 鈫� 涓枃锛氶攢鍞悎鍚岋級
+ 澶嶇敤椤甸潰锛欯/views/procurementManagement/procurementLedger/index.vue锛堥噰璐彴璐︼紱鏂囦欢鍚� index.vue 鈫� 鍏ュ彛椤碉級
+-->
+<template>
+ <ProcurementLedger />
+</template>
+
+<script setup>
+import ProcurementLedger from '@/views/procurementManagement/procurementLedger/index.vue'
+</script>
diff --git a/src/views/officeProcessAutomation/EnterpriseNews/news-manage/components/NewsDetailPanel.vue b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/components/NewsDetailPanel.vue
new file mode 100644
index 0000000..1124472
--- /dev/null
+++ b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/components/NewsDetailPanel.vue
@@ -0,0 +1,169 @@
+<!-- EnterpriseNews锛氳鎯呭彧璇婚潰鏉匡紙鍚簰鍔級 -->
+<template>
+ <el-descriptions :column="2" border>
+ <el-descriptions-item label="鏂伴椈缂栧彿">{{ row.newsNo || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐘舵��">
+ <el-tag :type="publishStatusTag(row.newsStatus ?? row.publishStatus)" size="small">
+ {{ publishStatusLabel(row.newsStatus ?? row.publishStatus) }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="鏂伴椈鍒嗙被">
+ <span class="type-badge" :style="{ color: newsTypeColor(row.newsType) }">
+ {{ newsTypeLabel(row.newsType) }}
+ </span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鎺掔増妯℃澘">{{ layoutTemplateLabel(row.layoutTemplate) }}</el-descriptions-item>
+ <el-descriptions-item label="鏍囬" :span="2">{{ row.title || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鎽樿" :span="2">{{ row.summary || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="闃呰鑼冨洿">{{ readScopeLabel(row.readScope) }}</el-descriptions-item>
+ <el-descriptions-item label="闃呰鐜�">
+ {{ readRate(row) }}%锛堟湭璇� {{ unreadCount }} 浜猴級
+ </el-descriptions-item>
+ <el-descriptions-item label="缂栬緫鏉冮檺">{{ publishRoleLabel(row.editorRole) }}</el-descriptions-item>
+ <el-descriptions-item label="瀹℃牳瑙掕壊">{{ publishRoleLabel(row.reviewerRole) }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戝竷浜�">{{ row.publisherName || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鍙戝竷鏃堕棿">{{ row.publishTime || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="褰撳墠鐗堟湰">v{{ row.versionNo || 1 }}</el-descriptions-item>
+ <el-descriptions-item label="闇�闃呰纭">
+ {{ row.requireReadConfirm ? "鏄�" : "鍚�" }}
+ </el-descriptions-item>
+ </el-descriptions>
+
+ <el-divider content-position="left">姝f枃鍐呭</el-divider>
+ <div v-if="row.contentHtml" class="news-html-body" v-html="row.contentHtml" />
+ <el-empty v-else description="鏆傛棤姝f枃" :image-size="48" />
+
+ <template v-if="row.mediaList?.length">
+ <el-divider content-position="left">鍥鹃泦 / 瑙嗛</el-divider>
+ <div class="media-grid">
+ <div v-for="(m, i) in row.mediaList" :key="i" class="media-item">
+ <el-tag size="small" type="info">{{ m.type === "video" ? "瑙嗛" : "鍥剧墖" }}</el-tag>
+ <span class="media-name">{{ m.name }}</span>
+ </div>
+ </div>
+ </template>
+
+ <el-divider content-position="left">闄勪欢</el-divider>
+ <template v-if="row.attachmentList?.length">
+ <el-tag
+ v-for="(f, i) in row.attachmentList"
+ :key="i"
+ class="file-tag"
+ type="info"
+ @click="openFile(f)"
+ >
+ {{ f.name }}
+ </el-tag>
+ </template>
+ <el-empty v-else description="鏆傛棤闄勪欢" :image-size="48" />
+
+ <template v-if="row.newsType === 'culture' && (row.publishStatus === 'PUBLISHED' || row.publishStatus === 'published')">
+ <el-divider content-position="left">浜掑姩锛堢偣璧� {{ likeCount }} 路 璇勮 {{ commentCount }}锛�</el-divider>
+ <div class="interaction-bar">
+ <el-button type="primary" plain size="small" @click="$emit('like')">
+ {{ likedByMe ? "鍙栨秷鐐硅禐" : "鐐硅禐" }}
+ </el-button>
+ </div>
+ <el-input
+ v-model="commentDraft"
+ type="textarea"
+ :rows="2"
+ maxlength="300"
+ show-word-limit
+ placeholder="鍐欎笅浣犵殑璇勮鈥�"
+ class="mb8"
+ />
+ <el-button type="primary" size="small" @click="submitComment">鍙戣〃璇勮</el-button>
+ <el-timeline v-if="row.comments?.length" class="comment-timeline mt12">
+ <el-timeline-item v-for="c in row.comments" :key="c.id" :timestamp="c.time">
+ <strong>{{ c.name }}</strong>锛歿{ c.content }}
+ </el-timeline-item>
+ </el-timeline>
+ <el-empty v-else description="鏆傛棤璇勮" :image-size="40" />
+ </template>
+</template>
+
+<script setup>
+import { computed, ref } from "vue";
+import {
+ newsTypeLabel,
+ newsTypeColor,
+ publishStatusLabel,
+ publishStatusTag,
+ layoutTemplateLabel,
+ readScopeLabel,
+ publishRoleLabel,
+ readRate,
+ getUnreadEmployees,
+} from "../enterpriseNewsUtils.js";
+
+const props = defineProps({
+ row: { type: Object, default: () => ({}) },
+});
+
+const emit = defineEmits(["like", "comment"]);
+
+const commentDraft = ref("");
+
+const unreadCount = computed(() => getUnreadEmployees(props.row).length);
+const likeCount = computed(() => props.row?.likes?.length || 0);
+const commentCount = computed(() => props.row?.comments?.length || 0);
+const likedByMe = computed(() => (props.row?.likes || []).some((l) => l.userId === "u1"));
+
+function openFile(f) {
+ const url = f?.url || f?.downloadURL;
+ if (url) window.open(url, "_blank");
+}
+
+function submitComment() {
+ emit("comment", commentDraft.value);
+ commentDraft.value = "";
+}
+</script>
+
+<style scoped>
+.type-badge {
+ font-weight: 600;
+}
+.news-html-body {
+ padding: 12px 16px;
+ background: var(--el-fill-color-light);
+ border-radius: 6px;
+ line-height: 1.7;
+ max-height: 320px;
+ overflow-y: auto;
+}
+.media-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+.media-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px 12px;
+ background: var(--el-fill-color-lighter);
+ border-radius: 4px;
+}
+.media-name {
+ font-size: 13px;
+}
+.file-tag {
+ margin: 0 8px 8px 0;
+ cursor: pointer;
+}
+.interaction-bar {
+ margin-bottom: 8px;
+}
+.comment-timeline {
+ max-height: 200px;
+ overflow-y: auto;
+}
+.mb8 {
+ margin-bottom: 8px;
+}
+.mt12 {
+ margin-top: 12px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsApprovalBridge.js b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsApprovalBridge.js
new file mode 100644
index 0000000..b870ab7
--- /dev/null
+++ b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsApprovalBridge.js
@@ -0,0 +1,11 @@
+/** @deprecated 璇蜂娇鐢� enterpriseNewsMappers.js */
+export {
+ ENTERPRISE_NEWS_PAYLOAD_KEY,
+ buildEnterpriseNewsSaveDto,
+ buildEnterpriseNewsTableColumns,
+ canEditEnterpriseNewsRow,
+ extractEnterpriseNewsFromRow,
+ mapApiRowToNewsForm,
+ mapEnterpriseNewsFromApi,
+ syncNewsFormToSubmitPayload,
+} from "./enterpriseNewsMappers.js";
diff --git a/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsMappers.js b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsMappers.js
new file mode 100644
index 0000000..27cb9bc
--- /dev/null
+++ b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsMappers.js
@@ -0,0 +1,221 @@
+import {
+ createEmptyForm,
+ normalizeEnterpriseNewsStatus,
+ publishStatusLabel,
+ publishStatusTag,
+} from "./enterpriseNewsUtils.js";
+
+/** formPayload 涓瓨鏀惧畬鏁翠紒涓氭柊闂讳笟鍔℃暟鎹殑閿紙瀹℃壒瀹炰緥淇濆瓨鐢級 */
+export const ENTERPRISE_NEWS_PAYLOAD_KEY = "enterpriseNews";
+
+const READ_SCOPE_FROM_API = {
+ all: "all",
+ dept: "department",
+ department: "department",
+ custom: "custom",
+ management: "management",
+};
+
+const READ_SCOPE_TO_API = {
+ all: "all",
+ department: "dept",
+ dept: "dept",
+ custom: "custom",
+ management: "all",
+};
+
+export function mapReadScopeFromApi(scope) {
+ const key = String(scope ?? "").trim().toLowerCase();
+ return READ_SCOPE_FROM_API[key] || key || "all";
+}
+
+export function mapReadScopeToApi(scope) {
+ return READ_SCOPE_TO_API[scope] || scope || "all";
+}
+
+export function unwrapEnterpriseNewsPage(res) {
+ const data = res?.data ?? res;
+ if (!data || typeof data !== "object") {
+ return { records: [], total: 0 };
+ }
+ if (Array.isArray(data.records)) {
+ return { records: data.records, total: Number(data.total ?? 0) };
+ }
+ const nested = data.data;
+ if (nested && typeof nested === "object" && Array.isArray(nested.records)) {
+ return { records: nested.records, total: Number(nested.total ?? 0) };
+ }
+ return { records: [], total: 0 };
+}
+
+/** 缁勮 listPage 鏌ヨ鍙傛暟 */
+export function buildEnterpriseNewsListParams({ page, searchForm }) {
+ const params = {
+ current: page.current,
+ size: page.size,
+ };
+ const kw = (searchForm?.keyword || "").trim();
+ if (kw) params.title = kw;
+ if (searchForm?.newsType) params.category = searchForm.newsType;
+ if (searchForm?.status) params.status = searchForm.status;
+ const range = searchForm?.createTimeRange;
+ if (Array.isArray(range) && range[0]) {
+ params.createTimeStart = range[0];
+ }
+ if (Array.isArray(range) && range[1]) {
+ params.createTimeEnd = range[1];
+ }
+ return params;
+}
+
+/** 鎺ュ彛 EnterpriseNewsVo 鈫� 鍒楄〃琛� */
+export function mapEnterpriseNewsFromApi(row) {
+ if (!row) return {};
+ const newsStatus = normalizeEnterpriseNewsStatus(row.status);
+ return {
+ ...row,
+ newsNo: row.id != null ? String(row.id) : "鈥�",
+ newsType: row.category || "",
+ contentHtml: row.content || "",
+ publisherName: row.createUserName || "鈥�",
+ publishTime: row.createTime || "",
+ updateTime: row.updateTime || "",
+ newsStatus,
+ requireReadConfirm: row.isRequired === "1" || row.isRequired === 1,
+ readScope: mapReadScopeFromApi(row.readScope),
+ readCount: row.readCount ?? 0,
+ requiredReadCount: row.requiredReadCount ?? 0,
+ };
+}
+
+/** 鏄惁鍏佽淇敼锛堣崏绋裤�侀┏鍥炲彲鏀癸級 */
+export function canEditEnterpriseNewsRow(row) {
+ const status = normalizeEnterpriseNewsStatus(row?.newsStatus ?? row?.status);
+ return status === "DRAFT" || status === "REJECTED";
+}
+
+/** 鎺ュ彛琛� / 璇︽儏 鈫� 琛ㄥ崟 */
+export function mapApiRowToNewsForm(row) {
+ if (!row) return createEmptyForm();
+ return {
+ ...createEmptyForm(),
+ id: row.id != null ? String(row.id) : "",
+ newsNo: row.id != null ? String(row.id) : "",
+ title: row.title || "",
+ summary: row.summary || "",
+ contentHtml: row.content || row.contentHtml || "",
+ newsType: row.newsType || row.category || "announcement",
+ readScope: mapReadScopeFromApi(row.readScope),
+ requireReadConfirm: Boolean(row.requireReadConfirm ?? row.isRequired === "1"),
+ publisherName: row.createUserName || row.publisherName || "",
+ publishStatus: normalizeEnterpriseNewsStatus(row.newsStatus ?? row.status),
+ templateId: row.templateId,
+ templateName: row.templateName || "",
+ targetDeptIds: [...(row.deptIds || row.targetDeptIds || [])],
+ targetUserIds: [...(row.userIds || row.targetUserIds || [])],
+ };
+}
+
+/** 瀹℃壒瀹炰緥琛� formPayload 鈫� 琛ㄥ崟锛堝吋瀹规棫鏁版嵁锛� */
+export function extractEnterpriseNewsFromRow(row) {
+ if (!row?.formPayload && !row?.formFieldDefs && !row?.instanceNo) {
+ return mapApiRowToNewsForm(row);
+ }
+ const payload = row?.formPayload || {};
+ const raw = payload[ENTERPRISE_NEWS_PAYLOAD_KEY];
+ if (raw && typeof raw === "object") {
+ return { ...createEmptyForm(), ...raw };
+ }
+ return {
+ ...createEmptyForm(),
+ title: payload.title || row?.title || "",
+ summary: payload.summary || "",
+ newsType: payload.newsType || row?.category || "announcement",
+ contentHtml: payload.contentHtml || row?.content || "",
+ };
+}
+
+export function syncNewsFormToSubmitPayload(newsForm, submitForm) {
+ const snapshot = JSON.parse(JSON.stringify(newsForm));
+ submitForm.formPayload = {
+ ...(submitForm.formPayload || {}),
+ [ENTERPRISE_NEWS_PAYLOAD_KEY]: snapshot,
+ title: snapshot.title,
+ summary: snapshot.summary,
+ };
+}
+
+function toIdList(ids) {
+ if (!Array.isArray(ids) || !ids.length) return undefined;
+ const list = ids
+ .map((id) => (typeof id === "number" ? id : Number(id)))
+ .filter((n) => !Number.isNaN(n));
+ return list.length ? list : undefined;
+}
+
+/** 琛ㄥ崟 鈫� POST /enterpriseNews/save 璇锋眰浣� */
+export function buildEnterpriseNewsSaveDto(newsForm, { status } = {}) {
+ const dto = {
+ title: (newsForm.title || "").trim(),
+ summary: newsForm.summary || "",
+ content: newsForm.contentHtml || "",
+ category: newsForm.newsType || "",
+ readScope: mapReadScopeToApi(newsForm.readScope),
+ isRequired: newsForm.requireReadConfirm ? "1" : "0",
+ status: normalizeEnterpriseNewsStatus(status ?? newsForm.publishStatus),
+ };
+
+ const rawId = newsForm.id;
+ if (rawId != null && rawId !== "") {
+ const id = Number(rawId);
+ if (!Number.isNaN(id)) dto.id = id;
+ }
+
+ const deptIds = toIdList(newsForm.targetDeptIds);
+ if (deptIds) dto.deptIds = deptIds;
+
+ const userIds = toIdList(newsForm.targetUserIds);
+ if (userIds) dto.userIds = userIds;
+
+ const templateId = newsForm.templateId;
+ if (templateId != null && templateId !== "") {
+ const tid = Number(templateId);
+ if (!Number.isNaN(tid)) dto.templateId = tid;
+ }
+ if (newsForm.templateName) dto.templateName = newsForm.templateName;
+
+ return dto;
+}
+
+export function buildEnterpriseNewsTableColumns(buildTableActions) {
+ return [
+ { label: "缂栧彿", prop: "newsNo", width: 120 },
+ { label: "鏍囬", prop: "title", minWidth: 180, showOverflowTooltip: true },
+ {
+ label: "鍒嗙被",
+ prop: "newsType",
+ width: 100,
+ dataType: "slot",
+ slot: "newsType",
+ },
+ {
+ label: "鐘舵��",
+ prop: "newsStatus",
+ width: 100,
+ dataType: "tag",
+ formatData: (v) => publishStatusLabel(v),
+ formatType: (v) => publishStatusTag(v),
+ },
+ { label: "鍒涘缓浜�", prop: "publisherName", width: 110 },
+ { label: "鍒涘缓鏃堕棿", prop: "createTime", width: 170 },
+ { label: "鏇存柊鏃堕棿", prop: "updateTime", width: 170 },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 220,
+ operation: buildTableActions(),
+ },
+ ];
+}
diff --git a/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsUtils.js b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsUtils.js
new file mode 100644
index 0000000..9bc29c3
--- /dev/null
+++ b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsUtils.js
@@ -0,0 +1,207 @@
+import dayjs from "dayjs";
+
+/** 鏂伴椈鍒嗙被锛氱粺涓�淇℃伅鍑哄彛 */
+export const NEWS_TYPE_OPTIONS = [
+ { value: "announcement", label: "浼佷笟鍏憡", color: "#409eff" },
+ { value: "policy", label: "鏀跨瓥瑙h", color: "#e6a23c" },
+ { value: "industry", label: "琛屼笟鍔ㄦ��", color: "#909399" },
+ { value: "culture", label: "鏂囧寲娲诲姩", color: "#67c23a" },
+];
+
+/** 浼佷笟鏂伴椈鐘舵�侊紙涓庡悗绔灇涓句竴鑷达級 */
+export const PUBLISH_STATUS_OPTIONS = [
+ { value: "DRAFT", label: "鑽夌", tag: "info" },
+ { value: "PENDING", label: "寰呭鎵�", tag: "warning" },
+ { value: "PUBLISHED", label: "宸插彂甯�", tag: "success" },
+ { value: "REJECTED", label: "椹冲洖", tag: "danger" },
+ { value: "OFFLINE", label: "宸蹭笅绾�", tag: "info" },
+];
+
+/** 浼佷笟鏂伴椈鍒楄〃绛涢�� */
+export const ENTERPRISE_NEWS_STATUS_SEARCH_OPTIONS = [...PUBLISH_STATUS_OPTIONS];
+
+const LEGACY_PUBLISH_STATUS_MAP = {
+ draft: "DRAFT",
+ pending_review: "PENDING",
+ published: "PUBLISHED",
+ archived: "OFFLINE",
+};
+
+/** 鍚庣鏁板瓧鐘舵�佺爜 鈫� 鏋氫妇锛�0 鑽夌 1 寰呭鎵� 2 宸插彂甯� 3 椹冲洖 4 宸蹭笅绾匡級 */
+const ENTERPRISE_NEWS_STATUS_NUMERIC_MAP = {
+ 0: "DRAFT",
+ 1: "PENDING",
+ 2: "PUBLISHED",
+ 3: "REJECTED",
+ 4: "OFFLINE",
+};
+
+const ENTERPRISE_NEWS_STATUS_LABEL_MAP = {
+ 鑽夌: "DRAFT",
+ 寰呭鎵�: "PENDING",
+ 宸插彂甯�: "PUBLISHED",
+ 椹冲洖: "REJECTED",
+ 宸查┏鍥�: "REJECTED",
+ 宸蹭笅绾�: "OFFLINE",
+};
+
+/** 缁熶竴涓哄悗绔姸鎬佹灇涓惧�� */
+export function normalizeEnterpriseNewsStatus(v) {
+ if (v == null || v === "") return "DRAFT";
+ if (typeof v === "number" || (typeof v === "string" && /^\d+$/.test(v.trim()))) {
+ const numKey = ENTERPRISE_NEWS_STATUS_NUMERIC_MAP[Number(v)];
+ if (numKey) return numKey;
+ }
+ const raw = String(v).trim();
+ if (ENTERPRISE_NEWS_STATUS_LABEL_MAP[raw]) {
+ return ENTERPRISE_NEWS_STATUS_LABEL_MAP[raw];
+ }
+ const upper = raw.toUpperCase();
+ if (upper === "APPROVED") return "PUBLISHED";
+ const hit = PUBLISH_STATUS_OPTIONS.find((x) => x.value === upper);
+ if (hit) return hit.value;
+ const legacy = LEGACY_PUBLISH_STATUS_MAP[raw.toLowerCase()];
+ if (legacy) return legacy;
+ return upper;
+}
+
+/** 鎺掔増妯℃澘 */
+export const LAYOUT_TEMPLATE_OPTIONS = [
+ { value: "standard", label: "鏍囧噯鍥炬枃" },
+ { value: "policy", label: "鏀跨瓥鏉℃枃" },
+ { value: "gallery", label: "鍥鹃泦鐩稿唽" },
+ { value: "briefing", label: "绠�鎶ユ憳瑕�" },
+];
+
+/** 闃呰鍙鑼冨洿 */
+export const READ_SCOPE_OPTIONS = [
+ { value: "all", label: "鍏ㄥ憳鍙" },
+ { value: "management", label: "绠$悊灞�" },
+ { value: "department", label: "鎸囧畾閮ㄩ棬" },
+ { value: "custom", label: "鑷畾涔夊悕鍗�" },
+];
+
+/** 缂栬緫/瀹℃牳瑙掕壊锛堝彂甯冩潈闄愶級 */
+export const PUBLISH_ROLE_OPTIONS = [
+ { value: "hr", label: "HR锛堜汉浜嬫斂绛栵級" },
+ { value: "admin", label: "绠$悊鍛橈紙澶栭儴鏂伴椈瀹℃牳锛�" },
+ { value: "dept_manager", label: "閮ㄩ棬璐熻矗浜�" },
+ { value: "editor", label: "鍐呭缂栬緫" },
+];
+
+/** 鐩爣鍙椾紬锛堝鎺ョ粍缁囨灦鏋� API 鍓嶄负绌猴級 */
+export const MOCK_AUDIENCE = [];
+
+const DEPT_OPTIONS = [
+ { value: "101", label: "鐮斿彂閮�" },
+ { value: "102", label: "閿�鍞儴" },
+ { value: "103", label: "琛屾斂閮�" },
+ { value: "104", label: "璐㈠姟閮�" },
+ { value: "105", label: "鎬荤粡鍔�" },
+ { value: "106", label: "浜哄姏璧勬簮閮�" },
+];
+
+export { DEPT_OPTIONS };
+
+export function newsTypeLabel(v) {
+ return NEWS_TYPE_OPTIONS.find((x) => x.value === v)?.label || v || "鈥�";
+}
+
+export function newsTypeColor(v) {
+ return NEWS_TYPE_OPTIONS.find((x) => x.value === v)?.color || "#909399";
+}
+
+export function publishStatusLabel(v) {
+ const key = normalizeEnterpriseNewsStatus(v);
+ return PUBLISH_STATUS_OPTIONS.find((x) => x.value === key)?.label || v || "鈥�";
+}
+
+export function publishStatusTag(v) {
+ const key = normalizeEnterpriseNewsStatus(v);
+ return PUBLISH_STATUS_OPTIONS.find((x) => x.value === key)?.tag || "info";
+}
+
+export function layoutTemplateLabel(v) {
+ return LAYOUT_TEMPLATE_OPTIONS.find((x) => x.value === v)?.label || v || "鈥�";
+}
+
+export function readScopeLabel(v) {
+ return READ_SCOPE_OPTIONS.find((x) => x.value === v)?.label || v || "鈥�";
+}
+
+export function publishRoleLabel(v) {
+ return PUBLISH_ROLE_OPTIONS.find((x) => x.value === v)?.label || v || "鈥�";
+}
+
+export function createEmptyForm() {
+ return {
+ id: "",
+ newsNo: "",
+ title: "",
+ summary: "",
+ newsType: "announcement",
+ layoutTemplate: "standard",
+ contentHtml: "",
+ coverImage: "",
+ mediaList: [],
+ attachmentList: [],
+ editorRole: "hr",
+ reviewerRole: "admin",
+ readScope: "all",
+ targetDeptIds: [],
+ targetUserIds: [],
+ publishStatus: "DRAFT",
+ publisherName: "",
+ publishTime: "",
+ readRecords: [],
+ remindLogs: [],
+ likes: [],
+ comments: [],
+ versions: [],
+ versionNo: 1,
+ requireReadConfirm: false,
+ templateId: null,
+ templateName: "",
+ };
+}
+
+/** 鎸夐槄璇昏寖鍥磋В鏋愮洰鏍囧彈浼� */
+export function resolveTargetAudience(row) {
+ const scope = row.readScope || "all";
+ if (scope === "management") {
+ return MOCK_AUDIENCE.filter((u) => u.isManagement);
+ }
+ if (scope === "department" && row.targetDeptIds?.length) {
+ const names = DEPT_OPTIONS.filter((d) => row.targetDeptIds.includes(d.value)).map((d) => d.label);
+ return MOCK_AUDIENCE.filter((u) => names.includes(u.deptName));
+ }
+ if (scope === "custom" && row.targetUserIds?.length) {
+ return MOCK_AUDIENCE.filter((u) => row.targetUserIds.includes(u.userId));
+ }
+ return [...MOCK_AUDIENCE];
+}
+
+export function getUnreadEmployees(row) {
+ const audience = resolveTargetAudience(row);
+ const readSet = new Set(
+ (row.readRecords || []).filter((r) => r.readAt).map((r) => r.userId)
+ );
+ return audience.filter((u) => !readSet.has(u.userId));
+}
+
+export function readRate(row) {
+ const audience = resolveTargetAudience(row);
+ if (!audience.length) return 0;
+ const readCount = (row.readRecords || []).filter((r) => r.readAt).length;
+ return Math.round((readCount / audience.length) * 100);
+}
+
+export function validateNewsForm(form) {
+ const title = (form.title || "").trim();
+ if (!title) return { ok: false, message: "璇峰~鍐欐柊闂绘爣棰�" };
+ if (!form.newsType) return { ok: false, message: "璇烽�夋嫨鏂伴椈鍒嗙被" };
+ if (form.readScope === "department" && !(form.targetDeptIds || []).length) {
+ return { ok: false, message: "璇烽�夋嫨鍙閮ㄩ棬" };
+ }
+ return { ok: true, title };
+}
diff --git a/src/views/officeProcessAutomation/EnterpriseNews/news-manage/index.vue b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/index.vue
new file mode 100644
index 0000000..f263a41
--- /dev/null
+++ b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/index.vue
@@ -0,0 +1,566 @@
+<!--OA妯″潡锛欵nterpriseNews 浼佷笟鏂伴椈锛坙istPage|save|update|delete锛屾柊寤轰繚鐣欏鎵规ā鏉匡級-->
+<template>
+ <div class="app-container enterprise-news-page">
+ <div class="search_form mb20">
+ <div class="search_fields">
+ <span class="search_title">鍏抽敭璇嶏細</span>
+ <el-input
+ v-model="searchForm.keyword"
+ style="width: 200px"
+ placeholder="鏍囬"
+ clearable
+ :prefix-icon="Search"
+ @keyup.enter="onSearch"
+ />
+ <span class="search_title" style="margin-left: 12px">鍒嗙被锛�</span>
+ <el-select v-model="searchForm.newsType" placeholder="鍏ㄩ儴" clearable style="width: 140px">
+ <el-option v-for="opt in NEWS_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
+ </el-select>
+ <span class="search_title" style="margin-left: 12px">鐘舵�侊細</span>
+ <el-select v-model="searchForm.status" placeholder="鍏ㄩ儴" clearable style="width: 120px">
+ <el-option
+ v-for="opt in ENTERPRISE_NEWS_STATUS_SEARCH_OPTIONS"
+ :key="opt.value"
+ :label="opt.label"
+ :value="opt.value"
+ />
+ </el-select>
+ <span class="search_title" style="margin-left: 12px">鍒涘缓鏃堕棿锛�</span>
+ <el-date-picker
+ v-model="searchForm.createTimeRange"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮�"
+ end-placeholder="缁撴潫"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ style="width: 260px"
+ clearable
+ />
+ <el-button type="primary" :icon="Search" class="ml10" @click="onSearch">鎼滅储</el-button>
+ <el-button :icon="RefreshRight" @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div class="search_actions">
+ <el-button type="primary" :icon="Plus" @click="openAddWithTemplate">鏂板缓鏂伴椈</el-button>
+ </div>
+ </div>
+
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ :total="page.total"
+ @pagination="onPagination"
+ >
+ <template #newsType="{ row }">
+ <span class="news-type-tag" :style="{ color: newsTypeColor(row.newsType) }">
+ {{ newsTypeLabel(row.newsType) }}
+ </span>
+ </template>
+ </PIMTable>
+ </div>
+
+ <ApprovalTemplateBindDialog
+ v-model:visible="templateBindVisible"
+ :module-key="APPROVAL_MODULE_KEYS.ENTERPRISE_NEWS"
+ skip-form-confirm
+ @confirm="onTemplateBound"
+ @closed="onTemplateBindClosed"
+ />
+
+ <el-dialog
+ v-model="newsFormDialog.visible"
+ :title="newsFormDialog.title"
+ width="960px"
+ append-to-body
+ destroy-on-close
+ class="news-form-dialog"
+ @closed="onNewsFormClosed"
+ >
+ <el-form
+ ref="newsFormRef"
+ :model="newsForm"
+ :rules="newsFormRules"
+ label-width="110px"
+ :disabled="newsFormDialog.readonly"
+ >
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鏂伴椈鍒嗙被" prop="newsType">
+ <el-select v-model="newsForm.newsType" placeholder="璇烽�夋嫨" style="width: 100%">
+ <el-option v-for="opt in NEWS_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎺掔増妯℃澘">
+ <el-select v-model="newsForm.layoutTemplate" style="width: 100%">
+ <el-option
+ v-for="opt in LAYOUT_TEMPLATE_OPTIONS"
+ :key="opt.value"
+ :label="opt.label"
+ :value="opt.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="鏍囬" prop="title">
+ <el-input v-model="newsForm.title" placeholder="鏂伴椈鏍囬" maxlength="100" show-word-limit />
+ </el-form-item>
+ <el-form-item label="鎽樿">
+ <el-input v-model="newsForm.summary" type="textarea" :rows="2" maxlength="300" show-word-limit />
+ </el-form-item>
+ <el-form-item label="姝f枃" prop="contentHtml">
+ <Editor v-model="newsForm.contentHtml" :min-height="280" />
+ </el-form-item>
+ <el-form-item label="闄勪欢">
+ <FileUpload v-model:file-list="newsForm.attachmentList" :limit="10" button-text="涓婁紶 PDF / 鏂囨。" />
+ </el-form-item>
+ <el-form-item v-if="newsForm.layoutTemplate === 'gallery'" label="鍥鹃泦/瑙嗛">
+ <el-input
+ v-model="galleryInput"
+ placeholder="杈撳叆璧勬簮鍚嶇О鍚庡洖杞︽坊鍔狅紙婕旂ず锛�"
+ @keyup.enter="addGalleryItem"
+ />
+ <el-tag
+ v-for="(m, i) in newsForm.mediaList"
+ :key="i"
+ closable
+ class="media-tag"
+ @close="newsForm.mediaList.splice(i, 1)"
+ >
+ {{ m.name }}
+ </el-tag>
+ </el-form-item>
+
+ <el-divider content-position="left">鏉冮檺绠℃帶</el-divider>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="缂栬緫瑙掕壊">
+ <el-select v-model="newsForm.editorRole" style="width: 100%">
+ <el-option v-for="opt in PUBLISH_ROLE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀹℃牳瑙掕壊">
+ <el-select v-model="newsForm.reviewerRole" style="width: 100%">
+ <el-option v-for="opt in PUBLISH_ROLE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="闃呰鑼冨洿" prop="readScope">
+ <el-radio-group v-model="newsForm.readScope">
+ <el-radio v-for="opt in READ_SCOPE_OPTIONS" :key="opt.value" :value="opt.value">
+ {{ opt.label }}
+ </el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item v-if="newsForm.readScope === 'department'" label="鍙閮ㄩ棬">
+ <el-select v-model="newsForm.targetDeptIds" multiple placeholder="閫夋嫨閮ㄩ棬" style="width: 100%">
+ <el-option v-for="d in DEPT_OPTIONS" :key="d.value" :label="d.label" :value="d.value" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鏀跨瓥绫诲繀璇�">
+ <el-switch v-model="newsForm.requireReadConfirm" active-text="闇�闃呰纭锛堜究浜庣粺璁℃湭璇伙級" />
+ </el-form-item>
+
+ <template v-if="hasApprovalTemplate">
+ <el-divider content-position="left">瀹℃壒娴佺▼</el-divider>
+ <el-form-item label="瀹℃壒妯℃澘">
+ <span class="template-name">{{ approvalTemplateLabel }}</span>
+ </el-form-item>
+ <el-form-item v-if="activeTemplate" label="瀹℃壒娴佺▼" required>
+ <TemplateFlowEditor v-model="submitForm.flowNodes" :user-options="flowUserOptions" />
+ <p class="section-tip">娴佺▼涓庡鎵逛汉鐢辨ā鏉块缃紝鍙寜闇�寰皟鑺傜偣瀹℃壒浜恒��</p>
+ </el-form-item>
+ </template>
+ <el-alert
+ v-else-if="!isNewsEdit"
+ type="warning"
+ show-icon
+ :closable="false"
+ title="璇峰厛閫氳繃銆屾柊寤烘柊闂汇�嶉�夋嫨瀹℃壒妯℃澘"
+ />
+ </el-form>
+ <template v-if="!newsFormDialog.readonly" #footer>
+ <el-button @click="newsFormDialog.visible = false">鍙� 娑�</el-button>
+ <el-button :loading="newsSaving" @click="onNewsSave('draft')">瀛樿崏绋�</el-button>
+ <el-button type="warning" :loading="newsSaving" @click="onNewsSave('submit_review')">
+ 鎻愪氦瀹℃牳
+ </el-button>
+ <el-button type="primary" :loading="newsSaving" @click="onNewsSave('submit_review')">
+ 淇� 瀛�
+ </el-button>
+ </template>
+ </el-dialog>
+
+ <el-dialog v-model="detailDialog.visible" title="鏂伴椈璇︽儏" width="880px" append-to-body destroy-on-close>
+ <NewsDetailPanel :row="detailNewsRow" />
+ <template #footer>
+ <el-button v-if="canEditEnterpriseNewsRow(detailRow)" type="primary" @click="openNewsEditFromDetail">
+ 淇敼
+ </el-button>
+ <el-button @click="detailDialog.visible = false">鍏� 闂�</el-button>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { Plus, RefreshRight, Search } from "@element-plus/icons-vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import {
+ deleteEnterpriseNews,
+ saveEnterpriseNews,
+ updateEnterpriseNews,
+} from "@/api/officeProcessAutomation/enterpriseNews.js";
+import { computed, onMounted, reactive, ref } from "vue";
+import Editor from "@/components/Editor/index.vue";
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
+import TemplateFlowEditor from "../../ApproveManage/approve-template/components/TemplateFlowEditor.vue";
+import {
+ applyBindingToForm,
+ validateTemplateBinding,
+} from "../../ApproveManage/approve-shared/approvalTemplateBindingUtils.js";
+import { createEmptySubmitForm } from "../../ApproveManage/approve-list/approveListConstants.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
+import NewsDetailPanel from "./components/NewsDetailPanel.vue";
+import {
+ NEWS_TYPE_OPTIONS,
+ LAYOUT_TEMPLATE_OPTIONS,
+ READ_SCOPE_OPTIONS,
+ PUBLISH_ROLE_OPTIONS,
+ DEPT_OPTIONS,
+ createEmptyForm,
+ ENTERPRISE_NEWS_STATUS_SEARCH_OPTIONS,
+ newsTypeColor,
+ newsTypeLabel,
+ validateNewsForm,
+} from "./enterpriseNewsUtils.js";
+import {
+ buildEnterpriseNewsSaveDto,
+ buildEnterpriseNewsTableColumns,
+ canEditEnterpriseNewsRow,
+ mapApiRowToNewsForm,
+} from "./enterpriseNewsMappers.js";
+import { useEnterpriseNewsList } from "./useEnterpriseNewsList.js";
+
+const searchForm = reactive({
+ keyword: "",
+ newsType: "",
+ status: "",
+ createTimeRange: null,
+});
+
+const newsFormDialog = reactive({ visible: false, title: "", mode: "add", readonly: false });
+const detailDialog = reactive({ visible: false });
+const detailRow = ref({});
+const newsForm = reactive(createEmptyForm());
+const newsFormRef = ref();
+const galleryInput = ref("");
+
+const newsFormRules = {
+ title: [{ required: true, message: "璇疯緭鍏ユ柊闂绘爣棰�", trigger: "blur" }],
+ newsType: [{ required: true, message: "璇烽�夋嫨鏂伴椈鍒嗙被", trigger: "change" }],
+ readScope: [{ required: true, message: "璇烽�夋嫨闃呰鑼冨洿", trigger: "change" }],
+};
+
+const newsList = useEnterpriseNewsList();
+const { tableData, tableLoading, page, handleQuery: fetchNewsList, pagination: paginateNewsList } =
+ newsList;
+
+const submitForm = reactive(createEmptySubmitForm(""));
+const templateBindVisible = ref(false);
+const pendingTemplateBinding = ref(null);
+const newsSaving = ref(false);
+
+const isNewsEdit = computed(() => newsFormDialog.mode === "edit");
+const activeTemplate = computed(() => submitForm.templateSnapshot || null);
+const hasApprovalTemplate = computed(
+ () => Boolean(activeTemplate.value || newsForm.templateId)
+);
+const approvalTemplateLabel = computed(
+ () =>
+ activeTemplate.value?.label ||
+ newsForm.templateName ||
+ submitForm.templateName ||
+ "鈥�"
+);
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+function openAddWithTemplate() {
+ pendingTemplateBinding.value = null;
+ templateBindVisible.value = true;
+}
+
+function onTemplateBound(binding) {
+ pendingTemplateBinding.value = binding;
+}
+
+function resetSubmitForm() {
+ Object.assign(submitForm, createEmptySubmitForm(""));
+}
+
+const detailNewsRow = computed(() => mapApiRowToNewsForm(detailRow.value));
+
+const tableColumn = ref(
+ buildEnterpriseNewsTableColumns(() => [
+ { name: "璇︽儏", type: "text", clickFun: (row) => openNewsDetail(row) },
+ {
+ name: "淇敼",
+ type: "text",
+ disabled: (row) => !canEditEnterpriseNewsRow(row),
+ clickFun: (row) => openNewsEdit(row),
+ },
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ disabled: (row) => !canEditEnterpriseNewsRow(row),
+ clickFun: (row) => handleNewsDelete(row),
+ },
+ ])
+);
+
+function resetNewsForm(target = createEmptyForm()) {
+ Object.assign(newsForm, createEmptyForm(), target);
+}
+
+function openNewsFormDialog(mode, row) {
+ newsFormDialog.mode = mode;
+ newsFormDialog.readonly = mode === "view";
+ newsFormDialog.title =
+ mode === "add" ? "鏂板缓浼佷笟鏂伴椈" : mode === "edit" ? "缂栬緫浼佷笟鏂伴椈" : "鏌ョ湅浼佷笟鏂伴椈";
+ if (mode === "add") {
+ resetNewsForm();
+ } else if (row) {
+ resetNewsForm(mapApiRowToNewsForm(row));
+ }
+ newsFormDialog.visible = true;
+}
+
+function onTemplateBindClosed() {
+ const binding = pendingTemplateBinding.value;
+ if (!binding) return;
+ pendingTemplateBinding.value = null;
+ resetSubmitForm();
+ applyBindingToForm(submitForm, binding);
+ if (binding.templateId) {
+ newsForm.templateId = binding.templateId;
+ newsForm.templateName = binding.templateName || "";
+ }
+ openNewsFormDialog("add");
+}
+
+function openNewsEdit(row) {
+ if (!canEditEnterpriseNewsRow(row)) {
+ ElMessage.warning("褰撳墠鐘舵�佷笉鍙慨鏀�");
+ return;
+ }
+ resetSubmitForm();
+ if (row?.templateId != null) {
+ submitForm.templateId = row.templateId;
+ submitForm.templateName = row.templateName || "";
+ }
+ openNewsFormDialog("edit", row);
+}
+
+function openNewsDetail(row) {
+ detailRow.value = { ...row };
+ detailDialog.visible = true;
+}
+
+function openNewsEditFromDetail() {
+ const row = detailRow.value;
+ detailDialog.visible = false;
+ openNewsEdit(row);
+}
+
+async function handleNewsDelete(row) {
+ if (!canEditEnterpriseNewsRow(row)) {
+ ElMessage.warning("褰撳墠鐘舵�佷笉鍙垹闄�");
+ return;
+ }
+ if (row?.id == null || row.id === "") {
+ ElMessage.warning("鏃犳硶鍒犻櫎锛氱己灏戞柊闂� ID");
+ return;
+ }
+ const title = (row.title || "").trim() || "璇ユ潯鏂伴椈";
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゃ��${title}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+ "鍒犻櫎纭",
+ {
+ type: "warning",
+ confirmButtonText: "纭畾鍒犻櫎",
+ cancelButtonText: "鍙栨秷",
+ distinguishCancelAndClose: true,
+ autofocus: false,
+ }
+ );
+ } catch {
+ return;
+ }
+ try {
+ await deleteEnterpriseNews([row.id]);
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ await fetchNewsList(searchForm);
+ } catch {
+ /* 閿欒鐢辫姹傛嫤鎴櫒鎻愮ず */
+ }
+}
+
+function onNewsFormClosed() {
+ newsFormRef.value?.resetFields?.();
+}
+
+function addGalleryItem() {
+ const name = (galleryInput.value || "").trim();
+ if (!name) return;
+ newsForm.mediaList = newsForm.mediaList || [];
+ newsForm.mediaList.push({ type: "image", name, url: "" });
+ galleryInput.value = "";
+}
+
+async function onNewsSave(action = "submit_review") {
+ try {
+ await newsFormRef.value?.validate();
+ } catch {
+ ElMessage.warning("璇峰畬鍠勮〃鍗曞繀濉」鍚庡啀淇濆瓨");
+ return;
+ }
+ const v = validateNewsForm(newsForm);
+ if (!v.ok) {
+ ElMessage.warning(v.message);
+ return;
+ }
+ const status = action === "draft" ? "DRAFT" : "PENDING";
+ newsForm.publishStatus = status;
+
+ if (!isNewsEdit.value) {
+ const templateId = newsForm.templateId || submitForm.templateId;
+ if (!templateId) {
+ ElMessage.warning("璇峰厛閫夋嫨瀹℃壒妯℃澘");
+ return;
+ }
+ if (!newsForm.templateId) newsForm.templateId = templateId;
+ if (!newsForm.templateName && submitForm.templateName) {
+ newsForm.templateName = submitForm.templateName;
+ }
+ if (action !== "draft") {
+ const bindingCheck = validateTemplateBinding({ flowNodes: submitForm.flowNodes });
+ if (!bindingCheck.ok) {
+ ElMessage.warning(bindingCheck.message);
+ return;
+ }
+ }
+ } else if (!newsForm.templateId && submitForm.templateId) {
+ newsForm.templateId = submitForm.templateId;
+ newsForm.templateName = submitForm.templateName || newsForm.templateName;
+ }
+
+ const dto = buildEnterpriseNewsSaveDto(newsForm, { status });
+ if (isNewsEdit.value) {
+ if (dto.id == null) {
+ ElMessage.warning("鏃犳硶淇敼锛氱己灏戞柊闂� ID");
+ return;
+ }
+ }
+
+ if (newsSaving.value) return;
+ newsSaving.value = true;
+ try {
+ if (isNewsEdit.value) {
+ await updateEnterpriseNews(dto);
+ } else {
+ await saveEnterpriseNews(dto);
+ }
+ newsFormDialog.visible = false;
+ const msg =
+ action === "draft" ? "宸蹭繚瀛樿崏绋�" : isNewsEdit.value ? "淇敼鎴愬姛" : "宸叉彁浜ゅ鏍�";
+ ElMessage.success(msg);
+ if (!isNewsEdit.value) page.current = 1;
+ await fetchNewsList(searchForm);
+ } catch {
+ /* 閿欒鐢辫姹傛嫤鎴櫒鎻愮ず */
+ } finally {
+ newsSaving.value = false;
+ }
+}
+
+function onSearch() {
+ fetchNewsList(searchForm);
+}
+
+function resetSearch() {
+ searchForm.keyword = "";
+ searchForm.newsType = "";
+ searchForm.status = "";
+ searchForm.createTimeRange = null;
+ onSearch();
+}
+
+function onPagination(obj) {
+ paginateNewsList(obj, searchForm);
+}
+
+onMounted(() => {
+ loadFlowUsers();
+ fetchNewsList(searchForm);
+});
+</script>
+
+<style scoped>
+.enterprise-news-page .search_form {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: flex-start;
+ gap: 12px;
+}
+.search_fields {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 4px;
+}
+.search_actions {
+ flex-shrink: 0;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+.news-type-tag {
+ font-weight: 600;
+ font-size: 13px;
+}
+.media-tag {
+ margin: 6px 8px 0 0;
+}
+.template-name {
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+}
+.section-tip {
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ margin: 8px 0 0;
+ line-height: 1.5;
+}
+.mb20 {
+ margin-bottom: 20px;
+}
+.ml10 {
+ margin-left: 10px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/EnterpriseNews/news-manage/useEnterpriseNewsList.js b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/useEnterpriseNewsList.js
new file mode 100644
index 0000000..66aef1e
--- /dev/null
+++ b/src/views/officeProcessAutomation/EnterpriseNews/news-manage/useEnterpriseNewsList.js
@@ -0,0 +1,55 @@
+import { listEnterpriseNewsPage } from "@/api/officeProcessAutomation/enterpriseNews.js";
+import { ElMessage } from "element-plus";
+import { reactive, ref } from "vue";
+import {
+ buildEnterpriseNewsListParams,
+ mapEnterpriseNewsFromApi,
+ unwrapEnterpriseNewsPage,
+} from "./enterpriseNewsMappers.js";
+
+/** 浼佷笟鏂伴椈鍒楄〃锛氬垎椤垫煡璇� /enterpriseNews/listPage */
+export function useEnterpriseNewsList() {
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+ const page = reactive({ current: 1, size: 10, total: 0 });
+ let lastSearchForm = null;
+
+ async function fetchList(searchForm = {}) {
+ tableLoading.value = true;
+ try {
+ const res = await listEnterpriseNewsPage(
+ buildEnterpriseNewsListParams({ page, searchForm })
+ );
+ const { records, total } = unwrapEnterpriseNewsPage(res);
+ tableData.value = records.map(mapEnterpriseNewsFromApi);
+ page.total = total;
+ } catch {
+ tableData.value = [];
+ page.total = 0;
+ ElMessage.error("浼佷笟鏂伴椈鍒楄〃鍔犺浇澶辫触");
+ } finally {
+ tableLoading.value = false;
+ }
+ }
+
+ function handleQuery(searchForm) {
+ lastSearchForm = searchForm;
+ page.current = 1;
+ return fetchList(searchForm);
+ }
+
+ function pagination({ page: p, limit }, searchForm) {
+ page.current = p;
+ page.size = limit;
+ return fetchList(searchForm ?? lastSearchForm ?? {});
+ }
+
+ return {
+ tableData,
+ tableLoading,
+ page,
+ fetchList,
+ handleQuery,
+ pagination,
+ };
+}
diff --git a/src/views/officeProcessAutomation/HrManage/post-manage/index.vue b/src/views/officeProcessAutomation/HrManage/post-manage/index.vue
new file mode 100644
index 0000000..a57137c
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/post-manage/index.vue
@@ -0,0 +1,292 @@
+<!--OA妯″潡锛氬矖浣嶇鐞�-->
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
+ <el-form-item label="宀椾綅缂栫爜" prop="postCode">
+ <el-input
+ v-model="queryParams.postCode"
+ placeholder="璇疯緭鍏ュ矖浣嶇紪鐮�"
+ clearable
+ style="width: 200px"
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="宀椾綅鍚嶇О" prop="postName">
+ <el-input
+ v-model="queryParams.postName"
+ placeholder="璇疯緭鍏ュ矖浣嶅悕绉�"
+ clearable
+ style="width: 200px"
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select v-model="queryParams.status" placeholder="宀椾綅鐘舵��" clearable style="width: 200px">
+ <el-option
+ v-for="dict in sys_normal_disable"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="handleAdd"
+ v-hasPermi="['system:post:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="success"
+ plain
+ icon="Edit"
+ :disabled="single"
+ @click="handleUpdate"
+ v-hasPermi="['system:post:edit']"
+ >淇敼</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="danger"
+ plain
+ icon="Delete"
+ :disabled="multiple"
+ @click="handleDelete"
+ v-hasPermi="['system:post:remove']"
+ >鍒犻櫎</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="warning"
+ plain
+ icon="Download"
+ @click="handleExport"
+ v-hasPermi="['system:post:export']"
+ >瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column label="宀椾綅缂栧彿" align="center" prop="postId" />
+ <el-table-column label="宀椾綅缂栫爜" align="center" prop="postCode" />
+ <el-table-column label="宀椾綅鍚嶇О" align="center" prop="postName" />
+ <el-table-column label="宀椾綅鎺掑簭" align="center" prop="postSort" />
+ <el-table-column label="鐘舵��" align="center" prop="status">
+ <template #default="scope">
+ <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.createTime) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="180" align="center" class-name="small-padding fixed-width">
+ <template #default="scope">
+ <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:post:edit']">淇敼</el-button>
+ <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:post:remove']">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ v-model:page="queryParams.pageNum"
+ v-model:limit="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 娣诲姞鎴栦慨鏀瑰矖浣嶅璇濇 -->
+ <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+ <el-form ref="postRef" :model="form" :rules="rules" label-width="80px">
+ <el-form-item label="宀椾綅鍚嶇О" prop="postName">
+ <el-input v-model="form.postName" placeholder="璇疯緭鍏ュ矖浣嶅悕绉�" />
+ </el-form-item>
+ <el-form-item label="宀椾綅缂栫爜" prop="postCode">
+ <el-input v-model="form.postCode" placeholder="璇疯緭鍏ョ紪鐮佸悕绉�" />
+ </el-form-item>
+ <el-form-item label="宀椾綅椤哄簭" prop="postSort">
+ <el-input-number v-model="form.postSort" controls-position="right" :min="0" />
+ </el-form-item>
+ <el-form-item label="宀椾綅鐘舵��" prop="status">
+ <el-radio-group v-model="form.status">
+ <el-radio
+ v-for="dict in sys_normal_disable"
+ :key="dict.value"
+ :value="dict.value"
+ >{{ dict.label }}</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+ <el-button @click="cancel">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup name="Post">
+import { listPost, addPost, delPost, getPost, updatePost } from "@/api/system/post"
+import {onMounted} from "vue";
+
+const { proxy } = getCurrentInstance()
+const { sys_normal_disable } = proxy.useDict("sys_normal_disable")
+
+const postList = ref([])
+const open = ref(false)
+const loading = ref(true)
+const showSearch = ref(true)
+const ids = ref([])
+const single = ref(true)
+const multiple = ref(true)
+const total = ref(0)
+const title = ref("")
+
+const data = reactive({
+ form: {},
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ postCode: undefined,
+ postName: undefined,
+ status: undefined
+ },
+ rules: {
+ postName: [{ required: true, message: "宀椾綅鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }],
+ postCode: [{ required: true, message: "宀椾綅缂栫爜涓嶈兘涓虹┖", trigger: "blur" }],
+ postSort: [{ required: true, message: "宀椾綅椤哄簭涓嶈兘涓虹┖", trigger: "blur" }],
+ }
+})
+
+const { queryParams, form, rules } = toRefs(data)
+
+/** 鏌ヨ宀椾綅鍒楄〃 */
+function getList() {
+ loading.value = true
+ listPost(queryParams.value).then(response => {
+ postList.value = response.rows
+ total.value = response.total
+ loading.value = false
+ })
+}
+
+/** 鍙栨秷鎸夐挳 */
+function cancel() {
+ open.value = false
+ reset()
+}
+
+/** 琛ㄥ崟閲嶇疆 */
+function reset() {
+ form.value = {
+ postId: undefined,
+ postCode: undefined,
+ postName: undefined,
+ postSort: 0,
+ status: "0",
+ remark: undefined
+ }
+ proxy.resetForm("postRef")
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+ queryParams.value.pageNum = 1
+ getList()
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+ proxy.resetForm("queryRef")
+ handleQuery()
+}
+
+/** 澶氶�夋閫変腑鏁版嵁 */
+function handleSelectionChange(selection) {
+ ids.value = selection.map(item => item.postId)
+ single.value = selection.length != 1
+ multiple.value = !selection.length
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd() {
+ reset()
+ open.value = true
+ title.value = "娣诲姞宀椾綅"
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+ reset()
+ const postId = row.postId || ids.value
+ getPost(postId).then(response => {
+ form.value = response.data
+ open.value = true
+ title.value = "淇敼宀椾綅"
+ })
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+ proxy.$refs["postRef"].validate(valid => {
+ if (valid) {
+ if (form.value.postId != undefined) {
+ updatePost(form.value).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ open.value = false
+ getList()
+ })
+ } else {
+ addPost(form.value).then(response => {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛")
+ open.value = false
+ getList()
+ })
+ }
+ }
+ })
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+ const postIds = row.postId || ids.value
+ proxy.$modal.confirm('鏄惁纭鍒犻櫎宀椾綅缂栧彿涓�"' + postIds + '"鐨勬暟鎹」锛�').then(function() {
+ return delPost(postIds)
+ }).then(() => {
+ getList()
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
+ }).catch(() => {})
+}
+
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+ proxy.download("system/post/export", {
+ ...queryParams.value
+ }, `post_${new Date().getTime()}.xlsx`)
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
diff --git a/src/views/officeProcessAutomation/HrManage/regular-apply/index.vue b/src/views/officeProcessAutomation/HrManage/regular-apply/index.vue
new file mode 100644
index 0000000..291d57d
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/regular-apply/index.vue
@@ -0,0 +1,174 @@
+<!--OA妯″潡锛氳浆姝g敵璇�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">瀹℃壒鍗曞彿锛�</span>
+ <el-input
+ v-model="searchForm.instanceNo"
+ style="width: 220px"
+ placeholder="璇疯緭鍏ュ鎵瑰崟鍙�"
+ clearable
+ @keyup.enter="onSearch"
+ />
+ <span class="search_title" style="margin-left: 12px">鐢宠浜猴細</span>
+ <el-input
+ v-model="searchForm.applicantName"
+ style="width: 220px"
+ placeholder="璇疯緭鍏ョ敵璇蜂汉"
+ clearable
+ :prefix-icon="Search"
+ @keyup.enter="onSearch"
+ />
+ <el-button type="primary" style="margin-left: 10px" @click="onSearch">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" @click="openAddWithTemplate">鏂板杞鐢宠</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ @pagination="onPagination"
+ :total="page.total"
+ />
+ </div>
+
+ <ApprovalInstanceSubmitDialog
+ v-model="submitDialog.visible"
+ :title="submitDialogTitle"
+ :form="submitForm"
+ :rules="submitFormRules"
+ :fields="submitFormFields"
+ :active-template="activeTemplate"
+ :user-options="flowUserOptions"
+ :is-edit="isSubmitEdit"
+ :saving="submitSaving"
+ :form-ref="submitFormRef"
+ @submit="onSubmit"
+ />
+
+ <ApprovalTemplateBindDialog
+ v-model:visible="templateBindVisible"
+ :module-key="APPROVAL_MODULE_KEYS.REGULAR"
+ skip-form-confirm
+ @confirm="onTemplateBound"
+ @closed="onTemplateBindClosed"
+ />
+
+ <ApprovalInstanceDetailDialog
+ v-model="detailDialog.visible"
+ title="杞鐢宠璇︽儏"
+ :row="detailRow"
+ @edit="openEditFromDetail"
+ />
+ </div>
+</template>
+
+<script setup>
+import { Search } from "@element-plus/icons-vue";
+import { ElMessage } from "element-plus";
+import { onMounted, reactive } from "vue";
+import ApprovalInstanceDetailDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue";
+import ApprovalInstanceSubmitDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue";
+import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
+import { buildInstanceTableColumns } from "../../ApproveManage/approve-shared/approvalInstanceFormConfigTable.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { useApprovalInstanceModule } from "../../ApproveManage/approve-shared/useApprovalInstanceModule.js";
+import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
+
+const searchForm = reactive({
+ instanceNo: "",
+ applicantName: "",
+});
+
+const mod = useApprovalInstanceModule({
+ moduleKey: APPROVAL_MODULE_KEYS.REGULAR,
+ buildExtraListParams(sf) {
+ const extra = {};
+ const name = (sf?.applicantName || "").trim();
+ if (name) extra.applicantName = name;
+ return extra;
+ },
+});
+
+const {
+ tableData,
+ tableLoading,
+ page,
+ detailDialog,
+ detailRow,
+ submitDialog,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ isSubmitEdit,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitDialogTitle,
+ templateBindVisible,
+ handleQuery,
+ initModuleList,
+ pagination,
+ openAddWithTemplate,
+ onTemplateBound,
+ onTemplateBindClosed,
+ openEditFromDetail,
+ submitInstanceForm,
+ buildTableActions,
+} = mod;
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, {
+ moduleKey: APPROVAL_MODULE_KEYS.REGULAR,
+});
+
+function onSearch() {
+ handleQuery(searchForm);
+}
+
+function resetSearch() {
+ searchForm.instanceNo = "";
+ searchForm.applicantName = "";
+ onSearch();
+}
+
+function onPagination(obj) {
+ pagination(obj, searchForm);
+}
+
+async function onSubmit() {
+ const ok = await submitInstanceForm({ skipValidate: true });
+ if (ok) ElMessage.success(isSubmitEdit.value ? "淇敼鎴愬姛" : "鎻愪氦鎴愬姛");
+}
+
+onMounted(async () => {
+ loadFlowUsers();
+ await initModuleList(searchForm);
+});
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+</style>
diff --git a/src/views/officeProcessAutomation/HrManage/resign-apply/components/formDia.vue b/src/views/officeProcessAutomation/HrManage/resign-apply/components/formDia.vue
new file mode 100644
index 0000000..86c59ce
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/resign-apply/components/formDia.vue
@@ -0,0 +1,347 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板绂昏亴' : '缂栬緫绂昏亴'"
+ width="70%"
+ @close="closeDia"
+ >
+ <!-- 鍛樺伐淇℃伅灞曠ず鍖哄煙 -->
+ <div class="info-section">
+ <div class="info-title">鍛樺伐淇℃伅</div>
+ <el-form :model="form" label-width="200px" label-position="left" :rules="rules" ref="formRef" style="margin-top: 20px">
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="濮撳悕锛�" prop="staffOnJobId">
+ <el-select v-model="form.staffOnJobId"
+ placeholder="璇烽�夋嫨浜哄憳"
+ style="width: 100%"
+ :disabled="operationType === 'edit'"
+ @change="handleSelect">
+ <el-option
+ v-for="item in personList"
+ :key="item.id"
+ :label="item.staffName"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍛樺伐缂栧彿锛�">
+ {{ currentStaffRecord.staffNo || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎬у埆锛�">
+ {{ currentStaffRecord.sex || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎴风睄浣忓潃锛�">
+ {{ currentStaffRecord.nativePlace || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="宀椾綅锛�">
+ {{ currentStaffRecord.postName || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐜颁綇鍧�锛�">
+ {{ currentStaffRecord.adress || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绗竴瀛﹀巻锛�">
+ {{ currentStaffRecord.firstStudy || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓撲笟锛�">
+ {{ currentStaffRecord.profession || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="骞撮緞锛�">
+ {{ currentStaffRecord.age || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴鐢佃瘽锛�">
+ {{ currentStaffRecord.phone || '-' }}
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绱ф�ヨ仈绯讳汉锛�">
+ {{ currentStaffRecord.emergencyContact || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绱ф�ヨ仈绯讳汉鑱旂郴鐢佃瘽锛�">
+ {{ currentStaffRecord.emergencyContactPhone || '-' }}
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绂昏亴鏃ユ湡锛�" prop="leaveDate">
+ <el-date-picker
+ v-model="form.leaveDate"
+ type="date"
+ :disabled="operationType === 'edit'"
+ :disabled-date="disabledFutureDate"
+ placeholder="璇烽�夋嫨绂昏亴鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绂昏亴鍘熷洜锛�" prop="reason">
+ <el-select v-model="form.reason" placeholder="璇烽�夋嫨绂昏亴鍘熷洜" style="width: 100%" @change="handleSelectDimissionReason">
+ <el-option
+ v-for="(item, index) in dimissionReasonOptions"
+ :key="index"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="澶囨敞锛�" prop="remark" v-if="form.reason === 'other'">
+ <el-input
+ v-model="form.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="澶囨敞"
+ maxlength="500"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+
+<!-- <el-row :gutter="30">-->
+<!-- <el-col :span="12">-->
+<!-- <div class="info-item">-->
+<!-- <span class="info-label">绂昏亴鍘熷洜锛�</span>-->
+<!-- <el-select v-model="form.reason" placeholder="璇烽�夋嫨浜哄憳" style="width: 100%" @change="handleSelect">-->
+<!-- <el-option-->
+<!-- v-for="(item, index) in dimissionReasonOptions"-->
+<!-- :key="index"-->
+<!-- :label="item.label"-->
+<!-- :value="item.value"-->
+<!-- />-->
+<!-- </el-select>-->
+<!-- </div>-->
+<!-- </el-col>-->
+<!-- <el-col :span="12">-->
+<!-- <div class="info-item">-->
+<!-- <span class="info-label">鍛樺伐缂栧彿锛�</span>-->
+<!-- <span class="info-value">{{ form.staffNo || '-' }}</span>-->
+<!-- </div>-->
+<!-- </el-col>-->
+<!-- </el-row>-->
+ </div>
+
+ <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, toRefs, getCurrentInstance} from "vue";
+import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
+import {createStaffLeave, updateStaffLeave} from "@/api/personnelManagement/staffLeave.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const getTodayDate = () => {
+ const now = new Date();
+ const year = now.getFullYear();
+ const month = `${now.getMonth() + 1}`.padStart(2, '0');
+ const day = `${now.getDate()}`.padStart(2, '0');
+ return `${year}-${month}-${day}`;
+};
+
+const disabledFutureDate = (time) => {
+ const todayEnd = new Date();
+ todayEnd.setHours(23, 59, 59, 999);
+ return time.getTime() > todayEnd.getTime();
+};
+const data = reactive({
+ form: {
+ staffOnJobId: undefined,
+ leaveDate: "",
+ reason: "",
+ remark: "",
+ },
+ rules: {
+ staffName: [{ required: true, message: "璇烽�夋嫨浜哄憳" }],
+ leaveDate: [{ required: true, message: "璇烽�夋嫨绂昏亴鏃ユ湡", trigger: "change" }],
+ reason: [{ required: true, message: "璇烽�夋嫨绂昏亴鍘熷洜"}],
+ },
+ dimissionReasonOptions: [
+ {label: '钖祫寰呴亣', value: 'salary'},
+ {label: '鑱屼笟鍙戝睍', value: 'career_development'},
+ {label: '宸ヤ綔鐜', value: 'work_environment'},
+ {label: '涓汉鍘熷洜', value: 'personal_reason'},
+ {label: '鍏朵粬', value: 'other'},
+ ],
+ currentStaffRecord: {},
+});
+const { form, rules, dimissionReasonOptions, currentStaffRecord } = toRefs(data);
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === 'edit') {
+ currentStaffRecord.value = row
+ form.value.staffOnJobId = row.staffOnJobId
+ form.value.leaveDate = row.leaveDate
+ form.value.reason = row.reason
+ form.value.remark = row.remark
+ personList.value = [
+ {
+ staffName: row.staffName,
+ id: row.staffOnJobId,
+ }
+ ]
+ } else {
+ form.value.leaveDate = getTodayDate()
+ getList()
+ }
+}
+
+const handleSelectDimissionReason = (val) => {
+ if (val === 'other') {
+ form.value.remark = ''
+ }
+}
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitForm = () => {
+ form.value.staffState = 0
+ if (form.value.reason !== 'other') {
+ form.value.remark = ''
+ }
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ if (operationType.value === "add") {
+ createStaffLeave(form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ } else {
+ updateStaffLeave(currentStaffRecord.value.id, form.value).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ })
+ }
+ }
+ })
+
+}
+// 鍏抽棴寮规
+const closeDia = () => {
+ // 琛ㄥ崟宸叉敞閲婏紝鎵嬪姩閲嶇疆琛ㄥ崟鏁版嵁
+ form.value = {
+ staffOnJobId: undefined,
+ leaveDate: "",
+ reason: "",
+ remark: "",
+ };
+ dialogFormVisible.value = false;
+ emit('close')
+};
+
+const personList = ref([]);
+
+/**
+ * 鑾峰彇褰撳墠鍦ㄨ亴浜哄憳鍒楄〃
+ */
+const getList = () => {
+ staffOnJobListPage({
+ current: -1,
+ size: -1,
+ staffState: 1
+ }).then(res => {
+ personList.value = res.data.records || []
+ })
+};
+
+const handleSelect = (val) => {
+ let obj = personList.value.find(item => item.id === val)
+ currentStaffRecord.value = {}
+ if (obj) {
+ // 淇濈暀绂昏亴鏃ユ湡鍜岀鑱屽師鍥狅紝鍙洿鏂板憳宸ヤ俊鎭�
+ currentStaffRecord.value = obj
+ }
+}
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+.info-section {
+ background: #f5f7fa;
+ padding: 20px;
+ border-radius: 8px;
+ margin-bottom: 20px;
+}
+
+.info-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 20px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #e4e7ed;
+}
+
+.info-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 16px;
+ min-height: 32px;
+}
+
+.info-label {
+ min-width: 140px;
+ color: #606266;
+ font-size: 14px;
+ font-weight: 500;
+}
+
+.info-value {
+ flex: 1;
+ color: #303133;
+ font-size: 14px;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/HrManage/resign-apply/index.vue b/src/views/officeProcessAutomation/HrManage/resign-apply/index.vue
new file mode 100644
index 0000000..2b20970
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/resign-apply/index.vue
@@ -0,0 +1,220 @@
+<!--OA妯″潡锛氱鑱岀敵璇�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">濮撳悕锛�</span>
+ <el-input
+ v-model="searchForm.staffName"
+ 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 @click="handleOut">瀵煎嚭</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/dimission/components/formDia.vue";
+import { findStaffLeaveListPage } from "@/api/personnelManagement/staffLeave.js";
+import {ElMessageBox} from "element-plus";
+
+const data = reactive({
+ searchForm: {
+ staffName: "",
+ },
+});
+const { searchForm } = toRefs(data);
+const tableColumn = ref([
+ {
+ label: "鐘舵��",
+ prop: "staffState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == 0) {
+ return "绂昏亴";
+ } else if (params == 1) {
+ return "鍦ㄨ亴";
+ } else {
+ return null;
+ }
+ },
+ formatType: (params) => {
+ if (params == 0) {
+ return "danger";
+ } else if (params == 1) {
+ return "primary";
+ } else {
+ return null;
+ }
+ },
+ },
+ {
+ label: "绂昏亴鏃ユ湡",
+ prop: "leaveDate",
+ },
+ {
+ label: "鍛樺伐缂栧彿",
+ prop: "staffNo",
+ },
+ {
+ label: "濮撳悕",
+ prop: "staffName",
+ },
+ {
+ label: "鎬у埆",
+ prop: "sex",
+ },
+ {
+ label: "鎴风睄浣忓潃",
+ prop: "nativePlace",
+ },
+ {
+ label: "閮ㄩ棬",
+ prop: "deptName",
+ },
+ {
+ label: "宀椾綅",
+ prop: "postName",
+ },
+ {
+ label: "鐜颁綇鍧�",
+ prop: "adress",
+ width:200
+ },
+ {
+ label: "绗竴瀛﹀巻",
+ prop: "firstStudy",
+ },
+ {
+ label: "涓撲笟",
+ prop: "profession",
+ width:100
+ },
+ {
+ label: "骞撮緞",
+ prop: "age",
+ },
+ {
+ label: "鑱旂郴鐢佃瘽",
+ prop: "phone",
+ width:150
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉",
+ prop: "emergencyContact",
+ width: 120
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉鐢佃瘽",
+ prop: "emergencyContactPhone",
+ width:150
+ },
+ {
+ 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 handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ findStaffLeaveListPage({...page, ...searchForm.value}).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 handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/staff/staffLeave/export", {}, "浜哄憳绂昏亴.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped></style>
+
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/components/BasicInfoSection.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/components/BasicInfoSection.vue
new file mode 100644
index 0000000..0aa4f06
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/components/BasicInfoSection.vue
@@ -0,0 +1,181 @@
+<template>
+ <el-card class="form-card" shadow="never">
+ <template #header>
+ <span class="card-title">
+ <span class="card-title-line">|</span>
+ 鍩烘湰淇℃伅
+ </span>
+ </template>
+
+ <el-row :gutter="24">
+ <el-col :span="5">
+ <el-form-item label="鍛樺伐缂栧彿" prop="staffNo">
+ <el-input
+ v-model="form.staffNo"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ :disabled="operationType !== 'add'"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="濮撳悕" prop="staffName">
+ <el-input
+ v-model="form.staffName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="鍒悕" prop="alias">
+ <el-input
+ v-model="form.alias"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="鎵嬫満" prop="phone">
+ <el-input
+ v-model="form.phone"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="11"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="鎬у埆" prop="sex">
+ <el-select
+ v-model="form.sex"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鐢�" value="鐢�" />
+ <el-option label="濂�" value="濂�" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="24">
+ <el-col :span="5">
+ <el-form-item label="鍑虹敓鏃ユ湡" prop="birthDate">
+ <el-date-picker
+ v-model="form.birthDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="骞撮緞" prop="age">
+ <el-input-number
+ v-model="form.age"
+ :min="0"
+ :max="150"
+ :precision="0"
+ :step="1"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="绫嶈疮" prop="nativePlace">
+ <el-input
+ v-model="form.nativePlace"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="5">
+ <el-form-item label="姘戞棌" prop="nation">
+ <el-input
+ v-model="form.nation"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="濠氬Щ鐘跺喌" prop="maritalStatus">
+ <el-select
+ v-model="form.maritalStatus"
+ placeholder="璇烽�夋嫨"
+ clearable
+ 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-row>
+
+ <el-row :gutter="24">
+ <el-col :span="10">
+ <el-form-item label="瑙掕壊" prop="roleId">
+ <el-select
+ v-model="form.roleId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in roleOptions"
+ :key="item.roleId"
+ :label="item.roleName"
+ :value="item.roleId"
+ :disabled="item.status == 1"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-card>
+</template>
+
+<script setup>
+import { toRefs } from "vue";
+
+const props = defineProps({
+ form: { type: Object, required: true },
+ operationType: { type: String, default: "add" },
+ roleOptions: { type: Array, default: () => [] },
+});
+
+const { form, operationType, roleOptions } = toRefs(props);
+</script>
+
+<style scoped>
+.form-card {
+ margin-bottom: 16px;
+}
+
+.card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+}
+</style>
+
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/components/EducationWorkSection.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/components/EducationWorkSection.vue
new file mode 100644
index 0000000..c1470e7
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/components/EducationWorkSection.vue
@@ -0,0 +1,263 @@
+<template>
+ <div>
+ <!-- 鏁欒偛缁忓巻 -->
+ <el-card class="form-card" shadow="never">
+ <template #header>
+ <span class="card-title">
+ <span class="card-title-line">|</span>
+ 鏁欒偛缁忓巻
+ </span>
+ </template>
+ <el-table :data="form.staffEducationList" border>
+ <el-table-column label="瀛﹀巻" prop="education" width="120">
+ <template #default="{ row }">
+ <el-select
+ v-model="row.education"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="涓笓鍙婁互涓�" value="secondary" />
+ <el-option label="澶т笓" value="junior_college" />
+ <el-option label="鏈" value="bachelor" />
+ <el-option label="纭曞+" value="master" />
+ <el-option label="鍗氬+鍙婁互涓�" value="doctor" />
+ </el-select>
+ </template>
+ </el-table-column>
+ <el-table-column label="姣曚笟闄㈡牎" prop="schoolName" min-width="160">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.schoolName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="30"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍏ュ鏃堕棿" prop="enrollTime" width="150">
+ <template #default="{ row }">
+ <el-date-picker
+ v-model="row.enrollTime"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="姣曚笟鏃堕棿" prop="graduateTime" width="150">
+ <template #default="{ row }">
+ <el-date-picker
+ v-model="row.graduateTime"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="涓撲笟" prop="major" min-width="140">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.major"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="瀛︿綅" prop="degree" width="140">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.degree"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="80" align="center">
+ <template #default="scope">
+ <el-button
+ v-if="form.staffEducationList.length > 1"
+ type="primary"
+ link
+ @click="removeEducationRow(scope.$index)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <div class="table-add-row" @click="addEducationRow">鏂板缓涓�琛�</div>
+ </el-card>
+
+ <!-- 宸ヤ綔缁忓巻 -->
+ <el-card class="form-card" shadow="never">
+ <template #header>
+ <span class="card-title">
+ <span class="card-title-line">|</span>
+ 宸ヤ綔缁忓巻
+ </span>
+ </template>
+ <el-table :data="form.staffWorkExperienceList" border>
+ <el-table-column label="鍓嶅叕鍙�" prop="formerCompany" min-width="180">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.formerCompany"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="30"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍓嶅叕鍙搁儴闂�" prop="formerDept" min-width="140">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.formerDept"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍓嶅叕鍙歌亴浣�" prop="formerPosition" min-width="140">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.formerPosition"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="寮�濮嬫棩鏈�" prop="startDate" width="150">
+ <template #default="{ row }">
+ <el-date-picker
+ v-model="row.startDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="缁撴潫鏃ユ湡" prop="endDate" width="150">
+ <template #default="{ row }">
+ <el-date-picker
+ v-model="row.endDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="宸ヤ綔鎻忚堪" prop="workDesc" min-width="220">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.workDesc"
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="500"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="80" align="center">
+ <template #default="scope">
+ <el-button
+ v-if="form.staffWorkExperienceList.length > 1"
+ type="primary"
+ link
+ @click="removeWorkRow(scope.$index)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <div class="table-add-row" @click="addWorkRow">鏂板缓涓�琛�</div>
+ </el-card>
+ </div>
+</template>
+
+<script setup>
+import { toRefs } from "vue";
+
+const props = defineProps({
+ form: { type: Object, required: true },
+});
+
+const emit = defineEmits(["update:form"]);
+
+const { form } = toRefs(props);
+
+const addEducationRow = () => {
+ form.value.staffEducationList.push({
+ education: "",
+ schoolName: "",
+ enrollTime: "",
+ graduateTime: "",
+ major: "",
+ degree: "",
+ });
+};
+
+const removeEducationRow = (index) => {
+ if (form.value.staffEducationList.length <= 1) return;
+ form.value.staffEducationList.splice(index, 1);
+};
+
+const addWorkRow = () => {
+ form.value.staffWorkExperienceList.push({
+ formerCompany: "",
+ formerDept: "",
+ formerPosition: "",
+ startDate: "",
+ endDate: "",
+ workDesc: "",
+ });
+};
+
+const removeWorkRow = (index) => {
+ if (form.value.staffWorkExperienceList.length <= 1) return;
+ form.value.staffWorkExperienceList.splice(index, 1);
+};
+</script>
+
+<style scoped>
+.form-card {
+ margin-bottom: 16px;
+}
+
+.card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+}
+
+.table-add-row {
+ margin-top: 8px;
+ color: #409eff;
+ cursor: pointer;
+ font-size: 14px;
+}
+</style>
+
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/components/EmergencyAndAttachmentSection.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/components/EmergencyAndAttachmentSection.vue
new file mode 100644
index 0000000..bd63608
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/components/EmergencyAndAttachmentSection.vue
@@ -0,0 +1,115 @@
+<template>
+ <div>
+ <!-- 绱ф�ヨ仈绯讳汉 -->
+ <el-card class="form-card" shadow="never">
+ <template #header>
+ <span class="card-title">
+ <span class="card-title-line">|</span>
+ 绱ф�ヨ仈绯讳汉
+ </span>
+ </template>
+ <el-table :data="form.staffEmergencyContactList" border>
+ <el-table-column label="绱ф�ヨ仈绯讳汉濮撳悕" prop="contactName" min-width="160">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.contactName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="绱ф�ヨ仈绯讳汉鍏崇郴" prop="contactRelation" min-width="140">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.contactRelation"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="20"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="绱ф�ヨ仈绯讳汉鎵嬫満" prop="contactPhone" width="160">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.contactPhone"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="11"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="绱ф�ヨ仈绯讳汉浣忓潃" prop="contactAddress" min-width="220">
+ <template #default="{ row }">
+ <el-input
+ v-model="row.contactAddress"
+ placeholder="璇疯緭鍏�"
+ clearable
+ maxlength="50"
+ show-word-limit
+ />
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="80" align="center">
+ <template #default="scope">
+ <el-button
+ v-if="form.staffEmergencyContactList.length > 1"
+ type="primary"
+ link
+ @click="removeEmergencyRow(scope.$index)"
+ >
+ 鍒犻櫎
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <div class="table-add-row" @click="addEmergencyRow">鏂板缓涓�琛�</div>
+ </el-card>
+ </div>
+</template>
+
+<script setup>
+import { toRefs } from "vue";
+
+const props = defineProps({
+ form: { type: Object, required: true }
+});
+
+const { form } = toRefs(props);
+
+const addEmergencyRow = () => {
+ form.value.staffEmergencyContactList.push({
+ contactName: "",
+ contactRelation: "",
+ contactPhone: "",
+ contactAddress: "",
+ });
+};
+
+const removeEmergencyRow = (index) => {
+ if (form.value.staffEmergencyContactList.length <= 1) return;
+ form.value.staffEmergencyContactList.splice(index, 1);
+};
+</script>
+
+<style scoped>
+.form-card {
+ margin-bottom: 16px;
+}
+
+.card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+}
+
+.table-add-row {
+ margin-top: 8px;
+ color: #409eff;
+ cursor: pointer;
+ font-size: 14px;
+}
+</style>
+
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/components/JobInfoSection.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/components/JobInfoSection.vue
new file mode 100644
index 0000000..be33436
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/components/JobInfoSection.vue
@@ -0,0 +1,176 @@
+<template>
+ <el-card class="form-card" shadow="never">
+ <template #header>
+ <span class="card-title">
+ <span class="card-title-line">|</span>
+ 鍦ㄨ亴淇℃伅
+ </span>
+ </template>
+
+ <!-- 绗竴琛岋細鍚堝悓寮�濮� / 鍚堝悓缁撴潫 / 璇曠敤鏈� / 杞 -->
+ <el-row :gutter="24">
+ <el-col :span="6">
+ <el-form-item label="鍏ヨ亴鏃ユ湡" prop="contractStartTime">
+ <el-date-picker
+ v-model="form.contractStartTime"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ @change="calculateContractTerm"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item
+ label="鍚堝悓缁撴潫鏃ユ湡"
+ prop="contractEndTime"
+ required
+ :rules="[
+ {
+ required: true,
+ message: '璇烽�夋嫨鍚堝悓缁撴潫鏃ユ湡',
+ trigger: 'change',
+ },
+ ]"
+ >
+ <el-date-picker
+ v-model="form.contractEndTime"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ @change="calculateContractTerm"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="璇曠敤鏈燂紙鏈堬級" prop="probationPeriod">
+ <el-input-number
+ v-model="form.proTerm"
+ :min="0"
+ :max="24"
+ :precision="0"
+ :step="1"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="杞鏃ユ湡" prop="positiveDate">
+ <el-date-picker
+ v-model="form.positiveDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <!-- 绗簩琛岋細閮ㄩ棬 / 宀椾綅 / 鍩烘湰宸ヨ祫 -->
+ <el-row :gutter="24">
+ <el-col :span="8">
+ <el-form-item label="閮ㄩ棬" prop="sysDeptId">
+ <el-tree-select
+ v-model="form.sysDeptId"
+ :data="deptOptions"
+ check-strictly
+ :render-after-expand="false"
+ placeholder="璇烽�夋嫨"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="宀椾綅" prop="sysPostId">
+ <el-select
+ v-model="form.sysPostId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option
+ v-for="item in postOptions"
+ :key="item.postId"
+ :label="item.postName"
+ :value="item.postId"
+ :disabled="item.status === '1'"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鍩烘湰宸ヨ祫" prop="basicSalary">
+ <el-input-number
+ v-model="form.basicSalary"
+ :min="0"
+ :max="999999"
+ :precision="2"
+ :step="100"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-card>
+</template>
+
+<script setup>
+import { toRefs } from "vue";
+
+const props = defineProps({
+ form: { type: Object, required: true },
+ postOptions: { type: Array, default: () => [] },
+ deptOptions: { type: Array, default: () => [] },
+});
+
+const { form, postOptions, deptOptions } = toRefs(props);
+
+// 璁$畻鍚堝悓骞撮檺
+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;
+ }
+};
+</script>
+
+<style scoped>
+.form-card {
+ margin-bottom: 16px;
+}
+
+.card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+}
+</style>
+
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/components/NewOrEditFormDia.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/components/NewOrEditFormDia.vue
new file mode 100644
index 0000000..2ad06fb
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/components/NewOrEditFormDia.vue
@@ -0,0 +1,304 @@
+<template>
+ <FormDialog
+ v-model="dialogFormVisible"
+ :operation-type="operationType"
+ :title="dialogTitle"
+ width="90%"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia"
+ >
+ <div class="form-dia-body">
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-position="top"
+ >
+ <BasicInfoSection
+ :form="form"
+ :operation-type="operationType"
+ :role-options="roleOptions"
+ />
+ <JobInfoSection
+ :form="form"
+ :post-options="postOptions"
+ :dept-options="deptOptions"
+ />
+ <EducationWorkSection :form="form" />
+ <EmergencyAndAttachmentSection :form="form" />
+ </el-form>
+ </div>
+ </FormDialog>
+</template>
+
+<script setup>
+import {
+ ref,
+ reactive,
+ toRefs,
+ onMounted,
+ getCurrentInstance,
+ nextTick,
+} from "vue";
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { findPostOptions } from "@/api/system/post.js";
+import { deptTreeSelect, getUser } from "@/api/system/user.js";
+import {
+ staffOnJobInfo,
+ createStaffOnJob,
+ updateStaffOnJob,
+} from "@/api/personnelManagement/staffOnJob.js";
+
+import BasicInfoSection from "./BasicInfoSection.vue";
+import JobInfoSection from "./JobInfoSection.vue";
+import EducationWorkSection from "./EducationWorkSection.vue";
+import EmergencyAndAttachmentSection from "./EmergencyAndAttachmentSection.vue";
+
+const { proxy } = getCurrentInstance();
+const emit = defineEmits(["close"]);
+
+const dialogFormVisible = ref(false);
+const operationType = ref("add");
+const id = ref(0);
+const formRef = ref(null);
+
+const dialogTitle = () =>
+ operationType.value === "add" ? "鏂板鍏ヨ亴" : "缂栬緫浜哄憳";
+
+const createEmptyEducation = () => ({
+ education: "",
+ schoolName: "",
+ enrollTime: "",
+ graduateTime: "",
+ major: "",
+ degree: "",
+});
+
+const createEmptyWork = () => ({
+ formerCompany: "",
+ formerDept: "",
+ formerPosition: "",
+ startDate: "",
+ endDate: "",
+ workDesc: "",
+});
+
+const createEmptyEmergency = () => ({
+ contactName: "",
+ contactRelation: "",
+ contactPhone: "",
+ contactAddress: "",
+});
+
+const createDefaultForm = () => ({
+ id: undefined,
+ // 鍩烘湰淇℃伅
+ staffNo: "",
+ staffName: "",
+ alias: "",
+ phone: "",
+ sex: "",
+ birthDate: "",
+ age: undefined,
+ nativePlace: "",
+ nation: "",
+ maritalStatus: "",
+ politicalStatus: "",
+ firstWorkDate: "",
+ workingYears: undefined,
+ idCardNo: "",
+ hukouType: "",
+ email: "",
+ currentAddress: "",
+ // 鍦ㄨ亴淇℃伅
+ contractStartTime: "",
+ contractEndTime: "",
+ proTerm: undefined,
+ positiveDate: "",
+ sysDeptId: undefined,
+ sysPostId: undefined,
+ basicSalary: undefined,
+ // 閾惰鍗′俊鎭�
+ bankName: "",
+ bankCardNo: "",
+ // 鏁欒偛缁忓巻
+ staffEducationList: [createEmptyEducation()],
+ // 宸ヤ綔缁忓巻
+ staffWorkExperienceList: [createEmptyWork()],
+ // 绱ф�ヨ仈绯讳汉
+ staffEmergencyContactList: [createEmptyEmergency()],
+ // 瑙掕壊锛堝崟閫夛級
+ roleId: undefined,
+});
+
+const state = reactive({
+ form: createDefaultForm(),
+ rules: {
+ staffNo: [{ required: true, message: "璇疯緭鍏ュ憳宸ョ紪鍙�", trigger: "blur" }],
+ staffName: [{ required: true, message: "璇疯緭鍏ュ鍚�", trigger: "blur" }],
+ phone: [{ required: true, message: "璇疯緭鍏ユ墜鏈�", trigger: "blur" }],
+ sex: [{ required: true, message: "璇烽�夋嫨鎬у埆", trigger: "change" }],
+ birthDate: [
+ { required: true, message: "璇烽�夋嫨鍑虹敓鏃ユ湡", trigger: "change" },
+ ],
+ contractStartTime: [
+ { required: true, message: "璇烽�夋嫨鍏ヨ亴鏃ユ湡", trigger: "change" },
+ ],
+ contractEndTime: [
+ { required: true, message: "璇烽�夋嫨鍚堝悓缁撴潫鏃ユ湡", trigger: "change" },
+ ],
+ sysDeptId: [
+ { required: true, message: "璇烽�夋嫨閮ㄩ棬", trigger: "change" },
+ ],
+ roleId: [{ required: true, message: "璇烽�夋嫨瑙掕壊", trigger: "change" }],
+ },
+ postOptions: [],
+ deptOptions: [],
+});
+
+const { form, rules, postOptions, deptOptions } = toRefs(state);
+const roleOptions = ref([]);
+
+const resetForm = () => {
+ Object.assign(form.value, createDefaultForm());
+ nextTick(() => {
+ formRef.value?.clearValidate();
+ });
+};
+
+const fetchPostOptions = () => {
+ findPostOptions().then((res) => {
+ postOptions.value = res.data || [];
+ });
+};
+
+const fetchDeptOptions = () => {
+ deptTreeSelect().then((response) => {
+ deptOptions.value = filterDisabledDept(
+ JSON.parse(JSON.stringify(response.data || []))
+ );
+ });
+};
+
+const fetchRoleOptions = () => {
+ getUser().then((res) => {
+ roleOptions.value = res.roles || [];
+ });
+};
+
+function filterDisabledDept(deptList) {
+ return deptList.filter((dept) => {
+ if (dept.disabled) {
+ return false;
+ }
+ if (dept.children && dept.children.length) {
+ dept.children = filterDisabledDept(dept.children);
+ }
+ return true;
+ });
+}
+
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ fetchPostOptions();
+ fetchDeptOptions();
+ fetchRoleOptions();
+ resetForm();
+ if (type === "edit" && row?.id) {
+ id.value = row.id;
+ staffOnJobInfo(id.value, {}).then((res) => {
+ const d = res.data || {};
+ Object.assign(form.value, {
+ ...form.value,
+ ...d,
+ });
+ if (
+ !Array.isArray(form.value.staffEducationList) ||
+ !form.value.staffEducationList.length
+ ) {
+ form.value.staffEducationList = [createEmptyEducation()];
+ }
+ if (
+ !Array.isArray(form.value.staffWorkExperienceList) ||
+ !form.value.staffWorkExperienceList.length
+ ) {
+ form.value.staffWorkExperienceList = [createEmptyWork()];
+ }
+ if (
+ !Array.isArray(form.value.staffEmergencyContactList) ||
+ !form.value.staffEmergencyContactList.length
+ ) {
+ form.value.staffEmergencyContactList = [createEmptyEmergency()];
+ }
+ if (form.value.sysPostId === 0) {
+ form.value.sysPostId = undefined;
+ }
+ if (form.value.sysDeptId === 0) {
+ form.value.sysDeptId = undefined;
+ }
+ });
+ }
+};
+
+onMounted(() => {
+ fetchPostOptions();
+ fetchDeptOptions();
+});
+
+const submitForm = () => {
+ if (!form.value.sysPostId) {
+ form.value.sysPostId = undefined;
+ }
+ if (!form.value.sysDeptId) {
+ form.value.sysDeptId = undefined;
+ }
+ // 鍏煎鍚庣鍙兘浠嶄娇鐢� roleIds 鏁扮粍
+ form.value.roleIds = form.value.roleId ? [form.value.roleId] : [];
+ formRef.value?.validate((valid) => {
+ if (valid) {
+ if (operationType.value === "add") {
+ createStaffOnJob(form.value).then(() => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ });
+ } else {
+ updateStaffOnJob(id.value, form.value).then(() => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ });
+ }
+ }
+ });
+};
+
+const closeDia = () => {
+ formRef.value?.resetFields();
+ dialogFormVisible.value = false;
+ emit("close");
+};
+
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+.form-dia-body {
+ padding: 0;
+}
+
+.card-title-line {
+ color: #f56c6c;
+ margin-right: 4px;
+}
+
+.form-card {
+ margin-bottom: 16px;
+}
+
+.dialog-footer {
+ text-align: right;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/components/RenewContract.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/components/RenewContract.vue
new file mode 100644
index 0000000..9c2acfc
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/components/RenewContract.vue
@@ -0,0 +1,141 @@
+<template>
+ <el-dialog
+ v-model="isShow"
+ title="缁鍚堝悓"
+ width="800px"
+ @close="closeModal"
+ >
+ <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+ <el-form-item label="鍚堝悓寮�濮嬫棩鏈燂細" prop="contractStartTime">
+ <el-date-picker
+ v-model="form.contractStartTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ @change="calculateContractTerm"
+ />
+ </el-form-item>
+ <el-form-item label="鍚堝悓缁撴潫鏃ユ湡锛�" prop="contractEndTime">
+ <el-date-picker
+ v-model="form.contractEndTime"
+ type="date"
+ placeholder="璇烽�夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ clearable
+ style="width: 100%"
+ @change="calculateContractTerm"
+ />
+ </el-form-item>
+ <el-form-item label="鍚堝悓骞撮檺锛�" prop="contractTerm">
+ <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeModal">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+// 缁鍚堝悓
+import { renewContract } from "@/api/personnelManagement/staffOnJob.js";
+import {computed, getCurrentInstance,} from "vue";
+
+const emit = defineEmits(['update:visible', 'completed']);
+
+const data = reactive({
+ form: {
+ contractTerm: 0,
+ contractStartTime: "",
+ contractEndTime: "",
+ },
+ rules: {
+ contractTerm: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contractStartTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ contractEndTime: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ }
+});
+const { form, rules } = toRefs(data);
+let { proxy } = getCurrentInstance()
+
+const props = defineProps({
+ id: {
+ type: Number,
+ default: 0,
+ },
+
+ visible: {
+ type: Boolean,
+ required: true,
+ },
+})
+
+const isShow = computed({
+ get() {
+ return props.visible;
+ },
+ set(val) {
+ emit('update:visible', val);
+ },
+});
+
+// 璁$畻鍚堝悓骞撮檺
+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 submitForm = () => {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ renewContract(props.id, form.value).then(res => {
+ if (res.code === 200) {
+ proxy.$modal.msgSuccess("缁鍚堝悓鎴愬姛");
+ emit('completed');
+ closeModal();
+ }
+ })
+ }
+ })
+}
+
+// 鍏抽棴寮规
+const closeModal = () => {
+ // 閲嶇疆琛ㄥ崟鏁版嵁
+ form.value = {
+ contractTerm: 0,
+ contractStartTime: "",
+ contractEndTime: "",
+ };
+ isShow.value = false;
+};
+</script>
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/components/Show.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/components/Show.vue
new file mode 100644
index 0000000..5d0b261
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/components/Show.vue
@@ -0,0 +1,69 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ title="璇︽儏"
+ width="70%"
+ @close="closeDia"
+ >
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ height="600"
+ ></PIMTable>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import {staffOnJobInfo} from "@/api/personnelManagement/staffOnJob.js";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+
+const dialogFormVisible = ref(false);
+const operationType = ref('')
+const tableColumn = ref([
+ {
+ label: "鍚堝悓寮�濮嬫棩鏈�",
+ prop: "contractStartTime",
+ },
+ {
+ label: "鍚堝悓缁撴潫鏃ユ湡",
+ prop: "contractEndTime",
+ },
+]);
+const tableData = ref([]);
+const tableLoading = ref(false);
+
+// 鎵撳紑寮规
+const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === 'edit') {
+ staffOnJobInfo({staffNo: row.staffNo}).then(res => {
+ tableData.value = res.data
+ })
+ }
+}
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit('close')
+};
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/officeProcessAutomation/HrManage/staff-archive/index.vue b/src/views/officeProcessAutomation/HrManage/staff-archive/index.vue
new file mode 100644
index 0000000..66cec7a
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-archive/index.vue
@@ -0,0 +1,360 @@
+<!--OA妯″潡锛氬憳宸ユ。妗�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">濮撳悕锛�</span>
+ <el-input
+ v-model="searchForm.staffName"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ュ鍚嶆悳绱�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span class="search_title search_title2">閮ㄩ棬锛�</span>
+ <el-tree-select
+ v-model="searchForm.sysDeptId"
+ :data="deptOptions"
+ check-strictly
+ :render-after-expand="false"
+ style="width: 240px"
+ placeholder="璇烽�夋嫨"
+ />
+ <span class="search_title search_title2">鍏ヨ亴鏃ユ湡锛�</span>
+ <el-date-picker
+ v-model="searchForm.contractStartTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨"
+ />
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openFormNewOrEditFormDia('add')">鏂板鍏ヨ亴</el-button>
+ <el-button type="info" @click="handleImport">瀵煎叆</el-button>
+ <el-button @click="handleOut">瀵煎嚭</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>
+ <show-form-dia ref="formDia" @close="handleQuery"></show-form-dia>
+ <new-or-edit-form-dia ref="formDiaNewOrEditFormDia" @close="handleQuery"></new-or-edit-form-dia>
+ <renew-contract
+ v-if="isShowRenewContractModal"
+ v-model:visible="isShowRenewContractModal"
+ :id="id"
+ @completed="handleQuery"
+ />
+
+ <!-- 瀵煎叆瀵硅瘽妗� -->
+ <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
+ <el-upload
+ ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :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; margin-left: 5px;" @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, UploadFilled } from "@element-plus/icons-vue";
+import {onMounted, ref} from "vue";
+import {ElMessageBox} from "element-plus";
+import { deptTreeSelect } from "@/api/system/user.js";
+import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
+import { getToken } from "@/utils/auth";
+import dayjs from "dayjs";
+
+const NewOrEditFormDia = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue"));
+const ShowFormDia = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/Show.vue"));
+const RenewContract = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/RenewContract.vue"));
+
+const data = reactive({
+ searchForm: {
+ staffName: "",
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ deptOptions: [],
+});
+const { searchForm, deptOptions } = toRefs(data);
+const isShowRenewContractModal = ref(false);
+const id = ref(0);
+const tableColumn = ref([
+ {
+ label: "鐘舵��",
+ prop: "staffState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == 0) {
+ return "绂昏亴";
+ } else if (params == 1) {
+ return "鍦ㄨ亴";
+ } else {
+ return null;
+ }
+ },
+ formatType: (params) => {
+ if (params == 0) {
+ return "danger";
+ } else if (params == 1) {
+ return "primary";
+ } else {
+ return null;
+ }
+ },
+ },
+ {
+ label: "鍛樺伐缂栧彿",
+ prop: "staffNo",
+ },
+ {
+ label: "濮撳悕",
+ prop: "staffName",
+ },
+ {
+ label: "鍒悕",
+ prop: "alias",
+ },
+ {
+ label: "鎵嬫満",
+ prop: "phone",
+ width: 150,
+ },
+ {
+ label: "鎬у埆",
+ prop: "sex",
+ },
+ {
+ label: "鍑虹敓鏃ユ湡",
+ prop: "birthDate",
+ width: 120,
+ },
+ {
+ label: "鍏ヨ亴鏃ユ湡",
+ prop: "contractStartTime",
+ width: 120,
+ },
+ {
+ label: "骞撮緞",
+ prop: "age",
+ },
+ {
+ label: "绫嶈疮",
+ prop: "nativePlace",
+ },
+ {
+ label: "姘戞棌",
+ prop: "nation",
+ width: 100,
+ },
+ {
+ label: "濠氬Щ鐘跺喌",
+ prop: "maritalStatus",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ width: 180,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openFormNewOrEditFormDia("edit", row);
+ },
+ },
+ {
+ name: "缁鍚堝悓",
+ type: "text",
+ showHide: row => row.staffState === 1,
+ clickFun: (row) => {
+ isShowRenewContractModal.value = true;
+ id.value = row.id;
+ },
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0
+});
+const formDia = ref()
+const formDiaNewOrEditFormDia = ref()
+const { proxy } = getCurrentInstance()
+
+// 瀵煎叆鐩稿叧
+const uploadRef = ref(null)
+const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import"
+})
+
+const fetchDeptOptions = () => {
+ deptTreeSelect().then(response => {
+ deptOptions.value = filterDisabledDept(
+ JSON.parse(JSON.stringify(response.data))
+ );
+ });
+ };
+const filterDisabledDept = deptList => {
+ return deptList.filter(dept => {
+ if (dept.disabled) {
+ return false;
+ }
+ if (dept.children && dept.children.length) {
+ dept.children = filterDisabledDept(dept.children);
+ }
+ return true;
+ });
+ };
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ fetchDeptOptions();
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined
+ staffOnJobListPage({...params}).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 openFormNewOrEditFormDia = (type, row) => {
+ nextTick(() => {
+ formDiaNewOrEditFormDia.value?.openDialog(type, row)
+ })
+};
+
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/staff/staffOnJob/export", {staffState: 1}, "鍛樺伐鍙拌处.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 瀵煎叆鎸夐挳鎿嶄綔
+const handleImport = () => {
+ upload.title = "鍛樺伐瀵煎叆"
+ upload.open = true
+}
+
+// 涓嬭浇妯℃澘鎿嶄綔
+const importTemplate = () => {
+ proxy.download("/staff/staffOnJob/downloadTemplate", {}, `鍛樺伐瀵煎叆妯℃澘_${new Date().getTime()}.xlsx`)
+}
+
+// 鏂囦欢涓婁紶涓鐞�
+const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true
+}
+
+// 鏂囦欢涓婁紶鎴愬姛澶勭悊
+const handleFileSuccess = (response, file, fileList) => {
+ upload.open = false
+ upload.isUploading = false
+ proxy.$refs["uploadRef"].handleRemove(file)
+ proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "瀵煎叆缁撴灉", { dangerouslyUseHTMLString: true })
+ getList()
+}
+
+// 鎻愪氦涓婁紶鏂囦欢
+const submitFileForm = () => {
+ proxy.$refs["uploadRef"].submit()
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped>
+.search_title2 {
+ margin-left: 10px;
+}
+</style>
+
diff --git a/src/views/officeProcessAutomation/HrManage/staff-contract/components/formDia.vue b/src/views/officeProcessAutomation/HrManage/staff-contract/components/formDia.vue
new file mode 100644
index 0000000..3db1bee
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-contract/components/formDia.vue
@@ -0,0 +1,93 @@
+<template>
+ <div>
+ <el-dialog v-model="dialogFormVisible"
+ title="璇︽儏"
+ width="70%"
+ @close="closeDia">
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ height="600"></PIMTable>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <FileList v-if="fileDialogVisible"
+ v-model:visible="fileDialogVisible"
+ :record-type="'staff_contract'"
+ :record-id="recordId" />
+ </div>
+</template>
+
+<script setup>
+ import { ref, defineAsyncComponent, getCurrentInstance } from "vue";
+ import { findStaffContractListPage } from "@/api/personnelManagement/staffContract.js";
+ const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
+ );
+ const { proxy } = getCurrentInstance();
+ const emit = defineEmits(["close"]);
+ const fileDialogVisible = ref(false);
+ const recordId = ref(0);
+ const dialogFormVisible = ref(false);
+ const operationType = ref("");
+ const tableColumn = ref([
+ {
+ label: "鍚堝悓骞撮檺",
+ prop: "contractTerm",
+ },
+ {
+ label: "鍚堝悓寮�濮嬫棩鏈�",
+ prop: "contractStartTime",
+ },
+ {
+ label: "鍚堝悓缁撴潫鏃ユ湡",
+ prop: "contractEndTime",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 120,
+ operation: [
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: row => {
+ recordId.value = row.id;
+ fileDialogVisible.value = true;
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const tableLoading = ref(false);
+
+ // 鎵撳紑寮规
+ const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === "edit") {
+ findStaffContractListPage({ staffOnJobId: row.id }).then(res => {
+ tableData.value = res.data.records;
+ });
+ }
+ };
+
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit("close");
+ };
+ defineExpose({
+ openDialog,
+ });
+</script>
+
+<style scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/officeProcessAutomation/HrManage/staff-contract/filesDia.vue b/src/views/officeProcessAutomation/HrManage/staff-contract/filesDia.vue
new file mode 100644
index 0000000..02f9cef
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-contract/filesDia.vue
@@ -0,0 +1,197 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ title="涓婁紶闄勪欢"
+ width="50%"
+ @close="closeDia"
+ >
+ <div style="margin-bottom: 10px;text-align: right">
+ <el-upload
+ v-model:file-list="fileList"
+ class="upload-demo"
+ :action="uploadUrl"
+ :on-success="handleUploadSuccess"
+ :on-error="handleUploadError"
+ name="file"
+ :show-file-list="false"
+ :headers="headers"
+ style="display: inline;margin-right: 10px"
+ >
+ <el-button type="primary">涓婁紶闄勪欢</el-button>
+ </el-upload>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ :isSelection="true"
+ :page="page"
+ @selection-change="handleSelectionChange"
+ height="500"
+ @pagination="paginationSearch"
+ :total="page.total"
+ >
+ </PIMTable>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ <filePreview ref="filePreviewRef" />
+ </div>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import {ElMessageBox} from "element-plus";
+import {getToken} from "@/utils/auth.js";
+import filePreview from '@/components/filePreview/index.vue'
+import {
+ fileAdd,
+ fileDel,
+ fileListPage
+} from "@/api/financialManagement/revenueManagement.js";
+import Pagination from "@/components/PIMTable/Pagination.vue";
+const { proxy } = getCurrentInstance()
+const emit = defineEmits(['close'])
+
+const dialogFormVisible = ref(false);
+const currentId = ref('')
+const selectedRows = ref([]);
+const filePreviewRef = ref()
+const tableColumn = ref([
+ {
+ label: "鏂囦欢鍚嶇О",
+ prop: "name",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ operation: [
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: (row) => {
+ downLoadFile(row);
+ },
+ },
+ {
+ name: "棰勮",
+ type: "text",
+ clickFun: (row) => {
+ lookFile(row);
+ },
+ }
+ ],
+ },
+]);
+const page = reactive({
+ current: 1,
+ size: 100,
+});
+const total = ref(0);
+const tableData = ref([]);
+const fileList = ref([]);
+const tableLoading = ref(false);
+const accountType = ref('')
+const headers = ref({
+ Authorization: "Bearer " + getToken(),
+});
+const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃
+
+// 鎵撳紑寮规
+const openDialog = (row,type) => {
+ accountType.value = type;
+ dialogFormVisible.value = true;
+ currentId.value = row.id;
+ getList()
+}
+const paginationSearch = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ fileListPage({accountId: currentId.value,accountType:accountType.value, ...page}).then(res => {
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ })
+}
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+
+// 鍏抽棴寮规
+const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit('close')
+};
+// 涓婁紶鎴愬姛澶勭悊
+function handleUploadSuccess(res, file) {
+ // 濡傛灉涓婁紶鎴愬姛
+ if (res.code == 200) {
+ const fileRow = {}
+ fileRow.name = res.data.originalName
+ fileRow.url = res.data.tempPath
+ uploadFile(fileRow)
+ } else {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+ }
+}
+function uploadFile(file) {
+ file.accountId = currentId.value;
+ file.accountType = accountType.value;
+ fileAdd(file).then(res => {
+ proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
+ getList()
+ })
+}
+// 涓婁紶澶辫触澶勭悊
+function handleUploadError() {
+ proxy.$modal.msgError("鏂囦欢涓婁紶澶辫触");
+}
+// 涓嬭浇闄勪欢
+const downLoadFile = (row) => {
+ proxy.$download.byUrl(row.url, row.originalFilename);
+}
+// 鍒犻櫎
+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(() => {
+ fileDel(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ }).catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 棰勮闄勪欢
+const lookFile = (row) => {
+ filePreviewRef.value.open(row.url)
+}
+
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/officeProcessAutomation/HrManage/staff-contract/index.vue b/src/views/officeProcessAutomation/HrManage/staff-contract/index.vue
new file mode 100644
index 0000000..8186bdd
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/staff-contract/index.vue
@@ -0,0 +1,296 @@
+<!--OA妯″潡锛氬憳宸ュ悎鍚�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">濮撳悕锛�</span>
+ <el-input v-model="searchForm.staffName" style="width: 240px" placeholder="璇疯緭鍏ュ鍚嶆悳绱�" @change="handleQuery"
+ 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" />
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px">鎼滅储</el-button>
+ </div>
+ <div>
+ <el-button @click="handleOut">瀵煎嚭</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>
+
+ <!-- 鍚堝悓瀵煎叆瀵硅瘽妗� -->
+ <el-dialog
+ :title="upload.title"
+ v-model="upload.open"
+ width="400px"
+ append-to-body
+ >
+ <el-upload
+ ref="uploadRef"
+ :limit="1"
+ accept=".xlsx, .xls"
+ :headers="upload.headers"
+ :action="upload.url + '?updateSupport=' + upload.updateSupport"
+ :disabled="upload.isUploading"
+ :on-progress="handleFileUploadProgress"
+ :on-success="handleFileSuccess"
+ :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>
+ </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>
+ <files-dia ref="filesDia"></files-dia>
+ </div>
+</template>
+
+<script setup>
+import { Search } from "@element-plus/icons-vue";
+import { onMounted, ref } from "vue";
+import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue";
+import { ElMessageBox } from "element-plus";
+import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
+import dayjs from "dayjs";
+import { getToken } from "@/utils/auth.js";
+import FilesDia from "./filesDia.vue";
+const data = reactive({
+ searchForm: {
+ staffName: "",
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+});
+const { searchForm } = toRefs(data);
+const tableColumn = ref([
+ {
+ label: "鐘舵��",
+ prop: "staffState",
+ dataType: "tag",
+ formatData: (params) => {
+ if (params == 0) {
+ return "绂昏亴";
+ } else if (params == 1) {
+ return "鍦ㄨ亴";
+ } else {
+ return null;
+ }
+ },
+ formatType: (params) => {
+ if (params == 0) {
+ return "danger";
+ } else if (params == 1) {
+ return "primary";
+ } else {
+ return null;
+ }
+ },
+ },
+ {
+ label: "鍛樺伐缂栧彿",
+ prop: "staffNo",
+ },
+ {
+ label: "濮撳悕",
+ prop: "staffName",
+ },
+ {
+ label: "鎬у埆",
+ prop: "sex",
+ },
+ {
+ label: "鎴风睄浣忓潃",
+ prop: "nativePlace",
+ },
+ {
+ label: "宀椾綅",
+ prop: "postName",
+ },
+ {
+ label: "鐜颁綇鍧�",
+ prop: "adress",
+ width: 200
+ },
+ {
+ label: "绗竴瀛﹀巻",
+ prop: "firstStudy",
+ },
+ {
+ label: "涓撲笟",
+ prop: "profession",
+ width: 100
+ },
+ {
+ label: "骞撮緞",
+ prop: "age",
+ },
+ {
+ label: "鑱旂郴鐢佃瘽",
+ prop: "phone",
+ width: 150
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉",
+ prop: "emergencyContact",
+ width: 120
+ },
+ {
+ label: "绱ф�ヨ仈绯讳汉鐢佃瘽",
+ prop: "emergencyContactPhone",
+ width: 150
+ },
+ {
+ label: "鍚堝悓缁撴潫鏃ユ湡",
+ prop: "contractExpireTime",
+ width: 120
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ width: 120,
+ operation: [
+ {
+ name: "璇︽儏",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ }
+ ],
+ },
+]);
+const filesDia = ref()
+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 changeDaterange = (value) => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ }
+ getList();
+};
+// 鎵撳紑闄勪欢寮规
+const openFilesFormDia = (row) => {
+ nextTick(() => {
+ filesDia.value?.openDialog( row,'鍚堝悓')
+ })
+};
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined
+ params.staffState = 1
+ staffOnJobListPage(params).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 handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/staff/staffOnJob/export", {staffState: 1}, "鍚堝悓绠$悊.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙鍚堝悓瀵煎叆锛�
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙鍚堝悓瀵煎叆锛�
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 1,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import",
+});
+/** 瀵煎叆鎸夐挳鎿嶄綔 */
+function handleImport() {
+ upload.title = "鍚堝悓瀵煎叆";
+ upload.open = true;
+}
+/** 鎻愪氦涓婁紶鏂囦欢 */
+function submitFileForm() {
+ proxy.$refs["uploadRef"].submit();
+}
+/**鏂囦欢涓婁紶涓鐞� */
+const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true;
+};
+/** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+const handleFileSuccess = (response, file, fileList) => {
+ upload.open = false;
+ upload.isUploading = false;
+ proxy.$refs["uploadRef"].handleRemove(file);
+ getList();
+};
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped></style>
+
diff --git a/src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue b/src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue
new file mode 100644
index 0000000..f731d57
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue
@@ -0,0 +1,347 @@
+<!--OA妯″潡锛氳皟宀楃敵璇�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">瀹℃壒鍗曞彿锛�</span>
+ <el-input
+ v-model="searchForm.instanceNo"
+ style="width: 220px"
+ placeholder="璇疯緭鍏ュ鎵瑰崟鍙�"
+ clearable
+ @keyup.enter="onSearch"
+ />
+ <span class="search_title" style="margin-left: 12px">鐢宠浜猴細</span>
+ <el-select
+ v-model="searchForm.applicantId"
+ filterable
+ remote
+ clearable
+ reserve-keyword
+ placeholder="璇烽�夋嫨鎴栨悳绱㈢敵璇蜂汉"
+ style="width: 220px"
+ :remote-method="remoteSearchApplicant"
+ :loading="applicantSearchLoading"
+ >
+ <el-option
+ v-for="u in applicantSearchOptions"
+ :key="u.userId"
+ :label="userSelectLabel(u)"
+ :value="u.userId"
+ />
+ </el-select>
+ <el-button type="primary" style="margin-left: 10px" @click="onSearch">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" @click="openAddWithTemplate">鏂板璋冨矖鐢宠</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ @pagination="onPagination"
+ :total="page.total"
+ />
+ </div>
+
+ <ApprovalInstanceSubmitDialog
+ v-model="submitDialog.visible"
+ :title="submitDialogTitle"
+ :form="submitForm"
+ :rules="submitFormRules"
+ :fields="submitFormFields"
+ :active-template="activeTemplate"
+ :user-options="flowUserOptions"
+ :is-edit="isSubmitEdit"
+ :saving="submitSaving"
+ :form-ref="submitFormRef"
+ flow-attachments-only
+ @submit="onSubmit"
+ >
+ <template #before="{ form, fields }">
+ <FormPayloadFields :fields="displayTemplateFields(fields)" :form-payload="form.formPayload" />
+ <el-form-item label="鍘熷矖浣�">
+ <el-input :model-value="originalPostName" placeholder="閫夋嫨鐢宠浜哄悗鑷姩甯﹀嚭" disabled />
+ </el-form-item>
+ </template>
+ </ApprovalInstanceSubmitDialog>
+
+ <ApprovalTemplateBindDialog
+ v-model:visible="templateBindVisible"
+ :module-key="APPROVAL_MODULE_KEYS.TRANSFER"
+ skip-form-confirm
+ @confirm="onTemplateBound"
+ @closed="onTemplateBindClosed"
+ />
+
+ <ApprovalInstanceDetailDialog
+ v-model="detailDialog.visible"
+ title="璋冨矖鐢宠璇︽儏"
+ :row="detailRow"
+ @edit="openEditFromDetail"
+ />
+ </div>
+</template>
+
+<script setup>
+import { findPostOptions } from "@/api/system/post.js";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { ElMessage } from "element-plus";
+import { computed, onMounted, reactive, ref, watch } from "vue";
+import FormPayloadFields from "../../ApproveManage/approve-list/components/FormPayloadFields.vue";
+import ApprovalInstanceDetailDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue";
+import ApprovalInstanceSubmitDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue";
+import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
+import { buildInstanceTableColumns } from "../../ApproveManage/approve-shared/approvalInstanceFormConfigTable.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { useApprovalInstanceModule } from "../../ApproveManage/approve-shared/useApprovalInstanceModule.js";
+import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
+import { SELECT_OPTION_SOURCE } from "../../ApproveManage/approve-template/selectOptionSource.js";
+
+function isOriginalPostField(field) {
+ const label = String(field?.label || "");
+ return (
+ label.includes("鍘熷矖浣�") ||
+ field?.key === "originalPost" ||
+ field?.key === "originalPostName" ||
+ field?.key === "originalPostId"
+ );
+}
+
+function displayTemplateFields(fields = []) {
+ return (fields || []).filter((f) => !isOriginalPostField(f));
+}
+
+function findApplicantTemplateField(fields = []) {
+ return (
+ fields.find((f) => String(f?.label || "").includes("鐢宠浜�")) ||
+ fields.find((f) => f?.type === "select" && f?.optionSource === SELECT_OPTION_SOURCE.USER) ||
+ null
+ );
+}
+
+const searchForm = reactive({
+ instanceNo: "",
+ applicantId: "",
+});
+
+const mod = useApprovalInstanceModule({
+ moduleKey: APPROVAL_MODULE_KEYS.TRANSFER,
+});
+
+const {
+ tableData,
+ tableLoading,
+ page,
+ detailDialog,
+ detailRow,
+ submitDialog,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ isSubmitEdit,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitDialogTitle,
+ templateBindVisible,
+ handleQuery,
+ initModuleList,
+ pagination,
+ openAddWithTemplate,
+ onTemplateBound,
+ onTemplateBindClosed,
+ openEditFromDetail,
+ submitInstanceForm,
+ buildTableActions,
+} = mod;
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+const allUsersCache = ref([]);
+const postIdToName = ref({});
+const targetPostOptions = ref([]);
+const applicantSearchLoading = ref(false);
+const applicantSearchOptions = ref([]);
+const originalPostName = ref("");
+
+const applicantTemplateField = computed(() =>
+ findApplicantTemplateField(submitForm.formFieldDefs)
+);
+
+function unwrapArray(payload) {
+ if (Array.isArray(payload)) return payload;
+ if (payload && Array.isArray(payload.data)) return payload.data;
+ if (payload && Array.isArray(payload.rows)) return payload.rows;
+ return [];
+}
+
+function isActiveUser(u) {
+ if (u.delFlag === "2" || u.delFlag === 2) return false;
+ if (u.status == null) return true;
+ return String(u.status) === "0";
+}
+
+function userSelectLabel(u) {
+ const nick = u.nickName || "";
+ const name = u.userName || "";
+ if (nick && name && nick !== name) return `${nick}锛�${name}锛塦;
+ return nick || name || `鐢ㄦ埛${u.userId ?? u.id ?? ""}`;
+}
+
+function firstPostId(user) {
+ if (!user) return undefined;
+ if (Array.isArray(user.postIds) && user.postIds.length) return user.postIds[0];
+ if (user.postId != null && user.postId !== "") return user.postId;
+ return undefined;
+}
+
+function resolveOriginalPost(user) {
+ if (!user) return { originalPostName: "" };
+ const nameStr = (user.postName ?? user.postname ?? "").toString().trim();
+ if (nameStr) return { originalPostName: nameStr };
+ if (Array.isArray(user.posts) && user.posts.length) {
+ return { originalPostName: (user.posts[0].postName ?? "").toString() || "鏈懡鍚嶅矖浣�" };
+ }
+ const pid = firstPostId(user);
+ if (pid != null && pid !== "") {
+ const n = postIdToName.value[String(pid)] || "";
+ return { originalPostName: n || "褰撳墠宀椾綅锛堟湭鍦ㄥ矖浣嶅瓧鍏镐腑锛�" };
+ }
+ return { originalPostName: "鏈垎閰嶅矖浣�" };
+}
+
+function userById(id) {
+ if (id == null || id === "") return undefined;
+ return allUsersCache.value.find((u) => String(u.userId ?? u.id) === String(id));
+}
+
+function filterUsersByQuery(query) {
+ const list = allUsersCache.value.filter((u) => isActiveUser(u));
+ const q = (query || "").trim().toLowerCase();
+ if (!q) return [...list];
+ return list.filter((u) => {
+ const nick = (u.nickName || "").toLowerCase();
+ const uname = (u.userName || "").toLowerCase();
+ const phone = (u.phonenumber || u.phone || "").toString();
+ return nick.includes(q) || uname.includes(q) || phone.includes(q);
+ });
+}
+
+async function loadUserPool() {
+ try {
+ const res = await userListNoPageByTenantId();
+ allUsersCache.value = unwrapArray(res);
+ } catch {
+ allUsersCache.value = [];
+ }
+}
+
+async function loadPostOptions() {
+ try {
+ const res = await findPostOptions();
+ const rows = res.data ?? res.rows ?? [];
+ targetPostOptions.value = Array.isArray(rows) ? rows : [];
+ } catch {
+ targetPostOptions.value = [];
+ }
+ const m = {};
+ for (const p of targetPostOptions.value) {
+ const id = p.postId ?? p.value ?? p.id;
+ if (id != null && id !== "") m[String(id)] = p.postName ?? p.label ?? "";
+ }
+ postIdToName.value = m;
+}
+
+async function remoteSearchApplicant(query) {
+ applicantSearchLoading.value = true;
+ try {
+ if (!allUsersCache.value.length) await loadUserPool();
+ applicantSearchOptions.value = filterUsersByQuery(query);
+ } finally {
+ applicantSearchLoading.value = false;
+ }
+}
+
+function syncOriginalPostFromApplicant(uid) {
+ const u = userById(uid);
+ originalPostName.value = resolveOriginalPost(u).originalPostName;
+}
+
+watch(
+ () => {
+ const key = applicantTemplateField.value?.key;
+ return key ? submitForm.formPayload[key] : undefined;
+ },
+ async (uid) => {
+ if (!applicantTemplateField.value) return;
+ if (!allUsersCache.value.length) await loadUserPool();
+ syncOriginalPostFromApplicant(uid);
+ }
+);
+
+watch(
+ () => submitDialog.visible,
+ async (v) => {
+ if (!v) return;
+ const key = applicantTemplateField.value?.key;
+ if (key && submitForm.formPayload[key]) {
+ syncOriginalPostFromApplicant(submitForm.formPayload[key]);
+ }
+ }
+);
+
+const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, {
+ moduleKey: APPROVAL_MODULE_KEYS.TRANSFER,
+});
+
+function onSearch() {
+ handleQuery(searchForm);
+}
+
+async function resetSearch() {
+ searchForm.instanceNo = "";
+ searchForm.applicantId = "";
+ onSearch();
+ await remoteSearchApplicant("");
+}
+
+function onPagination(obj) {
+ pagination(obj, searchForm);
+}
+
+async function onSubmit() {
+ const ok = await submitInstanceForm({ skipValidate: true });
+ if (ok) ElMessage.success(isSubmitEdit.value ? "淇敼鎴愬姛" : "鎻愪氦鎴愬姛");
+}
+
+onMounted(async () => {
+ await Promise.all([loadUserPool(), loadPostOptions()]);
+ loadFlowUsers();
+ await remoteSearchApplicant("");
+ await initModuleList(searchForm);
+});
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+</style>
diff --git a/src/views/officeProcessAutomation/HrManage/work-handover/index.vue b/src/views/officeProcessAutomation/HrManage/work-handover/index.vue
new file mode 100644
index 0000000..a9b96ae
--- /dev/null
+++ b/src/views/officeProcessAutomation/HrManage/work-handover/index.vue
@@ -0,0 +1,249 @@
+<!--OA妯″潡锛氬伐浣滀氦鎺�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">瀹℃壒鍗曞彿锛�</span>
+ <el-input
+ v-model="searchForm.instanceNo"
+ style="width: 220px"
+ placeholder="璇疯緭鍏ュ鎵瑰崟鍙�"
+ clearable
+ @keyup.enter="onSearch"
+ />
+ <span class="search_title" style="margin-left: 12px">鐢宠浜猴細</span>
+ <el-select
+ v-model="searchForm.applicantId"
+ filterable
+ remote
+ clearable
+ reserve-keyword
+ placeholder="璇烽�夋嫨鎴栨悳绱㈢敵璇蜂汉"
+ style="width: 220px"
+ :remote-method="remoteSearchApplicant"
+ :loading="applicantSearchLoading"
+ >
+ <el-option
+ v-for="u in applicantSearchOptions"
+ :key="u.userId"
+ :label="userSelectLabel(u)"
+ :value="u.userId"
+ />
+ </el-select>
+ <el-button type="primary" style="margin-left: 10px" @click="onSearch">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div>
+ <el-button type="primary" @click="openAddWithTemplate">鏂板宸ヤ綔浜ゆ帴</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ @pagination="onPagination"
+ :total="page.total"
+ />
+ </div>
+
+ <ApprovalInstanceSubmitDialog
+ v-model="submitDialog.visible"
+ :title="submitDialogTitle"
+ :form="submitForm"
+ :rules="submitFormRules"
+ :fields="submitFormFields"
+ :active-template="activeTemplate"
+ :user-options="flowUserOptions"
+ :is-edit="isSubmitEdit"
+ :saving="submitSaving"
+ :form-ref="submitFormRef"
+ @submit="onSubmit"
+ />
+
+ <ApprovalTemplateBindDialog
+ v-model:visible="templateBindVisible"
+ :module-key="APPROVAL_MODULE_KEYS.WORK_HANDOVER"
+ skip-form-confirm
+ @confirm="onTemplateBound"
+ @closed="onTemplateBindClosed"
+ />
+
+ <ApprovalInstanceDetailDialog
+ v-model="detailDialog.visible"
+ title="宸ヤ綔浜ゆ帴璇︽儏"
+ :row="detailRow"
+ @edit="openEditFromDetail"
+ />
+ </div>
+</template>
+
+<script setup>
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { ElMessage } from "element-plus";
+import { onMounted, reactive, ref } from "vue";
+import ApprovalInstanceDetailDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue";
+import ApprovalInstanceSubmitDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue";
+import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
+import { buildInstanceTableColumns } from "../../ApproveManage/approve-shared/approvalInstanceFormConfigTable.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { useApprovalInstanceModule } from "../../ApproveManage/approve-shared/useApprovalInstanceModule.js";
+import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
+
+const handoverStatusOptions = [
+ { value: "in_progress", label: "杩涜涓�" },
+ { value: "completed", label: "宸插畬鎴�" },
+ { value: "returned", label: "宸查��鍥�" },
+];
+
+const handoverTypeOptions = [
+ { value: "resignation", label: "绂昏亴浜ゆ帴" },
+ { value: "transfer", label: "璋冨矖浜ゆ帴" },
+];
+
+const searchForm = reactive({
+ instanceNo: "",
+ applicantId: "",
+});
+
+const mod = useApprovalInstanceModule({
+ moduleKey: APPROVAL_MODULE_KEYS.WORK_HANDOVER,
+});
+
+const {
+ tableData,
+ tableLoading,
+ page,
+ detailDialog,
+ detailRow,
+ submitDialog,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ isSubmitEdit,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitDialogTitle,
+ templateBindVisible,
+ handleQuery,
+ initModuleList,
+ pagination,
+ openAddWithTemplate,
+ onTemplateBound,
+ onTemplateBindClosed,
+ openEditFromDetail,
+ submitInstanceForm,
+ buildTableActions,
+} = mod;
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+const allUsersCache = ref([]);
+const applicantSearchOptions = ref([]);
+const applicantSearchLoading = ref(false);
+
+function unwrapArray(payload) {
+ if (Array.isArray(payload)) return payload;
+ if (payload && Array.isArray(payload.data)) return payload.data;
+ if (payload && Array.isArray(payload.rows)) return payload.rows;
+ return [];
+}
+
+function isActiveUser(u) {
+ if (u.delFlag === "2" || u.delFlag === 2) return false;
+ if (u.status == null) return true;
+ return String(u.status) === "0";
+}
+
+function userSelectLabel(u) {
+ const nick = u.nickName || "";
+ const name = u.userName || "";
+ if (nick && name && nick !== name) return `${nick}锛�${name}锛塦;
+ return nick || name || `鐢ㄦ埛${u.userId ?? u.id ?? ""}`;
+}
+
+function filterUsersByQuery(query) {
+ const list = allUsersCache.value.filter((u) => isActiveUser(u));
+ const q = (query || "").trim().toLowerCase();
+ if (!q) return list.slice(0, 50);
+ return list
+ .filter((u) => {
+ const nick = (u.nickName || "").toLowerCase();
+ const name = (u.userName || "").toLowerCase();
+ const id = String(u.userId ?? u.id ?? "");
+ return nick.includes(q) || name.includes(q) || id.includes(q);
+ })
+ .slice(0, 50);
+}
+
+async function loadUserPool() {
+ try {
+ const res = await userListNoPageByTenantId();
+ allUsersCache.value = unwrapArray(res);
+ } catch {
+ allUsersCache.value = [];
+ }
+}
+
+async function remoteSearchApplicant(query) {
+ applicantSearchLoading.value = true;
+ try {
+ if (!allUsersCache.value.length) await loadUserPool();
+ applicantSearchOptions.value = filterUsersByQuery(query);
+ } finally {
+ applicantSearchLoading.value = false;
+ }
+}
+
+const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, {
+ moduleKey: APPROVAL_MODULE_KEYS.WORK_HANDOVER,
+});
+
+function onSearch() {
+ handleQuery(searchForm);
+}
+
+async function resetSearch() {
+ searchForm.instanceNo = "";
+ searchForm.applicantId = "";
+ onSearch();
+ await remoteSearchApplicant("");
+}
+
+function onPagination(obj) {
+ pagination(obj, searchForm);
+}
+
+async function onSubmit() {
+ const ok = await submitInstanceForm({ skipValidate: true });
+ if (ok) ElMessage.success(isSubmitEdit.value ? "淇敼鎴愬姛" : "鎻愪氦鎴愬姛");
+}
+
+onMounted(async () => {
+ await loadUserPool();
+ loadFlowUsers();
+ await remoteSearchApplicant("");
+ await initModuleList(searchForm);
+});
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+</style>
diff --git a/src/views/officeProcessAutomation/NoticeAnnouncement/notice-manage/index.vue b/src/views/officeProcessAutomation/NoticeAnnouncement/notice-manage/index.vue
new file mode 100644
index 0000000..3f65cb7
--- /dev/null
+++ b/src/views/officeProcessAutomation/NoticeAnnouncement/notice-manage/index.vue
@@ -0,0 +1,12 @@
+<!--
+ 妯″潡涓枃鍚嶏細閫氱煡鍏憡
+ 鐩綍鏍囪瘑锛歂oticeAnnouncement/notice-manage
+ 澶嶇敤椤甸潰锛欯/views/collaborativeApproval/noticeManagement/index.vue锛堝崗鍚屽鎵�-閫氱煡鍏憡锛�
+-->
+<template>
+ <NoticeManagement />
+</template>
+
+<script setup>
+import NoticeManagement from "@/views/collaborativeApproval/noticeManagement/index.vue";
+</script>
diff --git a/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/components/DetailPanel.vue b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/components/DetailPanel.vue
new file mode 100644
index 0000000..4db16a7
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/components/DetailPanel.vue
@@ -0,0 +1,74 @@
+<!-- 璐圭敤鎶ラ攢锛氳鎯呭彧璇婚潰鏉� -->
+<template>
+ <el-descriptions :column="2" border>
+ <el-descriptions-item label="鎶ラ攢鍗曞彿">{{ row.reimburseNo || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鎶ラ攢鐘舵��">
+ <el-tag :type="statusTagType(row.approvalResult)" size="small">{{ statusLabel(row.approvalResult) }}</el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="璐圭敤绫诲瀷">{{ expenseCategoryLabel(row.expenseCategory) }}</el-descriptions-item>
+ <el-descriptions-item label="鐢宠鏃堕棿">{{ row.applyTime || row.createTime || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鍛樺伐缂栧彿">{{ row.employeeNo || row.applicantNo || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鍛樺伐濮撳悕">{{ row.employeeName || row.applicantName || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鎶ラ攢鍘熷洜" :span="2">{{ row.reimburseReason || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鎶ラ攢閲戦">{{ row.applyAmount != null ? `${row.applyAmount} 鍏僠 : "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鏀舵浜�">{{ row.payee || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鏀舵璐﹀彿">{{ row.payeeAccount || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="寮�鎴锋敮琛�">{{ row.bankBranch || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item v-if="row.rejectReason" label="椹冲洖鍘熷洜" :span="2">
+ <span class="reject-text">{{ row.rejectReason }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鍒涘缓鏃堕棿" :span="2">{{ row.createTime || "鈥�" }}</el-descriptions-item>
+ </el-descriptions>
+
+ <el-divider content-position="left">鎶ラ攢鏄庣粏</el-divider>
+ <el-table v-if="row.expenseDetails?.length" :data="row.expenseDetails" border size="small">
+ <el-table-column type="index" label="搴忓彿" width="55" align="center" />
+ <el-table-column prop="invoiceDate" label="鍙戠エ鏃ユ湡" width="120" />
+ <el-table-column label="璐圭敤绉戠洰" width="100">
+ <template #default="{ row: d }">{{ expenseSubjectLabel(d.expenseSubject) }}</template>
+ </el-table-column>
+ <el-table-column prop="amount" label="閲戦" width="100" />
+ <el-table-column prop="description" label="鎻忚堪" min-width="140" show-overflow-tooltip />
+ </el-table>
+ <el-empty v-else description="鏆傛棤鏄庣粏" :image-size="48" />
+
+ <el-divider content-position="left">鍙戠エ闄勪欢</el-divider>
+ <template v-if="attachmentFiles.length">
+ <el-tag v-for="(f, i) in attachmentFiles" :key="i" class="file-tag" type="info" @click="openFile(f)">
+ {{ f.name }}
+ </el-tag>
+ </template>
+ <el-empty v-else description="鏆傛棤闄勪欢" :image-size="48" />
+</template>
+
+<script setup>
+import { computed } from "vue";
+import { expenseCategoryLabel, expenseSubjectLabel, statusLabel, statusTagType } from "../costReimburseUtils.js";
+
+const props = defineProps({
+ row: { type: Object, default: () => ({}) },
+});
+
+const attachmentFiles = computed(() => {
+ const list =
+ props.row?.attachmentList ||
+ props.row?.storageBlobVOList ||
+ props.row?.invoiceAttachments;
+ return Array.isArray(list) ? list : [];
+});
+
+function openFile(f) {
+ const url = f?.url || f?.downloadURL || f?.previewURL;
+ if (url) window.open(url, "_blank");
+}
+</script>
+
+<style scoped>
+.reject-text {
+ color: var(--el-color-danger);
+}
+.file-tag {
+ margin: 0 8px 8px 0;
+ cursor: pointer;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/costReimburseUtils.js b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/costReimburseUtils.js
new file mode 100644
index 0000000..1736b3e
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/costReimburseUtils.js
@@ -0,0 +1,313 @@
+import dayjs from "dayjs";
+
+/** 璐圭敤鎶ラ攢澶х被 */
+export const EXPENSE_CATEGORY_OPTIONS = [
+ { label: "宸梾", value: "travel" },
+ { label: "鍔炲叕閲囪喘", value: "office_procurement" },
+ { label: "涓氬姟鎷涘緟", value: "business_entertainment" },
+ { label: "浜ら�氳垂", value: "transport" },
+ { label: "閫氳璐�", value: "communication" },
+ { label: "鍏朵粬", value: "other" },
+];
+
+/** 鏄庣粏璐圭敤绉戠洰 */
+export const EXPENSE_SUBJECT_OPTIONS = [
+ { label: "浜ら�氳垂", value: "transport" },
+ { label: "浣忓璐�", value: "hotel" },
+ { label: "椁愰ギ璐�", value: "meal" },
+ { label: "鍔炲叕鐢ㄥ搧", value: "office_supply" },
+ { label: "鎷涘緟璐�", value: "entertainment" },
+ { label: "閫氳璐�", value: "phone" },
+ { label: "鍏朵粬", value: "other" },
+];
+
+/** 鍒嗙被濉姤妯℃澘锛堜竴閿皟鐢級 */
+export const CATEGORY_TEMPLATES = {
+ travel: {
+ label: "宸梾璐圭敤",
+ reason: "鍥犲叕鍑哄樊浜х敓鐨勪氦閫氥�佷綇瀹裤�侀楗瓑璐圭敤鎶ラ攢銆�",
+ details: [
+ { expenseSubject: "transport", description: "寰�杩斾氦閫氳垂" },
+ { expenseSubject: "hotel", description: "浣忓璐�" },
+ { expenseSubject: "meal", description: "鍑哄樊椁愰ギ" },
+ ],
+ },
+ office_procurement: {
+ label: "鍔炲叕閲囪喘",
+ reason: "閮ㄩ棬鏃ュ父鍔炲叕鐢ㄥ搧銆佽�楁潗閲囪喘鎶ラ攢銆�",
+ details: [
+ { expenseSubject: "office_supply", description: "鍔炲叕鐢ㄥ搧閲囪喘" },
+ { expenseSubject: "office_supply", description: "鎵撳嵃鑰楁潗" },
+ ],
+ },
+ business_entertainment: {
+ label: "涓氬姟鎷涘緟",
+ reason: "瀹㈡埛鎺ュ緟銆佸晢鍔″璇风瓑璐圭敤鎶ラ攢銆�",
+ details: [
+ { expenseSubject: "entertainment", description: "瀹㈡埛鎺ュ緟椁愯垂" },
+ { expenseSubject: "entertainment", description: "鍟嗗姟绀煎搧" },
+ ],
+ },
+ transport: {
+ label: "浜ら�氳垂",
+ reason: "甯傚唴閫氬嫟銆佹墦杞︺�佸仠杞︾瓑浜ら�氳垂鐢ㄦ姤閿�銆�",
+ details: [{ expenseSubject: "transport", description: "甯傚唴浜ら��" }],
+ },
+ communication: {
+ label: "閫氳璐�",
+ reason: "鍥犲叕閫氳銆佹祦閲忋�佽瘽璐硅ˉ璐存姤閿�銆�",
+ details: [{ expenseSubject: "phone", description: "璇濊垂/娴侀噺" }],
+ },
+ other: {
+ label: "鍏朵粬璐圭敤",
+ reason: "鍏朵粬鍥犲叕鏀嚭璐圭敤鎶ラ攢銆�",
+ details: [{ expenseSubject: "other", description: "鍏朵粬璐圭敤" }],
+ },
+};
+
+/** 瀹℃壒瑙掕壊灞曠ず鍚嶏紙鑺傜偣瀹℃壒浜洪』鍦ㄥ墠绔�夋嫨锛� */
+export const APPROVAL_ROLE_LABELS = {
+ direct_supervisor: "鐩村睘涓婄骇",
+ dept_manager: "閮ㄩ棬缁忕悊",
+ cfo: "璐㈠姟鎬荤洃",
+ compliance: "鍚堣瀹℃牳",
+};
+
+/** 鎸夐噾棰濋璁惧鎵归摼 */
+export const APPROVAL_AMOUNT_RULES = [
+ {
+ maxAmount: 500,
+ description: "500鍏冧互鍐咃細鐩村睘涓婄骇瀹℃壒",
+ roles: ["direct_supervisor"],
+ },
+ {
+ maxAmount: 5000,
+ description: "500锝�5000鍏冿細鐩村睘涓婄骇 + 閮ㄩ棬缁忕悊",
+ roles: ["direct_supervisor", "dept_manager"],
+ },
+ {
+ maxAmount: Infinity,
+ description: "瓒�5000鍏冿細鐩村睘涓婄骇 + 閮ㄩ棬缁忕悊 + 璐㈠姟鎬荤洃澶嶆牳",
+ roles: ["direct_supervisor", "dept_manager", "cfo"],
+ },
+];
+
+/** 閮ㄥ垎鍝佺被棰濆瀹℃壒鑺傜偣 */
+export const CATEGORY_EXTRA_APPROVAL = {
+ business_entertainment: ["compliance"],
+ office_procurement: [],
+};
+
+export function expenseCategoryLabel(v) {
+ return EXPENSE_CATEGORY_OPTIONS.find((x) => x.value === v)?.label || "鈥�";
+}
+
+export function expenseSubjectLabel(v) {
+ return EXPENSE_SUBJECT_OPTIONS.find((x) => x.value === v)?.label || "鈥�";
+}
+
+export function statusLabel(v) {
+ if (v === "draft") return "鑽夌";
+ if (v === "approved") return "宸查�氳繃";
+ if (v === "paid") return "宸蹭粯娆�";
+ if (v === "rejected") return "宸查┏鍥�";
+ if (v === "cancelled") return "宸叉挙鍥�";
+ return "瀹℃牳涓�";
+}
+
+export function statusTagType(v) {
+ if (v === "draft") return "info";
+ if (v === "approved" || v === "paid") return "success";
+ if (v === "rejected") return "danger";
+ if (v === "cancelled") return "info";
+ return "warning";
+}
+
+export { formatApprovalFlowSummary } from "../shared/finReimbursementMappers.js";
+
+export function resolveApprovalRoles(amount, expenseCategory) {
+ const amt = Number(amount) || 0;
+ let roles = [];
+ for (const rule of APPROVAL_AMOUNT_RULES) {
+ if (amt <= rule.maxAmount) {
+ roles = [...rule.roles];
+ break;
+ }
+ }
+ if (!roles.length) roles = ["direct_supervisor"];
+ const extra = CATEGORY_EXTRA_APPROVAL[expenseCategory] || [];
+ extra.forEach((r) => {
+ if (!roles.includes(r)) roles.push(r);
+ });
+ return roles;
+}
+
+export function buildAutoApprovalFlow(amount, expenseCategory, previousNodes = []) {
+ const roles = resolveApprovalRoles(amount, expenseCategory);
+ const prevByRole = new Map();
+ (previousNodes || []).forEach((n, idx) => {
+ if (n?.roleKey) prevByRole.set(n.roleKey, n);
+ else if (n?.approverId != null && n.approverId !== "") {
+ prevByRole.set(`__idx_${idx}`, n);
+ }
+ });
+ return roles.map((role, i) => {
+ const prev = prevByRole.get(role) || prevByRole.get(`__idx_${i}`);
+ const hasApprover = prev?.approverId != null && prev.approverId !== "";
+ return {
+ approverId: hasApprover ? prev.approverId : null,
+ approverName: hasApprover
+ ? prev.approverName || ""
+ : APPROVAL_ROLE_LABELS[role] || role,
+ roleKey: role,
+ signMode: prev?.signMode || "countersign",
+ sortOrder: i + 1,
+ nodeOrder: i + 1,
+ nodeStatus: i === 0 ? "process" : "wait",
+ approveOpinion: "",
+ approveTime: "",
+ };
+ });
+}
+
+export function getApprovalRuleHint(amount, expenseCategory) {
+ const amt = Number(amount) || 0;
+ const rule = APPROVAL_AMOUNT_RULES.find((r) => amt <= r.maxAmount) || APPROVAL_AMOUNT_RULES[APPROVAL_AMOUNT_RULES.length - 1];
+ const extra = CATEGORY_EXTRA_APPROVAL[expenseCategory] || [];
+ const extraText = extra.length
+ ? `锛�${expenseCategoryLabel(expenseCategory)}绫诲彟闇�锛�${extra.map((r) => APPROVAL_ROLE_LABELS[r] || r).join("銆�")}`
+ : "";
+ return `${rule.description}${extraText}`;
+}
+
+export function createEmptyExpenseDetail() {
+ return {
+ id: `ed_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
+ invoiceDate: "",
+ expenseSubject: "",
+ amount: undefined,
+ description: "",
+ };
+}
+
+export function createEmptyForm() {
+ return {
+ id: undefined,
+ reimburseNo: "",
+ applicantId: "",
+ employeeNo: "",
+ employeeName: "",
+ expenseCategory: "",
+ reimburseReason: "",
+ applyAmount: undefined,
+ payee: "",
+ payeeAccount: "",
+ bankBranch: "",
+ expenseDetails: [],
+ attachmentList: [],
+ approvalFlowNodes: [],
+ currentNodeIndex: 0,
+ approvalResult: "pending",
+ rejectReason: "",
+ deptId: "",
+ deptName: "",
+ };
+}
+
+export function applyCategoryTemplate(form, category) {
+ const tpl = CATEGORY_TEMPLATES[category];
+ if (!tpl) return;
+ form.expenseCategory = category;
+ if (!form.reimburseReason?.trim()) form.reimburseReason = tpl.reason;
+ form.expenseDetails = (tpl.details || []).map((d) => ({
+ ...createEmptyExpenseDetail(),
+ expenseSubject: d.expenseSubject,
+ description: d.description,
+ invoiceDate: dayjs().format("YYYY-MM-DD"),
+ }));
+}
+
+export function initApprovalFlowNodes(nodes) {
+ return (nodes || []).map((n, i) => ({
+ ...n,
+ sortOrder: i + 1,
+ nodeOrder: i + 1,
+ nodeStatus: i === 0 ? "process" : "wait",
+ approveOpinion: n.approveOpinion || "",
+ approveTime: n.approveTime || "",
+ }));
+}
+
+export function advanceApprovalFlow(row, opinion) {
+ const nodes = [...(row.approvalFlowNodes || [])];
+ const idx = row.currentNodeIndex ?? 0;
+ if (!nodes.length) return { nodes, currentNodeIndex: idx, approvalResult: row.approvalResult };
+ const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
+ nodes[idx] = {
+ ...nodes[idx],
+ nodeStatus: "finish",
+ approveOpinion: opinion || "鍚屾剰",
+ approveTime: now,
+ };
+ const next = idx + 1;
+ if (next >= nodes.length) {
+ return { nodes, currentNodeIndex: idx, approvalResult: "approved", rejectReason: "" };
+ }
+ nodes[next] = { ...nodes[next], nodeStatus: "process" };
+ return { nodes, currentNodeIndex: next, approvalResult: "pending", rejectReason: "" };
+}
+
+export function rejectApprovalFlow(row, opinion) {
+ const nodes = [...(row.approvalFlowNodes || [])];
+ const idx = row.currentNodeIndex ?? 0;
+ const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
+ const reason = (opinion || "").trim() || "椹冲洖";
+ if (nodes[idx]) {
+ nodes[idx] = {
+ ...nodes[idx],
+ nodeStatus: "error",
+ approveOpinion: reason,
+ approveTime: now,
+ };
+ }
+ return { nodes, currentNodeIndex: idx, approvalResult: "rejected", rejectReason: reason };
+}
+
+export function normalizeImportedRow(raw, idx) {
+ const id = raw.id != null && String(raw.id).length ? `imp_${String(raw.id)}_${idx}` : `imp_${Date.now()}_${idx}`;
+ const expenseDetails = Array.isArray(raw.expenseDetails) ? raw.expenseDetails : [];
+ const applyAmount = raw.applyAmount ?? expenseDetails.reduce((s, d) => s + (Number(d.amount) || 0), 0);
+ const expenseCategory = raw.expenseCategory || "other";
+ const approvalFlowNodes =
+ Array.isArray(raw.approvalFlowNodes) && raw.approvalFlowNodes.length
+ ? raw.approvalFlowNodes
+ : buildAutoApprovalFlow(applyAmount, expenseCategory);
+
+ return {
+ id,
+ reimburseNo: raw.reimburseNo || `CR${dayjs().format("YYYYMMDD")}${String(idx).padStart(4, "0")}`,
+ applicantId: raw.applicantId != null ? String(raw.applicantId) : `imp_user_${idx}`,
+ employeeNo: raw.employeeNo ?? raw.applicantNo ?? "",
+ employeeName: raw.employeeName ?? raw.applicantName ?? "鏈煡",
+ applicantNo: raw.employeeNo ?? raw.applicantNo ?? "",
+ applicantName: raw.employeeName ?? raw.applicantName ?? "鏈煡",
+ expenseCategory,
+ reimburseReason: raw.reimburseReason ?? "",
+ applyAmount,
+ payee: raw.payee ?? "",
+ payeeAccount: raw.payeeAccount ?? "",
+ bankBranch: raw.bankBranch ?? "",
+ expenseDetails,
+ attachmentList: Array.isArray(raw.attachmentList) ? raw.attachmentList : [],
+ invoiceAttachments: Array.isArray(raw.invoiceAttachments) ? raw.invoiceAttachments : [],
+ approvalFlowNodes,
+ currentNodeIndex: raw.currentNodeIndex ?? 0,
+ approvalResult: ["pending", "approved", "rejected"].includes(raw.approvalResult) ? raw.approvalResult : "pending",
+ rejectReason: raw.rejectReason ?? "",
+ approvalRecords: Array.isArray(raw.approvalRecords) ? raw.approvalRecords : [],
+ applyTime: raw.applyTime || raw.createTime || dayjs().format("YYYY-MM-DD HH:mm:ss"),
+ createTime: raw.createTime || dayjs().format("YYYY-MM-DD HH:mm:ss"),
+ deptId: raw.deptId ?? "",
+ deptName: raw.deptName ?? "",
+ };
+}
diff --git a/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/index.vue b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/index.vue
new file mode 100644
index 0000000..c9da4fc
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/index.vue
@@ -0,0 +1,550 @@
+<!--OA妯″潡锛氳垂鐢ㄦ姤閿�锛堝垪琛� /finReimbursement/listPage锛宺eimbursementType=2锛�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div class="search_fields">
+ <span class="search_title">鐢宠浜猴細</span>
+ <el-input
+ v-model="searchForm.applicantKeyword"
+ style="width: 220px"
+ placeholder="濮撳悕鎴栫紪鍙�"
+ clearable
+ :prefix-icon="Search"
+ @keyup.enter="handleQuery"
+ />
+ <el-button type="primary" style="margin-left: 10px" @click="handleQuery">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div class="search_actions">
+ <el-button type="success" plain @click="handleImportClick">瀵煎叆</el-button>
+ <el-button type="warning" plain @click="handleExport">瀵煎嚭</el-button>
+ <el-button type="primary" @click="openFormDialog('add')">鏂板璐圭敤鎶ラ攢</el-button>
+ </div>
+ </div>
+
+ <input ref="importInputRef" type="file" accept="application/json,.json" class="sr-only-input" @change="onImportFile" />
+
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ :total="page.total"
+ @pagination="pagination"
+ />
+ </div>
+
+ <!-- 鏂板 / 缂栬緫 -->
+ <el-dialog
+ v-model="formDialog.visible"
+ :title="formDialog.title"
+ width="1120px"
+ append-to-body
+ destroy-on-close
+ class="cost-reimburse-form-dialog"
+ @closed="onFormClosed"
+ >
+ <el-alert type="info" show-icon :closable="false" class="mb16">
+ <template #title>鍏ㄥ搧绫昏垂鐢ㄦ姤閿� 路 鍒嗙被妯℃澘涓�閿~鎶�</template>
+ <template #default>
+ 鏀寔宸梾銆佸姙鍏噰璐�佷笟鍔℃嫑寰呫�佷氦閫氳垂銆侀�氳璐圭瓑锛涙寜閲戦鑷姩鍖归厤瀹℃壒閾撅紙500鍏冨唴鐩村睘涓婄骇锛岃秴5000鍏冭储鍔℃�荤洃澶嶆牳锛夈��
+ </template>
+ </el-alert>
+
+ <div v-if="!formDialog.readonly" class="template-bar mb16">
+ <span class="template-label">鍒嗙被妯℃澘锛�</span>
+ <el-button
+ v-for="(tpl, key) in CATEGORY_TEMPLATES"
+ :key="key"
+ size="small"
+ :type="form.expenseCategory === key ? 'primary' : 'default'"
+ plain
+ @click="applyTemplate(key)"
+ >
+ {{ tpl.label }}
+ </el-button>
+ </div>
+
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="formRules"
+ label-width="120px"
+ class="cost-reimburse-form"
+ :disabled="formDialog.readonly"
+ >
+ <el-card class="form-section" shadow="never">
+ <template #header><span class="card-header-title">鍩烘湰淇℃伅</span></template>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍛樺伐缂栧彿">
+ <el-input v-model="form.employeeNo" readonly placeholder="閫夋嫨鍛樺伐鍚庤嚜鍔ㄥ甫鍑�" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍛樺伐濮撳悕" prop="applicantId">
+ <el-select
+ v-model="form.applicantId"
+ filterable
+ remote
+ clearable
+ reserve-keyword
+ placeholder="璇烽�夋嫨鎴栨悳绱㈠憳宸�"
+ style="width: 100%"
+ :remote-method="remoteSearchApplicantForm"
+ :loading="applicantFormSearchLoading"
+ @change="onApplicantChange"
+ >
+ <el-option
+ v-for="u in applicantFormOptions"
+ :key="u.userId"
+ :label="userSelectLabel(u)"
+ :value="u.userId"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="璐圭敤绫诲瀷" prop="expenseCategory">
+ <el-select
+ v-model="form.expenseCategory"
+ placeholder="璇烽�夋嫨璐圭敤绫诲瀷"
+ style="width: 100%"
+ @change="onExpenseCategoryChange"
+ >
+ <el-option
+ v-for="opt in EXPENSE_CATEGORY_OPTIONS"
+ :key="opt.value"
+ :label="opt.label"
+ :value="opt.value"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎶ラ攢鐘舵��">
+ <el-tag
+ :type="form.approvalResult === 'approved' ? 'success' : form.approvalResult === 'rejected' ? 'danger' : 'warning'"
+ effect="plain"
+ >
+ {{
+ form.approvalResult === "approved"
+ ? "宸查�氳繃"
+ : form.approvalResult === "rejected"
+ ? "宸查┏鍥�"
+ : "瀹℃牳涓�"
+ }}
+ </el-tag>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="24">
+ <el-form-item label="鎶ラ攢鍘熷洜" prop="reimburseReason">
+ <el-input
+ v-model="form.reimburseReason"
+ type="textarea"
+ :rows="3"
+ placeholder="璇峰~鍐欐姤閿�鍘熷洜"
+ maxlength="2000"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鎶ラ攢閲戦" prop="applyAmount">
+ <div class="amount-row">
+ <el-input-number
+ v-model="form.applyAmount"
+ :min="0"
+ :precision="2"
+ controls-position="right"
+ class="amount-input"
+ @change="autoAssignApprovalFlow"
+ />
+ <el-button v-if="!formDialog.readonly" type="primary" link @click="syncApplyAmountFromDetails">
+ 鎸夋槑缁嗘眹鎬� {{ detailTotalAmount }} 鍏�
+ </el-button>
+ </div>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header>
+ <div class="card-header-row">
+ <span class="card-header-title">鎶ラ攢鏄庣粏</span>
+ <el-button v-if="!formDialog.readonly" type="primary" plain size="small" @click="addExpenseDetail">
+ 鏂板鏄庣粏
+ </el-button>
+ </div>
+ </template>
+
+ <el-table :data="form.expenseDetails" border size="small" class="detail-table">
+ <el-table-column type="index" label="搴忓彿" width="55" align="center" />
+ <el-table-column label="鍙戠エ鏃ユ湡" width="150">
+ <template #default="{ row }">
+ <el-date-picker
+ v-if="!formDialog.readonly"
+ v-model="row.invoiceDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ size="small"
+ style="width: 100%"
+ />
+ <span v-else>{{ row.invoiceDate || "鈥�" }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="璐圭敤绉戠洰" width="130">
+ <template #default="{ row }">
+ <el-select v-if="!formDialog.readonly" v-model="row.expenseSubject" size="small" style="width: 100%">
+ <el-option
+ v-for="opt in EXPENSE_SUBJECT_OPTIONS"
+ :key="opt.value"
+ :label="opt.label"
+ :value="opt.value"
+ />
+ </el-select>
+ <span v-else>{{ expenseSubjectLabel(row.expenseSubject) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="閲戦" width="120">
+ <template #default="{ row }">
+ <el-input-number
+ v-if="!formDialog.readonly"
+ v-model="row.amount"
+ :min="0"
+ :precision="2"
+ size="small"
+ controls-position="right"
+ style="width: 100%"
+ @change="onDetailAmountChange"
+ />
+ <span v-else>{{ row.amount ?? "鈥�" }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎻忚堪" min-width="140">
+ <template #default="{ row }">
+ <el-input v-if="!formDialog.readonly" v-model="row.description" size="small" placeholder="璇存槑" />
+ <span v-else>{{ row.description || "鈥�" }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column v-if="!formDialog.readonly" label="鎿嶄綔" width="70" align="center">
+ <template #default="{ $index }">
+ <el-button type="danger" link size="small" @click="removeExpenseDetail($index)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header><span class="card-header-title">鏀舵淇℃伅</span></template>
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <el-form-item label="鏀舵浜�" prop="payee">
+ <el-input v-model="form.payee" placeholder="璇疯緭鍏ユ敹娆句汉" maxlength="50" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鏀舵璐﹀彿" prop="payeeAccount">
+ <el-input v-model="form.payeeAccount" placeholder="閾惰鍗″彿" maxlength="30" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="寮�鎴锋敮琛�" prop="bankBranch">
+ <el-input v-model="form.bankBranch" placeholder="寮�鎴锋敮琛屽叏绉�" maxlength="100" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header><span class="card-header-title">闄勪欢锛堝彂绁級</span></template>
+ <el-form-item label-width="0" class="attachment-form-item">
+ <div class="upload-block">
+ <FileUpload v-model:file-list="form.attachmentList" :limit="20" button-text="鐐瑰嚮閫夋嫨鏂囦欢" />
+ </div>
+ </el-form-item>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header>
+ <div class="card-header-row">
+ <span class="card-header-title">瀹℃壒娴佺▼</span>
+ <el-button v-if="!formDialog.readonly" type="primary" link size="small" @click="autoAssignApprovalFlow">
+ 鎸夎鍒欓噸鏂板垎閰�
+ </el-button>
+ </div>
+ </template>
+ <el-alert type="success" :title="approvalRuleHint" show-icon :closable="false" class="mb12" />
+ <el-form-item prop="approvalFlowNodes" label-width="0">
+ <ApprovalFlowEditor
+ v-if="!formDialog.readonly"
+ v-model="form.approvalFlowNodes"
+ :user-options="flowUserOptions"
+ @update:model-value="onApprovalFlowChange"
+ />
+ <ApprovalFlowProgress v-else :nodes="form.approvalFlowNodes" :current-index="form.currentNodeIndex" />
+ <p v-if="!formDialog.readonly" class="flow-tip">绯荤粺宸叉寜閲戦涓庤垂鐢ㄧ被鍨嬭嚜鍔ㄥ垎閰嶅鎵逛汉锛屽彲鎵嬪姩璋冩暣銆�</p>
+ </el-form-item>
+ </el-card>
+ </el-form>
+ <template #footer>
+ <el-button
+ v-if="!formDialog.readonly"
+ type="primary"
+ :loading="submitSaving"
+ @click="submitForm"
+ >
+ 鎻� 浜�
+ </el-button>
+ <el-button @click="formDialog.visible = false">{{ formDialog.readonly ? "鍏� 闂�" : "鍙� 娑�" }}</el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 璇︽儏 -->
+ <el-dialog v-model="detailDialog.visible" title="璐圭敤鎶ラ攢璇︽儏" width="900px" append-to-body destroy-on-close>
+ <div v-loading="detailLoading">
+ <DetailPanel :row="detailRow" />
+ <el-divider content-position="left">瀹℃壒娴佺▼</el-divider>
+ <ApprovalFlowProgress
+ :nodes="detailRow.approvalFlowProgressNodes ?? detailRow.approvalFlowNodes"
+ :current-index="detailRow.currentNodeIndex ?? 0"
+ />
+ <el-divider content-position="left">瀹℃壒璁板綍</el-divider>
+ <el-timeline v-if="detailRow.approvalRecords?.length">
+ <el-timeline-item
+ v-for="(rec, i) in detailRow.approvalRecords"
+ :key="i"
+ :type="rec.result === 'approved' ? 'success' : rec.result === 'rejected' ? 'danger' : 'primary'"
+ :timestamp="rec.time"
+ >
+ {{ rec.operatorName }} 鈥� {{ approvalActionLabel(rec.result) }}锛歿{ rec.opinion || "鏃犳剰瑙�" }}
+ </el-timeline-item>
+ </el-timeline>
+ <el-empty v-else description="鏆傛棤瀹℃壒璁板綍" :image-size="60" />
+ </div>
+ <template #footer>
+ <el-button type="primary" @click="detailDialog.visible = false">鍏� 闂�</el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 瀹℃壒 -->
+ <el-dialog
+ v-model="approveDialog.visible"
+ title="璐圭敤鎶ラ攢瀹℃壒"
+ width="1000px"
+ append-to-body
+ destroy-on-close
+ @closed="approveOpinion = ''"
+ >
+ <DetailPanel :row="approveDialog.row" />
+ <el-divider content-position="left">娴佺▼杩涘害</el-divider>
+ <ApprovalFlowProgress
+ :nodes="approveDialog.row?.approvalFlowProgressNodes ?? approveDialog.row?.approvalFlowNodes"
+ :current-index="approveDialog.row?.currentNodeIndex ?? 0"
+ />
+ <el-form label-width="100px" class="mt16">
+ <el-form-item label="瀹℃壒鎰忚" required>
+ <el-input
+ v-model="approveOpinion"
+ type="textarea"
+ :rows="3"
+ maxlength="500"
+ show-word-limit
+ placeholder="閫氳繃鍙暀绌猴紱椹冲洖璇峰~鍐欏叿浣撳師鍥狅紙濡傦細鍙戠エ妯$硦闇�閲嶄紶锛�"
+ />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button type="success" @click="submitApprove('approved')">閫� 杩�</el-button>
+ <el-button type="danger" @click="submitApprove('rejected')">椹� 鍥�</el-button>
+ <el-button @click="approveDialog.visible = false">鍙� 娑�</el-button>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+import ApprovalFlowEditor from "@/views/officeProcessAutomation/AttendManage/overtime-apply/components/ApprovalFlowEditor.vue";
+import ApprovalFlowProgress from "../travel-reimburse/components/ApprovalFlowProgress.vue";
+import DetailPanel from "./components/DetailPanel.vue";
+import { useCostReimburse } from "./useCostReimburse.js";
+
+const cr = useCostReimburse();
+const {
+ Search,
+ EXPENSE_CATEGORY_OPTIONS,
+ CATEGORY_TEMPLATES,
+ EXPENSE_SUBJECT_OPTIONS,
+ expenseSubjectLabel,
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ tableColumn,
+ importInputRef,
+ formRef,
+ form,
+ formDialog,
+ formRules,
+ detailDialog,
+ detailLoading,
+ detailRow,
+ approveDialog,
+ approveOpinion,
+ applicantFormSearchLoading,
+ applicantFormOptions,
+ flowUserOptions,
+ detailTotalAmount,
+ approvalRuleHint,
+ handleQuery,
+ resetSearch,
+ pagination,
+ remoteSearchApplicantForm,
+ userSelectLabel,
+ onApplicantChange,
+ onExpenseCategoryChange,
+ applyTemplate,
+ onDetailAmountChange,
+ onApprovalFlowChange,
+ addExpenseDetail,
+ removeExpenseDetail,
+ syncApplyAmountFromDetails,
+ autoAssignApprovalFlow,
+ openFormDialog,
+ onFormClosed,
+ submitForm,
+ submitSaving,
+ approvalActionLabel,
+ submitApprove,
+ handleExport,
+ handleImportClick,
+ onImportFile,
+} = cr;
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.mb16 {
+ margin-bottom: 16px;
+}
+.mb12 {
+ margin-bottom: 12px;
+}
+.mt16 {
+ margin-top: 16px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_fields {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 4px;
+}
+.search_actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+.sr-only-input {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.template-bar {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 8px;
+}
+.template-label {
+ font-size: 14px;
+ color: var(--el-text-color-secondary);
+ flex-shrink: 0;
+}
+.form-section {
+ margin-bottom: 16px;
+ border: 1px solid var(--el-border-color-lighter);
+}
+.form-section :deep(.el-card__header) {
+ padding: 12px 16px;
+ background: var(--el-fill-color-lighter);
+}
+.form-section :deep(.el-card__body) {
+ padding: 16px 16px 4px;
+}
+.card-header-title {
+ font-size: 15px;
+ font-weight: 600;
+}
+.card-header-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.amount-row {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ width: 100%;
+}
+.amount-input {
+ flex: 1;
+ min-width: 160px;
+}
+.attachment-form-item {
+ margin-bottom: 0;
+}
+.detail-table {
+ margin-bottom: 0;
+}
+.upload-block {
+ width: 100%;
+}
+.flow-tip {
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ margin-top: 8px;
+}
+.cost-reimburse-form-dialog :deep(.el-dialog__body) {
+ padding-top: 12px;
+}
+.cost-reimburse-form :deep(.el-form-item) {
+ margin-bottom: 18px;
+}
+.cost-reimburse-form :deep(.el-input-number) {
+ width: 100%;
+}
+.cost-reimburse-form :deep(.el-row) {
+ margin-bottom: 0;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/useCostReimburse.js b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/useCostReimburse.js
new file mode 100644
index 0000000..3b90a3b
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/cost-reimburse/useCostReimburse.js
@@ -0,0 +1,634 @@
+import { Search } from "@element-plus/icons-vue";
+import dayjs from "dayjs";
+import {
+ deleteFinReimbursement,
+ getFinReimbursementDetail,
+ listFinReimbursementPage,
+ persistFinReimbursement,
+} from "@/api/officeProcessAutomation/finReimbursement.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { computed, getCurrentInstance, nextTick, onMounted, reactive, ref } from "vue";
+import {
+ buildCostReimbursementSaveDto,
+ buildFinReimbursementListParams,
+ filterReimbursementRowsBySearch,
+ hasActiveReimbursementSearch,
+ canDeleteReimbursementRow,
+ canEditReimbursementRow,
+ enrichReimbursementListRowsWithApprovalFlow,
+ filterRowsByReimbursementType,
+ FIN_REIMBURSEMENT_TYPE,
+ mapCostReimbursementRow,
+ mapFinReimbursementDetailRow,
+ resolveReimbursementDeleteId,
+ unwrapFinReimbursementDetail,
+ unwrapFinReimbursementPage,
+ validateReimbursementApprovalNodes,
+ validateReimbursementPersistDto,
+} from "../shared/finReimbursementMappers.js";
+import { consumeReimburseEditFromApprove } from "../shared/reimburseApproveBridge.js";
+import {
+ EXPENSE_CATEGORY_OPTIONS,
+ CATEGORY_TEMPLATES,
+ EXPENSE_SUBJECT_OPTIONS,
+ expenseCategoryLabel,
+ expenseSubjectLabel,
+ statusLabel,
+ statusTagType,
+ formatApprovalFlowSummary,
+ buildAutoApprovalFlow,
+ getApprovalRuleHint,
+ createEmptyExpenseDetail,
+ createEmptyForm,
+ applyCategoryTemplate,
+ initApprovalFlowNodes,
+ advanceApprovalFlow,
+ rejectApprovalFlow,
+ normalizeImportedRow,
+} from "./costReimburseUtils.js";
+
+function unwrapArray(payload) {
+ if (Array.isArray(payload)) return payload;
+ if (payload?.data && Array.isArray(payload.data)) return payload.data;
+ if (payload?.rows && Array.isArray(payload.rows)) return payload.rows;
+ return [];
+}
+
+function isActiveUser(u) {
+ if (u.delFlag === "2" || u.delFlag === 2) return false;
+ if (u.status == null) return true;
+ return String(u.status) === "0";
+}
+
+function demoFlowNodes(amount = 1200, category = "transport") {
+ return buildAutoApprovalFlow(amount, category);
+}
+
+export function useCostReimburse() {
+ const { proxy } = getCurrentInstance();
+
+ const allRows = ref([]);
+
+ const searchForm = reactive({
+ applicantKeyword: "",
+ });
+ const tableLoading = ref(false);
+ const page = reactive({ current: 1, size: 10, total: 0 });
+ const importInputRef = ref(null);
+ const allUsersCache = ref([]);
+ const applicantFormSearchLoading = ref(false);
+ const applicantFormOptions = ref([]);
+ const formRef = ref();
+ const form = reactive(createEmptyForm());
+ const formDialog = reactive({ visible: false, title: "", mode: "add", readonly: false });
+ const detailDialog = reactive({ visible: false });
+ const detailLoading = ref(false);
+ const detailRow = ref({});
+ const approveDialog = reactive({ visible: false, row: null });
+ const approveOpinion = ref("");
+ const submitSaving = ref(false);
+
+ const tableData = computed(() =>
+ allRows.value.map((r) => ({
+ ...r,
+ approvalFlowSummary: formatApprovalFlowSummary(r),
+ }))
+ );
+
+ async function fetchList() {
+ tableLoading.value = true;
+ try {
+ const res = await listFinReimbursementPage(
+ buildFinReimbursementListParams({
+ page,
+ searchForm,
+ reimbursementType: FIN_REIMBURSEMENT_TYPE.COST,
+ })
+ );
+ const { records, total } = unwrapFinReimbursementPage(res);
+ const filtered = filterRowsByReimbursementType(
+ records,
+ FIN_REIMBURSEMENT_TYPE.COST
+ );
+ let mapped = filtered.map(mapCostReimbursementRow);
+ mapped = await enrichReimbursementListRowsWithApprovalFlow(
+ mapped,
+ FIN_REIMBURSEMENT_TYPE.COST
+ );
+ if (hasActiveReimbursementSearch(searchForm)) {
+ mapped = filterReimbursementRowsBySearch(mapped, searchForm);
+ }
+ allRows.value = mapped;
+ const dropped = records.length - filtered.length;
+ let nextTotal =
+ dropped > 0 ? Math.max(0, Number(total) - dropped) : Number(total);
+ if (hasActiveReimbursementSearch(searchForm)) {
+ nextTotal = mapped.length;
+ }
+ page.total = nextTotal;
+ } catch {
+ allRows.value = [];
+ page.total = 0;
+ proxy?.$modal?.msgError?.("璐圭敤鎶ラ攢鍒楄〃鍔犺浇澶辫触");
+ } finally {
+ tableLoading.value = false;
+ }
+ }
+
+ const flowUserOptions = computed(() => allUsersCache.value.filter(isActiveUser));
+
+ const detailTotalAmount = computed(() => {
+ const sum = (form.expenseDetails || []).reduce((s, d) => s + (Number(d.amount) || 0), 0);
+ return Math.round(sum * 100) / 100;
+ });
+
+ const approvalRuleHint = computed(() =>
+ getApprovalRuleHint(form.applyAmount ?? detailTotalAmount.value, form.expenseCategory)
+ );
+
+ const tableColumn = ref([
+ { label: "鎶ラ攢鍗曞彿", prop: "reimburseNo", width: 150 },
+ { label: "鐢宠浜虹紪鍙�", prop: "applicantNo", width: 110 },
+ { label: "鐢宠浜�", prop: "applicantName", minWidth: 90 },
+ { label: "鎶ラ攢閲戦(鍏�)", prop: "applyAmount", width: 110 },
+ { label: "鎶ラ攢鍘熷洜", prop: "reimburseReason", minWidth: 160, showOverflowTooltip: true },
+ { label: "鐢宠鏃堕棿", prop: "applyTime", width: 165 },
+ { label: "鍒涘缓鏃堕棿", prop: "createTime", width: 165 },
+ {
+ label: "鎶ラ攢鐘舵��",
+ prop: "approvalResult",
+ width: 100,
+ dataType: "tag",
+ formatData: (v) => statusLabel(v),
+ formatType: (v) => statusTagType(v),
+ },
+ {
+ label: "瀹℃壒娴佺▼",
+ prop: "approvalFlowSummary",
+ minWidth: 200,
+ showOverflowTooltip: true,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 220,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ disabled: (row) => !canEditReimbursementRow(row),
+ clickFun: (row) => openFormDialog("edit", row),
+ },
+ { name: "璇︽儏", type: "text", clickFun: (row) => openDetail(row) },
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ disabled: (row) => !canDeleteReimbursementRow(row),
+ clickFun: (row) => confirmRemoveRow(row),
+ },
+ ],
+ },
+ ]);
+
+ const formRules = {
+ applicantId: [{ required: true, message: "璇烽�夋嫨鍛樺伐", trigger: "change" }],
+ expenseCategory: [{ required: true, message: "璇烽�夋嫨璐圭敤绫诲瀷", trigger: "change" }],
+ reimburseReason: [{ required: true, message: "璇峰~鍐欐姤閿�鍘熷洜", trigger: "blur" }],
+ applyAmount: [{ required: true, message: "璇峰~鍐欐姤閿�閲戦", trigger: "blur" }],
+ payee: [{ required: true, message: "璇峰~鍐欐敹娆句汉", trigger: "blur" }],
+ payeeAccount: [{ required: true, message: "璇峰~鍐欐敹娆捐处鍙�", trigger: "blur" }],
+ bankBranch: [{ required: true, message: "璇峰~鍐欏紑鎴锋敮琛�", trigger: "blur" }],
+ approvalFlowNodes: [
+ {
+ validator: (_r, _v, cb) => {
+ const nodes = form.approvalFlowNodes || [];
+ if (!nodes.length) {
+ cb(new Error("璇疯嚦灏戦厤缃竴涓鎵硅妭鐐�"));
+ return;
+ }
+ if (nodes.some((n) => n.approverId == null || n.approverId === "")) {
+ cb(new Error("姣忎釜鑺傜偣椤婚�夋嫨瀹℃壒浜�"));
+ return;
+ }
+ cb();
+ },
+ trigger: "change",
+ },
+ ],
+ };
+
+ async function loadUserPool() {
+ try {
+ allUsersCache.value = unwrapArray(await userListNoPageByTenantId());
+ } catch {
+ allUsersCache.value = [];
+ }
+ }
+
+ function userSelectLabel(u) {
+ const nick = u.nickName || "";
+ const name = u.userName || "";
+ if (nick && name && nick !== name) return `${nick}锛�${name}锛塦;
+ return nick || name || `鐢ㄦ埛${u.userId ?? u.id ?? ""}`;
+ }
+
+ function userById(id) {
+ return allUsersCache.value.find((u) => String(u.userId ?? u.id) === String(id));
+ }
+
+ function employeeNoFromUser(u) {
+ if (!u) return "";
+ return u.userName ?? u.userCode ?? u.jobNumber ?? u.workNo ?? (u.userId != null ? String(u.userId) : "");
+ }
+
+ function filterUsersByQuery(query) {
+ const list = allUsersCache.value.filter(isActiveUser);
+ const q = (query || "").trim().toLowerCase();
+ if (!q) return [...list];
+ return list.filter((u) => {
+ const nick = (u.nickName || "").toLowerCase();
+ const uname = (u.userName || "").toLowerCase();
+ return nick.includes(q) || uname.includes(q);
+ });
+ }
+
+ async function remoteSearchApplicantForm(query) {
+ applicantFormSearchLoading.value = true;
+ try {
+ if (!allUsersCache.value.length) await loadUserPool();
+ applicantFormOptions.value = filterUsersByQuery(query);
+ } finally {
+ applicantFormSearchLoading.value = false;
+ }
+ }
+
+ function onApplicantChange(uid) {
+ const u = userById(uid);
+ if (u) {
+ form.employeeName = u.nickName || u.userName || "";
+ form.employeeNo = employeeNoFromUser(u);
+ form.payee = form.payee || form.employeeName;
+ form.deptId = String(u.deptId ?? u.sysDeptId ?? "");
+ form.deptName = u.dept?.deptName ?? u.deptName ?? "";
+ } else {
+ form.employeeName = "";
+ form.employeeNo = "";
+ }
+ }
+
+ function autoAssignApprovalFlow() {
+ const amount = Number(form.applyAmount) || detailTotalAmount.value || 0;
+ form.approvalFlowNodes = buildAutoApprovalFlow(
+ amount,
+ form.expenseCategory || "other",
+ form.approvalFlowNodes
+ );
+ nextTick(() => formRef.value?.validateField?.("approvalFlowNodes"));
+ }
+
+ function onExpenseCategoryChange(val) {
+ if (val && !(form.expenseDetails || []).length) {
+ applyCategoryTemplate(form, val);
+ syncApplyAmountFromDetails();
+ }
+ autoAssignApprovalFlow();
+ }
+
+ function applyTemplate(category) {
+ applyCategoryTemplate(form, category);
+ syncApplyAmountFromDetails();
+ autoAssignApprovalFlow();
+ proxy?.$modal?.msgSuccess?.(`宸插簲鐢ㄣ��${CATEGORY_TEMPLATES[category]?.label || category}銆嶅~鎶ユā鏉縛);
+ }
+
+ function onDetailAmountChange() {
+ syncApplyAmountFromDetails();
+ autoAssignApprovalFlow();
+ }
+
+ function onApprovalFlowChange() {
+ nextTick(() => formRef.value?.validateField?.("approvalFlowNodes"));
+ }
+
+ function addExpenseDetail() {
+ form.expenseDetails.push(createEmptyExpenseDetail());
+ }
+
+ function removeExpenseDetail(index) {
+ form.expenseDetails.splice(index, 1);
+ syncApplyAmountFromDetails();
+ autoAssignApprovalFlow();
+ }
+
+ function syncApplyAmountFromDetails() {
+ form.applyAmount = detailTotalAmount.value;
+ }
+
+ function handleQuery() {
+ page.current = 1;
+ return fetchList();
+ }
+
+ function resetSearch() {
+ searchForm.applicantKeyword = "";
+ handleQuery();
+ }
+
+ function pagination(obj) {
+ page.current = obj.page;
+ page.size = obj.limit;
+ return fetchList();
+ }
+
+ async function loadCostDetailRow(row) {
+ const id = resolveReimbursementDeleteId(row);
+ if (id == null) {
+ throw new Error("missing id");
+ }
+ const res = await getFinReimbursementDetail(id);
+ const raw = unwrapFinReimbursementDetail(res);
+ return mapFinReimbursementDetailRow(raw, FIN_REIMBURSEMENT_TYPE.COST);
+ }
+
+ async function openDetail(row) {
+ const id = resolveReimbursementDeleteId(row);
+ if (id == null) {
+ proxy?.$modal?.msgWarning?.("鏃犳硶鏌ョ湅璇︽儏锛氱己灏戞姤閿�鍗� ID");
+ return;
+ }
+ detailDialog.visible = true;
+ detailLoading.value = true;
+ detailRow.value = { ...row };
+ try {
+ detailRow.value = await loadCostDetailRow(row);
+ } catch {
+ proxy?.$modal?.msgError?.("鍔犺浇璇︽儏澶辫触");
+ detailDialog.visible = false;
+ } finally {
+ detailLoading.value = false;
+ }
+ }
+
+ async function confirmRemoveRow(row) {
+ const id = resolveReimbursementDeleteId(row);
+ if (id == null) {
+ proxy?.$modal?.msgWarning?.("鏃犳硶鍒犻櫎锛氱己灏戞姤閿�鍗� ID");
+ return;
+ }
+ const title = row.reimburseNo || row.billNo || row.reimburseReason || "璇ユ姤閿�鍗�";
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゃ��${title}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+ "鍒犻櫎纭",
+ {
+ type: "warning",
+ confirmButtonText: "纭畾鍒犻櫎",
+ cancelButtonText: "鍙栨秷",
+ distinguishCancelAndClose: true,
+ autofocus: false,
+ }
+ );
+ } catch {
+ return;
+ }
+ try {
+ await deleteFinReimbursement([id]);
+ proxy?.$modal?.msgSuccess?.("鍒犻櫎鎴愬姛");
+ if (detailDialog.visible && resolveReimbursementDeleteId(detailRow.value) === id) {
+ detailDialog.visible = false;
+ }
+ await handleQuery();
+ } catch {
+ proxy?.$modal?.msgError?.("鍒犻櫎澶辫触");
+ }
+ }
+
+ function openApprove(row) {
+ approveDialog.row = { ...row };
+ approveDialog.visible = true;
+ }
+
+ function approvalActionLabel(v) {
+ if (v === "approved") return "閫氳繃";
+ if (v === "rejected") return "椹冲洖";
+ return "鎻愪氦";
+ }
+
+ async function openFormDialog(mode, row) {
+ formDialog.mode = mode;
+ formDialog.readonly = false;
+ formDialog.title = mode === "add" ? "鏂板璐圭敤鎶ラ攢" : "缂栬緫璐圭敤鎶ラ攢";
+ if (!allUsersCache.value.length) await loadUserPool();
+ Object.assign(form, createEmptyForm());
+ if (mode === "edit" && row) {
+ let editRow = row;
+ try {
+ editRow = await loadCostDetailRow(row);
+ } catch {
+ proxy?.$modal?.msgError?.("鍔犺浇鎶ラ攢璇︽儏澶辫触");
+ return;
+ }
+ Object.assign(form, {
+ ...JSON.parse(JSON.stringify(editRow)),
+ reimbursementId: editRow.reimbursementId ?? editRow.id,
+ attachmentList: JSON.parse(JSON.stringify(editRow.attachmentList || editRow.invoiceAttachments || [])),
+ approvalFlowNodes: JSON.parse(JSON.stringify(editRow.approvalFlowNodes || [])),
+ expenseDetails: JSON.parse(JSON.stringify(editRow.expenseDetails || [])),
+ });
+ const u = userById(editRow.applicantId);
+ applicantFormOptions.value = u
+ ? [u]
+ : [{ userId: editRow.applicantId, nickName: editRow.employeeName, userName: editRow.employeeNo }];
+ } else {
+ form.approvalFlowNodes = buildAutoApprovalFlow(0, "other");
+ remoteSearchApplicantForm("");
+ }
+ formDialog.visible = true;
+ nextTick(() => {
+ formRef.value?.clearValidate?.();
+ });
+ }
+
+ function onFormClosed() {
+ formRef.value?.resetFields?.();
+ }
+
+ async function submitForm() {
+ try {
+ await formRef.value?.validate?.();
+ } catch {
+ return;
+ }
+ if (!(form.expenseDetails || []).length) {
+ proxy?.$modal?.msgWarning?.("璇疯嚦灏戞坊鍔犱竴鏉℃姤閿�鏄庣粏");
+ return;
+ }
+ syncApplyAmountFromDetails();
+
+ if (submitSaving.value) return;
+ const isEdit = formDialog.mode === "edit";
+ const dto = buildCostReimbursementSaveDto(form);
+ const check = validateReimbursementPersistDto(dto, isEdit);
+ if (!check.ok) {
+ proxy?.$modal?.msgWarning?.(check.message);
+ return;
+ }
+ const nodeCheck = validateReimbursementApprovalNodes(dto);
+ if (!nodeCheck.ok) {
+ proxy?.$modal?.msgWarning?.(nodeCheck.message);
+ return;
+ }
+ submitSaving.value = true;
+ try {
+ await persistFinReimbursement(dto, isEdit);
+ proxy?.$modal?.msgSuccess?.(isEdit ? "淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
+ formDialog.visible = false;
+ await handleQuery();
+ } catch {
+ proxy?.$modal?.msgError?.(isEdit ? "淇濆瓨澶辫触" : "鎻愪氦澶辫触");
+ } finally {
+ submitSaving.value = false;
+ }
+ }
+
+ async function submitApprove(result) {
+ const row = approveDialog.row;
+ if (!row) return;
+ if (result === "rejected" && !(approveOpinion.value || "").trim()) {
+ proxy?.$modal?.msgWarning?.("椹冲洖椤诲~鍐欏鎵规剰瑙侊紙濡傦細鍙戠エ妯$硦闇�閲嶄紶锛�");
+ return;
+ }
+ const idx = allRows.value.findIndex((r) => r.id === row.id);
+ if (idx === -1) return;
+ const cur = allRows.value[idx];
+ const operatorName = "褰撳墠瀹℃壒浜�";
+ const record = {
+ operatorName,
+ result,
+ opinion: approveOpinion.value || (result === "approved" ? "鍚屾剰" : "椹冲洖"),
+ time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
+ };
+ const records = [...(cur.approvalRecords || []), record];
+ let flowUpdate;
+ if (result === "approved") {
+ flowUpdate = advanceApprovalFlow(cur, approveOpinion.value);
+ } else {
+ flowUpdate = rejectApprovalFlow(cur, approveOpinion.value);
+ }
+ allRows.value[idx] = {
+ ...cur,
+ approvalFlowNodes: flowUpdate.nodes,
+ currentNodeIndex: flowUpdate.currentNodeIndex,
+ approvalResult: flowUpdate.approvalResult,
+ rejectReason: flowUpdate.rejectReason ?? cur.rejectReason,
+ approvalRecords: records,
+ };
+ proxy?.$modal?.msgSuccess?.(result === "approved" ? "宸查�氳繃" : "宸查┏鍥�");
+ approveDialog.visible = false;
+ handleQuery();
+ }
+
+ function handleExport() {
+ const data = allRows.value;
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json;charset=utf-8" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `璐圭敤鎶ラ攢瀵煎嚭_${dayjs().format("YYYYMMDDHHmmss")}.json`;
+ a.click();
+ URL.revokeObjectURL(url);
+ proxy?.$modal?.msgSuccess?.(`宸插鍑� ${data.length} 鏉);
+ }
+
+ function handleImportClick() {
+ importInputRef.value?.click?.();
+ }
+
+ function onImportFile(e) {
+ const file = e.target.files?.[0];
+ e.target.value = "";
+ if (!file) return;
+ const reader = new FileReader();
+ reader.onload = () => {
+ try {
+ const parsed = JSON.parse(String(reader.result || ""));
+ const arr = Array.isArray(parsed) ? parsed : parsed?.rows || parsed?.data;
+ if (!Array.isArray(arr) || !arr.length) {
+ proxy?.$modal?.msgWarning?.("瀵煎叆鏍煎紡椤讳负璐圭敤鎶ラ攢 JSON 鏁扮粍");
+ return;
+ }
+ arr.forEach((raw, i) => allRows.value.unshift(normalizeImportedRow(raw, i)));
+ proxy?.$modal?.msgSuccess?.(`鎴愬姛瀵煎叆 ${arr.length} 鏉);
+ handleQuery();
+ } catch {
+ proxy?.$modal?.msgError?.("瑙f瀽澶辫触");
+ }
+ };
+ reader.readAsText(file, "utf-8");
+ }
+
+ onMounted(async () => {
+ loadUserPool();
+ await fetchList();
+ const editPayload = consumeReimburseEditFromApprove();
+ if (editPayload?.reimbursementId != null) {
+ await openFormDialog("edit", { reimbursementId: editPayload.reimbursementId });
+ }
+ });
+
+ return {
+ Search,
+ EXPENSE_CATEGORY_OPTIONS,
+ CATEGORY_TEMPLATES,
+ EXPENSE_SUBJECT_OPTIONS,
+ expenseCategoryLabel,
+ expenseSubjectLabel,
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ tableColumn,
+ importInputRef,
+ formRef,
+ form,
+ formDialog,
+ formRules,
+ detailDialog,
+ detailLoading,
+ detailRow,
+ approveDialog,
+ approveOpinion,
+ applicantFormSearchLoading,
+ applicantFormOptions,
+ flowUserOptions,
+ detailTotalAmount,
+ approvalRuleHint,
+ handleQuery,
+ resetSearch,
+ pagination,
+ remoteSearchApplicantForm,
+ userSelectLabel,
+ onApplicantChange,
+ onExpenseCategoryChange,
+ applyTemplate,
+ onDetailAmountChange,
+ onApprovalFlowChange,
+ addExpenseDetail,
+ removeExpenseDetail,
+ syncApplyAmountFromDetails,
+ autoAssignApprovalFlow,
+ openFormDialog,
+ onFormClosed,
+ submitForm,
+ submitSaving,
+ openDetail,
+ approvalActionLabel,
+ submitApprove,
+ handleExport,
+ handleImportClick,
+ onImportFile,
+ };
+}
diff --git a/src/views/officeProcessAutomation/ReimburseManage/shared/components/FinReimburseApprovePanel.vue b/src/views/officeProcessAutomation/ReimburseManage/shared/components/FinReimburseApprovePanel.vue
new file mode 100644
index 0000000..724376d
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/shared/components/FinReimburseApprovePanel.vue
@@ -0,0 +1,70 @@
+<!-- 宸梾/璐圭敤鎶ラ攢锛氬鎵瑰垪琛ㄥ唴璇︽儏/瀹℃壒寮圭獥鍐呭锛堜笌鎶ラ攢椤靛脊绐椾竴鑷达級 -->
+<template>
+ <div v-loading="loading">
+ <TravelDetailPanel v-if="isTravel" :row="reimburseRow" />
+ <CostDetailPanel v-else :row="reimburseRow" />
+
+ <el-divider content-position="left">娴佺▼杩涘害</el-divider>
+ <ApprovalFlowProgress
+ :nodes="reimburseRow.approvalFlowProgressNodes ?? reimburseRow.approvalFlowNodes"
+ :current-index="reimburseRow.currentNodeIndex ?? 0"
+ />
+
+ <template v-if="mode === 'detail'">
+ <el-divider content-position="left">瀹℃壒璁板綍锛堝叏娴佺▼鐣欑棔锛�</el-divider>
+ <el-timeline v-if="reimburseRow.approvalRecords?.length">
+ <el-timeline-item
+ v-for="(rec, i) in reimburseRow.approvalRecords"
+ :key="i"
+ :type="rec.result === 'approved' ? 'success' : rec.result === 'rejected' ? 'danger' : 'primary'"
+ :timestamp="rec.time"
+ >
+ {{ rec.operatorName }} 鈥� {{ actionLabel(rec.result) }}锛歿{ rec.opinion || "鏃犳剰瑙�" }}
+ </el-timeline-item>
+ </el-timeline>
+ <el-empty v-else description="鏆傛棤瀹℃壒璁板綍" :image-size="60" />
+ </template>
+
+ <el-form v-else label-width="100px" class="mt16">
+ <el-form-item label="瀹℃壒鎰忚">
+ <el-input
+ :model-value="approveOpinion"
+ type="textarea"
+ :rows="3"
+ maxlength="500"
+ show-word-limit
+ :placeholder="isTravel ? '閫氳繃鍙暀绌猴紱椹冲洖璇峰~鍐欏師鍥�' : '閫氳繃鍙暀绌猴紱椹冲洖璇峰~鍐欏叿浣撳師鍥狅紙濡傦細鍙戠エ妯$硦闇�閲嶄紶锛�'"
+ @update:model-value="$emit('update:approveOpinion', $event)"
+ />
+ </el-form-item>
+ </el-form>
+ </div>
+</template>
+
+<script setup>
+import { computed } from "vue";
+import { isTravelReimbursementType } from "../finReimbursementMappers.js";
+import ApprovalFlowProgress from "../../travel-reimburse/components/ApprovalFlowProgress.vue";
+import CostDetailPanel from "../../cost-reimburse/components/DetailPanel.vue";
+import TravelDetailPanel from "../../travel-reimburse/components/DetailPanel.vue";
+
+const props = defineProps({
+ mode: { type: String, default: "detail" },
+ moduleKey: { type: String, default: "" },
+ reimburseRow: { type: Object, default: () => ({}) },
+ loading: { type: Boolean, default: false },
+ approveOpinion: { type: String, default: "" },
+});
+
+defineEmits(["update:approveOpinion"]);
+
+const isTravel = computed(() =>
+ isTravelReimbursementType(props.reimburseRow?.reimbursementType ?? props.moduleKey)
+);
+
+function actionLabel(v) {
+ if (v === "approved") return "閫氳繃";
+ if (v === "rejected") return "椹冲洖";
+ return "鎻愪氦";
+}
+</script>
diff --git a/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js b/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js
new file mode 100644
index 0000000..c72633b
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementDetailExtras.js
@@ -0,0 +1,160 @@
+import { formatDisplayTime } from "../../ApproveManage/approve-template/approveTemplateConstants.js";
+import {
+ mapRecordResultFromApi,
+ mapRecordsFromApi,
+ mapTasksToFlowNodes,
+} from "../../ApproveManage/approve-list/approveListConstants.js";
+
+function taskStatusToNodeStatus(taskStatus) {
+ const s = String(taskStatus ?? "").toUpperCase();
+ if (["APPROVED", "COMPLETED", "FINISHED", "PASSED", "AGREE"].includes(s)) {
+ return "finish";
+ }
+ if (["REJECTED", "REJECT", "REFUSE", "REFUSED"].includes(s)) {
+ return "error";
+ }
+ if (["PENDING", "IN_APPROVAL", "PROCESS", "PROCESSING"].includes(s)) {
+ return "process";
+ }
+ return "wait";
+}
+
+/** storageBlobVOList 鈫� 椤甸潰闄勪欢鍒楄〃 */
+export function mapReimbursementAttachments(source = {}) {
+ const list =
+ source.storageBlobVOList ||
+ source.storageBlobDTOs ||
+ source.storageBlobDTOS ||
+ source.storageBlobVOS ||
+ source.attachmentList ||
+ source.invoiceAttachments ||
+ [];
+ if (!Array.isArray(list)) return [];
+ return list.map((b, i) => ({
+ ...b,
+ id: b.id ?? b.blobId ?? `att_${i}`,
+ name:
+ b.fileName ||
+ b.originalFilename ||
+ b.originalFileName ||
+ b.blobName ||
+ b.name ||
+ "闄勪欢",
+ url:
+ b.url ||
+ b.fileUrl ||
+ b.downloadUrl ||
+ b.downloadURL ||
+ b.previewUrl ||
+ b.previewURL ||
+ b.link ||
+ "",
+ }));
+}
+
+/** 瀹℃壒璁板綍鏉ヨ嚜 tasks锛堟瘡鏉′换鍔′竴鏉$暀鐥曪級 */
+export function mapTasksToApprovalRecords(tasks) {
+ const list = Array.isArray(tasks) ? tasks : [];
+ return list
+ .map((t, index) => ({
+ id: t.id ?? index,
+ operatorName: t.approverName || t.operatorName || t.createUserName || "鈥�",
+ result: mapRecordResultFromApi(
+ t.approveAction ?? t.taskStatus ?? t.status
+ ),
+ opinion: t.approveComment || t.comment || t.opinion || "",
+ time: formatDisplayTime(
+ t.approveTime || t.finishTime || t.updateTime || t.createTime || ""
+ ),
+ levelNo: t.levelNo ?? t.taskLevel,
+ raw: t,
+ }))
+ .sort((a, b) => {
+ const la = Number(a.levelNo ?? 0);
+ const lb = Number(b.levelNo ?? 0);
+ if (la !== lb) return la - lb;
+ return String(a.time).localeCompare(String(b.time));
+ });
+}
+
+/** tasks 鈫� ApprovalFlowProgress 鑺傜偣 */
+export function mapTasksToApprovalFlowNodes(tasks) {
+ const grouped = mapTasksToFlowNodes(tasks);
+ return grouped.map((node, i) => {
+ const approvers = node.approvers || [];
+ const statuses = approvers.map(a =>
+ taskStatusToNodeStatus(a.taskStatus ?? a.status)
+ );
+ let nodeStatus = "wait";
+ if (statuses.includes("error")) nodeStatus = "error";
+ else if (statuses.length && statuses.every(s => s === "finish")) {
+ nodeStatus = "finish";
+ } else if (statuses.includes("process")) nodeStatus = "process";
+
+ const names = approvers.map(a => a.approverName).filter(Boolean).join("銆�");
+ const opinions = approvers
+ .map(a => a.approveComment)
+ .filter(Boolean)
+ .join("锛�");
+
+ return {
+ nodeOrder: node.nodeOrder ?? node.levelNo ?? i + 1,
+ sortOrder: node.nodeOrder ?? node.levelNo ?? i + 1,
+ approverName: names || "鈥�",
+ approveOpinion: opinions,
+ approveTime: approvers.find(a => a.approveTime)?.approveTime || "",
+ nodeStatus,
+ signMode: node.signMode,
+ };
+ });
+}
+
+export function computeApprovalFlowCurrentIndex(approvalFlowNodes = []) {
+ const list = approvalFlowNodes || [];
+ const processing = list.findIndex(n => n.nodeStatus === "process");
+ if (processing >= 0) return processing;
+ const errorIdx = list.findIndex(n => n.nodeStatus === "error");
+ if (errorIdx >= 0) return errorIdx;
+ return list.filter(n => n.nodeStatus === "finish").length;
+}
+
+/** 璇︽儏 DTO 琛ュ厖 tasks / 闄勪欢 / 瀹℃壒璁板綍 */
+export function applyFinReimbursementDetailEnrichment(mapped, raw = {}) {
+ if (!mapped || typeof mapped !== "object") return mapped;
+ const source = { ...raw, ...mapped };
+ const tasks = Array.isArray(source.tasks) ? source.tasks : [];
+ const attachments = mapReimbursementAttachments(source);
+ const approvalRecords = tasks.length
+ ? mapTasksToApprovalRecords(tasks)
+ : mapRecordsFromApi(source.records || source.approvalRecords);
+ /** 琛ㄥ崟缂栬緫鍥炴樉锛氫繚鐣� nodes 鏄犲皠锛堝惈 approverId锛夛紝鍕跨敤 tasks 瑕嗙洊 */
+ const approvalFlowNodes = Array.isArray(mapped.approvalFlowNodes)
+ ? mapped.approvalFlowNodes
+ : [];
+ /** 璇︽儏/杩涘害鏉″睍绀猴細鏈� tasks 鏃剁敤浠诲姟鐘舵�佽妭鐐� */
+ const approvalFlowProgressNodes = tasks.length
+ ? mapTasksToApprovalFlowNodes(tasks)
+ : approvalFlowNodes;
+ const currentNodeIndex = computeApprovalFlowCurrentIndex(
+ approvalFlowProgressNodes.length ? approvalFlowProgressNodes : approvalFlowNodes
+ );
+ const rejectReason =
+ approvalRecords.find(r => r.result === "rejected")?.opinion ||
+ source.rejectReason ||
+ "";
+
+ return {
+ ...mapped,
+ tasks,
+ storageBlobVOList: attachments,
+ attachmentList: attachments,
+ invoiceAttachments: attachments,
+ approvalRecords,
+ records: tasks.length ? tasks : source.records,
+ approvalFlowNodes,
+ approvalFlowProgressNodes,
+ currentNodeIndex,
+ rejectReason,
+ flowNodes: tasks.length ? mapTasksToFlowNodes(tasks) : mapped.flowNodes,
+ };
+}
diff --git a/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementMappers.js b/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementMappers.js
new file mode 100644
index 0000000..2525f70
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/shared/finReimbursementMappers.js
@@ -0,0 +1,904 @@
+import dayjs from "dayjs";
+import { getFinReimbursementDetail } from "@/api/officeProcessAutomation/finReimbursement.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { mapSignModeToApi } from "../../ApproveManage/approve-template/approveTemplateConstants.js";
+import { EXPENSE_CATEGORY_OPTIONS } from "../cost-reimburse/costReimburseUtils.js";
+import { EXPENSE_SUBJECT_OPTIONS } from "../travel-reimburse/travelReimburseUtils.js";
+import { mapTasksToFlowNodes } from "../../ApproveManage/approve-list/approveListConstants.js";
+import { applyFinReimbursementDetailEnrichment } from "./finReimbursementDetailExtras.js";
+
+/** 鎶ラ攢绫诲瀷锛�1-宸梾鎶ラ攢锛�2-璐圭敤鎶ラ攢 */
+export const FIN_REIMBURSEMENT_TYPE = {
+ TRAVEL: "1",
+ COST: "2",
+};
+
+const REIMBURSEMENT_TYPE_LABEL = {
+ [FIN_REIMBURSEMENT_TYPE.TRAVEL]: "宸梾鎶ラ攢",
+ [FIN_REIMBURSEMENT_TYPE.COST]: "璐圭敤鎶ラ攢",
+};
+
+/** 褰掍竴鍖栨姤閿�绫诲瀷锛�1-宸梾锛�2-璐圭敤 */
+export function normalizeReimbursementType(val) {
+ const s = String(val ?? "").trim();
+ if (s === "1" || s === FIN_REIMBURSEMENT_TYPE.TRAVEL) {
+ return FIN_REIMBURSEMENT_TYPE.TRAVEL;
+ }
+ if (s === "2" || s === FIN_REIMBURSEMENT_TYPE.COST) {
+ return FIN_REIMBURSEMENT_TYPE.COST;
+ }
+ return "";
+}
+
+export function reimbursementTypeLabel(type) {
+ return REIMBURSEMENT_TYPE_LABEL[normalizeReimbursementType(type)] || "鈥�";
+}
+
+export function getModuleKeyByReimbursementType(type) {
+ const t = normalizeReimbursementType(type);
+ if (t === FIN_REIMBURSEMENT_TYPE.TRAVEL) {
+ return APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE;
+ }
+ if (t === FIN_REIMBURSEMENT_TYPE.COST) {
+ return APPROVAL_MODULE_KEYS.COST_REIMBURSE;
+ }
+ return "";
+}
+
+/** 浼樺厛鎺ュ彛 reimbursementType锛屽叾娆¢〉闈� moduleKey / 鍏ュ弬 */
+export function resolveReimbursementType(raw, fallback) {
+ const fromApi = normalizeReimbursementType(raw?.reimbursementType);
+ if (fromApi) return fromApi;
+ return (
+ normalizeReimbursementType(fallback) ||
+ getReimbursementTypeByModuleKey(fallback) ||
+ ""
+ );
+}
+
+export function isTravelReimbursementType(type) {
+ return (
+ resolveReimbursementType({ reimbursementType: type }, type) ===
+ FIN_REIMBURSEMENT_TYPE.TRAVEL
+ );
+}
+
+export function filterRowsByReimbursementType(rows, expectedType) {
+ const expected = normalizeReimbursementType(expectedType);
+ if (!expected) return rows || [];
+ return (rows || []).filter((row) => {
+ const t = resolveReimbursementType(row, expected);
+ return t === expected;
+ });
+}
+
+export function getReimbursementTypeByModuleKey(moduleKey) {
+ if (moduleKey === APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE) {
+ return FIN_REIMBURSEMENT_TYPE.TRAVEL;
+ }
+ if (moduleKey === APPROVAL_MODULE_KEYS.COST_REIMBURSE) {
+ return FIN_REIMBURSEMENT_TYPE.COST;
+ }
+ return "";
+}
+
+export function unwrapFinReimbursementPage(res) {
+ const data = res?.data ?? res;
+ if (!data || typeof data !== "object") {
+ return { records: [], total: 0 };
+ }
+ if (Array.isArray(data.records)) {
+ return { records: data.records, total: Number(data.total ?? 0) };
+ }
+ const nested = data.data;
+ if (nested && typeof nested === "object" && Array.isArray(nested.records)) {
+ return { records: nested.records, total: Number(nested.total ?? 0) };
+ }
+ return { records: [], total: 0 };
+}
+
+/** 璇︽儏鎺ュ彛 data 瑙e寘 */
+export function unwrapFinReimbursementDetail(res) {
+ const data = res?.data ?? res;
+ if (!data || typeof data !== "object") return {};
+ if (data.billNo != null || data.id != null || data.reimbursementType != null) {
+ return data;
+ }
+ const nested = data.data;
+ if (nested && typeof nested === "object" && !Array.isArray(nested)) {
+ return nested;
+ }
+ if (data.finReimbursementDto && typeof data.finReimbursementDto === "object") {
+ return data.finReimbursementDto;
+ }
+ return data;
+}
+
+/** 璇︽儏鏌ヨ鍙傛暟锛坬uery finReimbursementDto锛� */
+export function buildFinReimbursementDetailParams(id) {
+ const raw = id?.id != null ? id.id : id;
+ const n = toNumber(raw);
+ return { finReimbursementDto: { id: n != null ? n : raw } };
+}
+
+/** 璇︽儏 DTO 鈫� 椤甸潰琛岋紙鎸� reimbursementType 鏄犲皠锛屽惈 tasks / storageBlobVOList锛� */
+export function mapFinReimbursementDetailRow(raw, reimbursementTypeOrModuleKey) {
+ const type = resolveReimbursementType(raw, reimbursementTypeOrModuleKey);
+ let mapped = {};
+ if (type === FIN_REIMBURSEMENT_TYPE.TRAVEL) {
+ mapped = mapTravelReimbursementRow(raw);
+ } else if (type === FIN_REIMBURSEMENT_TYPE.COST) {
+ mapped = mapCostReimbursementRow(raw);
+ } else {
+ mapped = raw || {};
+ }
+
+ let formApprovalFlowNodes = mapNodesToFormFlow(resolveRowApiNodes(raw));
+ if (!formApprovalFlowNodes.length && Array.isArray(raw?.tasks) && raw.tasks.length) {
+ formApprovalFlowNodes = mapNodesToFormFlow(mapTasksToFlowNodes(raw.tasks));
+ }
+
+ const enriched = applyFinReimbursementDetailEnrichment(mapped, raw);
+ return {
+ ...enriched,
+ approvalFlowNodes: formApprovalFlowNodes.length
+ ? formApprovalFlowNodes
+ : enriched.approvalFlowNodes,
+ reimbursementType: type,
+ reimbursementTypeLabel: reimbursementTypeLabel(type),
+ moduleKey: getModuleKeyByReimbursementType(type),
+ };
+}
+
+/** 鍗曟嵁鐘舵�� 鈫� 椤甸潰 approvalResult锛堝吋瀹� statusLabel锛� */
+export function mapBillStatusToApprovalResult(billStatus) {
+ const upper = String(billStatus ?? "").trim().toUpperCase();
+ if (upper === "DRAFT") return "draft";
+ if (upper === "IN_APPROVAL") return "pending";
+ if (upper === "APPROVED") return "approved";
+ if (upper === "REJECTED") return "rejected";
+ if (upper === "WITHDRAWN") return "cancelled";
+ if (upper === "PAID") return "paid";
+ return "pending";
+}
+
+function pickApplicantQuery(searchForm = {}) {
+ const kw = (searchForm.applicantKeyword || "").trim();
+ if (!kw) return {};
+ // 鍗犱綅銆屽鍚嶆垨缂栧彿銆嶏細濮撳悕璧� applicantName锛涚紪鍙峰彟浼� applicantCode
+ const out = { applicantName: kw };
+ if (!/[\u4e00-\u9fa5]/.test(kw)) {
+ out.applicantCode = kw;
+ }
+ return out;
+}
+
+/** 鏄惁瀛樺湪鍒楄〃绛涢�夋潯浠讹紙浠呯敵璇蜂汉锛� */
+export function hasActiveReimbursementSearch(searchForm = {}) {
+ return Boolean((searchForm?.applicantKeyword || "").trim());
+}
+
+/** 鏈嶅姟绔湭鐢熸晥鏃讹紝鎸夌敵璇蜂汉鍋氬墠绔厹搴曠瓫閫� */
+export function filterReimbursementRowsBySearch(rows, searchForm = {}) {
+ const list = Array.isArray(rows) ? rows : [];
+ const kw = (searchForm?.applicantKeyword || "").trim().toLowerCase();
+ if (!kw) return list;
+
+ return list.filter((row) => {
+ const parts = [
+ row.applicantName,
+ row.employeeName,
+ row.applicantNo,
+ row.applicantCode,
+ row.employeeNo,
+ ]
+ .filter((v) => v != null && v !== "")
+ .map((v) => String(v).toLowerCase());
+ return parts.some((p) => p.includes(kw));
+ });
+}
+
+/** 鎵佸钩鍖栦负 Spring GET 鍙粦瀹氱殑 query锛坒inReimbursementDto.xxx锛屽嬁鐢ㄦ柟鎷彿锛� */
+function appendDotNotationQuery(target, prefix, fields) {
+ if (!fields || typeof fields !== "object") return;
+ for (const [key, value] of Object.entries(fields)) {
+ if (value == null || value === "") continue;
+ target[`${prefix}.${key}`] = value;
+ }
+}
+
+/** 缁勮 listPage 鏌ヨ鍙傛暟锛堟墎骞� page.* / finReimbursementDto.*锛屼笌 detail 鎺ュ彛涓�鑷达級 */
+export function buildFinReimbursementListParams({
+ page,
+ searchForm,
+ reimbursementType,
+ extraDto = {},
+}) {
+ const dto = {
+ reimbursementType,
+ ...pickApplicantQuery(searchForm),
+ ...(extraDto && typeof extraDto === "object" ? extraDto : {}),
+ };
+
+ const params = {
+ current: page.current,
+ size: page.size,
+ "page.current": page.current,
+ "page.size": page.size,
+ ...dto,
+ };
+ appendDotNotationQuery(params, "finReimbursementDto", dto);
+ return params;
+}
+
+function pickTravelField(obj, keys) {
+ if (!obj || typeof obj !== "object") return "";
+ for (const key of keys) {
+ const v = obj[key];
+ if (v != null && v !== "") return v;
+ }
+ return "";
+}
+
+/** 鍏煎 list/detail 澶氱宸梾瀛愬璞$粨鏋� */
+export function pickTravelFromRow(row) {
+ if (!row || typeof row !== "object") return {};
+ const nested =
+ (row.travel && typeof row.travel === "object" ? row.travel : null) ||
+ row.finReimbursementTravel ||
+ row.finReimbursementTravelDto ||
+ row.travelDto ||
+ row.travelVO ||
+ {};
+ const src =
+ nested && typeof nested === "object" && Object.keys(nested).length
+ ? nested
+ : row;
+ return {
+ startTime: pickTravelField(src, [
+ "startTime",
+ "travelStartTime",
+ "startDate",
+ "travelStartDate",
+ "departureTime",
+ ]),
+ endTime: pickTravelField(src, [
+ "endTime",
+ "travelEndTime",
+ "endDate",
+ "travelEndDate",
+ "returnTime",
+ ]),
+ travelDays: src.travelDays,
+ departureCity: pickTravelField(src, [
+ "departureCity",
+ "departurePlace",
+ "departure",
+ ]),
+ destinationCity: pickTravelField(src, [
+ "destinationCity",
+ "destination",
+ "destinationPlace",
+ ]),
+ hotelStandard: src.hotelStandard,
+ lodgingDays: src.lodgingDays ?? src.hotelDays,
+ mealAllowance: src.mealAllowance ?? src.livingSubsidy,
+ transportAllowance: src.transportAllowance ?? src.transportSubsidy,
+ lodgingLimit: src.lodgingLimit,
+ withinStandard: src.withinStandard,
+ standardTag: src.standardTag || "",
+ id: src.id,
+ reimbursementId: src.reimbursementId,
+ };
+}
+
+/** 鍒楄〃/璇︽儏鏃堕棿灞曠ず锛圛SO 鈫� YYYY-MM-DD HH:mm:ss锛� */
+export function formatReimbursementDateTime(val) {
+ if (val == null || val === "") return "";
+ const d = dayjs(val);
+ if (!d.isValid()) return String(val);
+ const raw = String(val);
+ const hasTime = raw.includes("T") || /:\d{2}/.test(raw);
+ return hasTime ? d.format("YYYY-MM-DD HH:mm:ss") : d.format("YYYY-MM-DD");
+}
+
+/** 鎺ュ彛琛� 鈫� 宸梾鎶ラ攢鍒楄〃琛岋紙鍏煎 useTravelReimburse 瀛楁锛� */
+export function mapTravelReimbursementRow(row) {
+ if (!row) return {};
+ const travel = pickTravelFromRow(row);
+ const details = Array.isArray(row.details) ? row.details : [];
+
+ const base = {
+ ...row,
+ id: row.id,
+ reimbursementId: row.id,
+ approvalInstanceId: row.approvalInstanceId,
+ reimburseNo: row.billNo || "",
+ applicantId: row.applicantId,
+ applicantNo: row.applicantCode || "",
+ applicantName: row.applicantName || "",
+ employeeNo: row.applicantCode || "",
+ employeeName: row.applicantName || "",
+ applicantDeptName: row.applicantDeptName || "",
+ reimburseReason: row.reason || "",
+ travelStartTime: formatReimbursementDateTime(travel.startTime),
+ travelEndTime: formatReimbursementDateTime(travel.endTime),
+ travelDays: travel.travelDays,
+ departurePlace: travel.departureCity || "",
+ destination: travel.destinationCity || "",
+ hotelStandard: travel.hotelStandard,
+ hotelDays: travel.lodgingDays,
+ livingSubsidy: travel.mealAllowance,
+ transportSubsidy: travel.transportAllowance,
+ lodgingLimit: travel.lodgingLimit,
+ needSpecialApproval: travel.withinStandard === "0" || travel.withinStandard === 0,
+ standardTag: travel.standardTag || "",
+ applyAmount: row.applyAmount,
+ payee: row.payeeName || "",
+ payeeAccount: row.payeeAccount || "",
+ payeeBank: row.payeeBank || "",
+ billStatus: row.billStatus,
+ approvalResult: mapBillStatusToApprovalResult(row.billStatus),
+ createTime: formatReimbursementDateTime(row.createTime),
+ expenseDetails: details.map((d) => ({
+ ...d,
+ expenseSubject: d.expenseCategory,
+ })),
+ travel:
+ row.travel && typeof row.travel === "object" && Object.keys(row.travel).length
+ ? row.travel
+ : travel,
+ details,
+ nodes: resolveRowApiNodes(row),
+ approvalFlowNodes: mapNodesToFormFlow(resolveRowApiNodes(row)),
+ tasks: row.tasks || [],
+ approvalFlowSummary: buildApprovalFlowSummaryForRow(row),
+ };
+ return base;
+}
+
+/** 鎺ュ彛琛� 鈫� 璐圭敤鎶ラ攢鍒楄〃琛岋紙鍏煎 useCostReimburse 瀛楁锛� */
+export function mapCostReimbursementRow(row) {
+ if (!row) return {};
+ const details = Array.isArray(row.details) ? row.details : [];
+ const apiNodes = resolveRowApiNodes(row);
+ const approvalFlowNodes = mapNodesToFormFlow(apiNodes);
+
+ return {
+ ...row,
+ id: row.id,
+ reimbursementId: row.id,
+ approvalInstanceId: row.approvalInstanceId,
+ reimburseNo: row.billNo || "",
+ applicantId: row.applicantId,
+ applicantNo: row.applicantCode || "",
+ applicantName: row.applicantName || "",
+ employeeNo: row.applicantCode || "",
+ employeeName: row.applicantName || "",
+ applicantDeptName: row.applicantDeptName || "",
+ reimburseReason: row.reason || "",
+ expenseCategory: row.expenseType || "",
+ applyAmount: row.applyAmount,
+ applyTime: formatReimbursementDateTime(row.createTime),
+ payee: row.payeeName || "",
+ payeeAccount: row.payeeAccount || "",
+ bankBranch: row.payeeBank || "",
+ billStatus: row.billStatus,
+ approvalResult: mapBillStatusToApprovalResult(row.billStatus),
+ createTime: formatReimbursementDateTime(row.createTime),
+ expenseDetails: details.map((d) => ({
+ ...d,
+ expenseSubject: d.expenseCategory,
+ })),
+ details,
+ nodes: apiNodes,
+ approvalFlowNodes,
+ tasks: row.tasks || [],
+ approvalFlowSummary: buildApprovalFlowSummaryForRow({
+ ...row,
+ nodes: apiNodes,
+ approvalFlowNodes,
+ }),
+ };
+}
+
+function toNumber(val) {
+ if (val == null || val === "") return undefined;
+ const n = Number(val);
+ return Number.isNaN(n) ? undefined : n;
+}
+
+function expenseSubjectToCategory(subject) {
+ const hit = EXPENSE_SUBJECT_OPTIONS.find((x) => x.value === subject);
+ return hit?.label || subject || "";
+}
+
+function expenseCategoryToType(category) {
+ const hit = EXPENSE_CATEGORY_OPTIONS.find((x) => x.value === category);
+ return hit?.label || category || "";
+}
+
+/** 鍒楄〃/璇︽儏琛屼笂鐨勫鎵硅妭鐐癸紙listPage 甯镐笉杩斿洖锛岄渶璇︽儏琛ュ叏锛� */
+export function resolveRowApiNodes(row) {
+ if (!row || typeof row !== "object") return [];
+ const list =
+ row.nodes ||
+ row.flowNodes ||
+ row.approveNodes ||
+ row.finReimbursementNodes ||
+ row.nodeList ||
+ row.reimbursementNodeList ||
+ [];
+ return Array.isArray(list) ? list : [];
+}
+
+function sortFlowNodesByLevel(nodes = []) {
+ return [...(Array.isArray(nodes) ? nodes : [])].sort((a, b) => {
+ const la = Number(a?.levelNo ?? a?.nodeOrder ?? a?.sortOrder ?? 0);
+ const lb = Number(b?.levelNo ?? b?.nodeOrder ?? b?.sortOrder ?? 0);
+ return la - lb;
+ });
+}
+
+function formatApiNodeApproverLabel(node, index) {
+ if (!node || typeof node !== "object") return "";
+ const approvers = Array.isArray(node.approvers) ? node.approvers : [];
+ const names = approvers
+ .map((a) => (a?.approverName || "").trim())
+ .filter(Boolean);
+ if (names.length) return names.join("/");
+ return (node.approverName || "").trim() || `鑺傜偣${index + 1}`;
+}
+
+/** 鎺ュ彛 nodes 鈫� 椤甸潰瀹℃壒娴侊紙鍗曞鎵逛汉鑺傜偣锛� */
+export function mapNodesToFormFlow(nodes = []) {
+ return sortFlowNodesByLevel(nodes).map((n, i) => {
+ const approvers = Array.isArray(n.approvers) ? n.approvers : [];
+ const first = approvers[0] || null;
+ const names = approvers
+ .map((a) => (a?.approverName || "").trim())
+ .filter(Boolean);
+ return {
+ ...n,
+ nodeOrder: n.levelNo ?? n.nodeOrder ?? i + 1,
+ signMode: String(n.approveType || "").toUpperCase() === "OR" ? "or_sign" : "countersign",
+ approverId:
+ toNumber(first?.approverId ?? n.approverId) ??
+ first?.approverId ??
+ n.approverId ??
+ null,
+ approverName:
+ names.join("銆�") || first?.approverName || n.approverName || "",
+ nodeStatus: n.nodeStatus,
+ };
+ });
+}
+
+function formatTasksToFlowSummary(tasks = []) {
+ const list = sortFlowNodesByLevel(
+ (Array.isArray(tasks) ? tasks : []).map((t, i) => ({
+ levelNo: t.levelNo ?? t.taskLevel ?? i + 1,
+ approverName:
+ (t.approverName || t.operatorName || t.createUserName || "").trim() ||
+ "",
+ }))
+ );
+ const parts = list.map((t) => t.approverName).filter(Boolean);
+ return parts.length ? parts.join(" 鈫� ") : "";
+}
+
+function buildApprovalFlowSummaryForRow(row) {
+ const apiNodes = sortFlowNodesByLevel(resolveRowApiNodes(row));
+ let flowNodes =
+ row?.approvalFlowNodes?.length > 0
+ ? sortFlowNodesByLevel(row.approvalFlowNodes)
+ : mapNodesToFormFlow(apiNodes);
+
+ if (!flowNodes.length && apiNodes.length) {
+ const line = apiNodes
+ .map((n, i) => formatApiNodeApproverLabel(n, i))
+ .filter(Boolean)
+ .join(" 鈫� ");
+ if (line) return line;
+ }
+
+ if (!flowNodes.length) {
+ const fromTasks = formatTasksToFlowSummary(row?.tasks);
+ if (fromTasks) return fromTasks;
+ return "鈥�";
+ }
+
+ return flowNodes
+ .map((n, i) => {
+ const name = (n.approverName || "").trim() || `鑺傜偣${i + 1}`;
+ if (n.nodeStatus === "finish") return `${name}鉁揱;
+ if (n.nodeStatus === "error") return `${name}鉁梎;
+ if (n.nodeStatus === "process") return `${name}鈥;
+ return name;
+ })
+ .join(" 鈫� ");
+}
+
+/** 鍒楄〃銆屽鎵规祦绋嬨�嶅垪鏂囨 */
+export function formatApprovalFlowSummary(row) {
+ return buildApprovalFlowSummaryForRow(row);
+}
+
+/** listPage 甯镐笉甯﹀畬鏁� nodes锛屽垪琛ㄥ姞杞藉悗缁熶竴鎷夎鎯呰ˉ鍏ㄥ绾у鎵规祦绋� */
+export async function enrichReimbursementListRowsWithApprovalFlow(
+ rows,
+ reimbursementType
+) {
+ const list = Array.isArray(rows) ? rows : [];
+ if (!list.length) return list;
+
+ const needIds = list
+ .map((r) => resolveReimbursementDeleteId(r))
+ .filter((id) => id != null);
+
+ if (!needIds.length) return list;
+
+ const detailById = new Map();
+ await Promise.all(
+ needIds.map(async (id) => {
+ try {
+ const res = await getFinReimbursementDetail(id);
+ detailById.set(String(id), unwrapFinReimbursementDetail(res));
+ } catch {
+ /* 鍗曡澶辫触涓嶅奖鍝嶅垪琛� */
+ }
+ })
+ );
+
+ const mapRow =
+ reimbursementType === FIN_REIMBURSEMENT_TYPE.TRAVEL
+ ? mapTravelReimbursementRow
+ : mapCostReimbursementRow;
+
+ return list.map((row) => {
+ const id = resolveReimbursementDeleteId(row);
+ const detail = id != null ? detailById.get(String(id)) : null;
+ if (!detail) return row;
+ const merged = {
+ ...row,
+ ...detail,
+ id: row.id ?? detail.id,
+ reimbursementId: row.reimbursementId ?? row.id ?? detail.id,
+ reimbursementType: detail.reimbursementType ?? row.reimbursementType,
+ };
+ return mapRow(merged);
+ });
+}
+
+/** 琛ㄥ崟涓婄殑瀹℃壒娴侊紙鍏煎 approvalFlowNodes / nodes / flowNodes锛� */
+export function resolveFormApprovalFlowNodes(form) {
+ const list =
+ form?.approvalFlowNodes ?? form?.nodes ?? form?.flowNodes ?? [];
+ return Array.isArray(list) ? list : [];
+}
+
+/** 椤甸潰瀹℃壒鑺傜偣 鈫� 鎺ュ彛 nodes */
+export function mapApprovalFlowNodesToApi(nodes = [], templateId) {
+ const list = Array.isArray(nodes) ? nodes : [];
+ return list
+ .map((n, i) => {
+ let approvers = [];
+ if (Array.isArray(n.approvers) && n.approvers.length) {
+ approvers = n.approvers
+ .filter((a) => a?.approverId != null && a.approverId !== "")
+ .map((a, idx) => {
+ const item = {
+ approverId: toNumber(a.approverId) ?? a.approverId,
+ approverName: a.approverName || "",
+ sortNo: a.sortNo ?? idx + 1,
+ };
+ if (a.id != null) item.id = a.id;
+ if (a.nodeId != null) item.nodeId = a.nodeId;
+ if (a.templateId != null) item.templateId = a.templateId;
+ else if (templateId != null) item.templateId = templateId;
+ if (a.roleKey) item.roleKey = a.roleKey;
+ return item;
+ });
+ } else if (n.approverId != null && n.approverId !== "") {
+ const item = {
+ approverId: toNumber(n.approverId) ?? n.approverId,
+ approverName: n.approverName || "",
+ sortNo: 1,
+ };
+ if (n.roleKey) item.roleKey = n.roleKey;
+ approvers = [item];
+ }
+ if (!approvers.length) return null;
+
+ const node = {
+ levelNo: n.levelNo ?? n.nodeOrder ?? n.sortOrder ?? i + 1,
+ approveType: n.approveType || mapSignModeToApi(n.signMode),
+ approvers,
+ };
+ if (n.id != null) node.id = n.id;
+ if (n.templateId != null) node.templateId = n.templateId;
+ else if (templateId != null) node.templateId = templateId;
+ if (n.roleKey) node.roleKey = n.roleKey;
+ return node;
+ })
+ .filter(Boolean);
+}
+
+/** 淇濆瓨鍓嶆牎楠� nodes 宸查厤缃� */
+export function validateReimbursementApprovalNodes(dto) {
+ if (Array.isArray(dto?.nodes) && dto.nodes.length > 0) {
+ return { ok: true };
+ }
+ return { ok: false, message: "璇烽厤缃鎵规祦绋嬪苟閫夋嫨瀹℃壒浜�" };
+}
+
+function mapDetailsToApi(details = []) {
+ return (details || []).map((d, i) => {
+ const item = {
+ rowNo: d.rowNo ?? i + 1,
+ invoiceDate: d.invoiceDate || undefined,
+ expenseCategory: expenseSubjectToCategory(d.expenseSubject ?? d.expenseCategory),
+ amount: toNumber(d.amount),
+ description: d.description || "",
+ invoiceNo: d.invoiceNo || undefined,
+ invoiceType: d.invoiceType || undefined,
+ invoiceAmount: toNumber(d.invoiceAmount),
+ taxRate: toNumber(d.taxRate),
+ taxAmount: toNumber(d.taxAmount),
+ remark: d.remark || undefined,
+ };
+ if (d.id != null && !String(d.id).startsWith("ed_")) {
+ item.id = toNumber(d.id) ?? d.id;
+ }
+ if (d.reimbursementId != null) item.reimbursementId = toNumber(d.reimbursementId);
+ return item;
+ });
+}
+
+function sumDetailAmount(details = []) {
+ const sum = (details || []).reduce((s, d) => s + (Number(d.amount) || 0), 0);
+ return Math.round(sum * 100) / 100;
+}
+
+/** 琛ㄥ崟闄勪欢鍒楄〃锛堝吋瀹瑰绉嶅瓧娈靛悕锛� */
+export function resolveFormAttachmentList(form) {
+ const list =
+ form?.attachmentList ??
+ form?.storageBlobDTOs ??
+ form?.storageBlobVOList ??
+ form?.invoiceAttachments ??
+ [];
+ return Array.isArray(list) ? list : [];
+}
+
+/** 椤甸潰闄勪欢 鈫� 淇濆瓨 DTO锛坰torageBlobVOList / storageBlobDTOs锛� */
+export function mapFormAttachmentsToApi(list = [], reimbursementId) {
+ const rid =
+ reimbursementId != null
+ ? toNumber(reimbursementId) ?? reimbursementId
+ : undefined;
+
+ return (list || [])
+ .map((item, i) => {
+ if (!item) return null;
+ const url =
+ item.url ||
+ item.fileUrl ||
+ item.downloadUrl ||
+ item.downloadURL ||
+ item.previewUrl ||
+ item.previewURL ||
+ item.link ||
+ "";
+ const name =
+ item.fileName ||
+ item.originalFilename ||
+ item.originalFileName ||
+ item.blobName ||
+ item.name ||
+ `闄勪欢${i + 1}`;
+
+ const idRaw = item.id ?? item.blobId;
+ const isTempId =
+ idRaw != null &&
+ /^(inv_|att_|ed_|local_)/.test(String(idRaw));
+
+ if (!url && (idRaw == null || isTempId)) return null;
+
+ const blob = {
+ fileName: name,
+ originalFilename: name,
+ fileUrl: url || undefined,
+ url: url || undefined,
+ };
+
+ if (idRaw != null && !isTempId) {
+ const n = toNumber(idRaw);
+ blob.id = n != null ? n : idRaw;
+ blob.blobId = blob.id;
+ }
+ if (rid != null) blob.reimbursementId = rid;
+ return blob;
+ })
+ .filter(Boolean);
+}
+
+function applyStorageBlobsToSaveDto(dto, form) {
+ const blobs = mapFormAttachmentsToApi(
+ resolveFormAttachmentList(form),
+ dto?.id ?? form?.reimbursementId ?? form?.id
+ );
+ if (blobs.length) {
+ dto.storageBlobVOList = blobs;
+ dto.storageBlobDTOs = blobs;
+ }
+ return dto;
+}
+
+/** 淇敼鏃惰ˉ榻愪富琛ㄤ笌瀛愯〃鍏宠仈 ID */
+function applyReimbursementRelations(dto) {
+ const rid = dto?.id;
+ if (rid == null) return dto;
+ if (dto.travel && typeof dto.travel === "object") {
+ dto.travel.reimbursementId = rid;
+ }
+ if (Array.isArray(dto.details)) {
+ dto.details.forEach((d) => {
+ d.reimbursementId = rid;
+ });
+ }
+ const blobLists = [dto.storageBlobVOList, dto.storageBlobDTOs].filter(Array.isArray);
+ blobLists.forEach((list) => {
+ list.forEach((b) => {
+ b.reimbursementId = rid;
+ });
+ });
+ return dto;
+}
+
+function resolveReimbursementId(form) {
+ const rawId = form?.reimbursementId ?? form?.id;
+ if (rawId == null || rawId === "" || String(rawId).startsWith("local_")) {
+ return undefined;
+ }
+ return toNumber(rawId) ?? rawId;
+}
+
+/** 宸梾琛ㄥ崟 鈫� FinReimbursementDto */
+export function buildTravelReimbursementSaveDto(form, { computeTravelDays } = {}) {
+ const details = mapDetailsToApi(form.expenseDetails);
+ const detailTotal = sumDetailAmount(form.expenseDetails);
+ const applyAmount = toNumber(form.applyAmount) ?? detailTotal;
+ const travelDays =
+ form.travelDays != null
+ ? toNumber(form.travelDays)
+ : computeTravelDays?.(form.travelStartTime, form.travelEndTime);
+
+ const dto = {
+ reimbursementType: FIN_REIMBURSEMENT_TYPE.TRAVEL,
+ expenseType: "宸梾璐�",
+ applicantId: toNumber(form.applicantId),
+ applicantCode: form.employeeNo || form.applicantNo || "",
+ applicantName: form.employeeName || form.applicantName || "",
+ applicantDeptId: toNumber(form.applicantDeptId),
+ applicantDeptName: form.applicantDeptName || form.deptName || "",
+ reason: (form.reimburseReason || "").trim(),
+ applyAmount,
+ detailTotalAmount: detailTotal,
+ payeeName: form.payee || "",
+ payeeAccount: form.payeeAccount || undefined,
+ payeeBank: form.payeeBank || undefined,
+ billStatus: "IN_APPROVAL",
+ deptId: toNumber(form.deptId),
+ travel: {
+ startTime: form.travelStartTime || undefined,
+ endTime: form.travelEndTime || undefined,
+ travelDays,
+ departureCity: form.departurePlace || "",
+ destinationCity: form.destination || "",
+ hotelStandard: toNumber(form.hotelStandard),
+ lodgingDays: toNumber(form.hotelDays),
+ mealAllowance: toNumber(form.livingSubsidy),
+ transportAllowance: toNumber(form.transportSubsidy),
+ lodgingLimit: toNumber(form.lodgingLimit),
+ standardTag: form.standardTag || (form.needSpecialApproval ? "瓒呮爣鐗规壒" : "鍦ㄦ爣鍑嗚寖鍥村唴"),
+ withinStandard: form.needSpecialApproval ? "0" : "1",
+ },
+ details,
+ nodes: mapApprovalFlowNodesToApi(
+ resolveFormApprovalFlowNodes(form),
+ form.templateId
+ ),
+ };
+
+ const id = resolveReimbursementId(form);
+ if (id != null) dto.id = id;
+ if (form.billNo || form.reimburseNo) {
+ dto.billNo = form.billNo || form.reimburseNo;
+ }
+ if (form.approvalInstanceId != null) {
+ dto.approvalInstanceId = toNumber(form.approvalInstanceId);
+ }
+ if (form.approveProcessId != null) {
+ dto.approveProcessId = toNumber(form.approveProcessId);
+ }
+ if (form.travel?.id != null) dto.travel.id = toNumber(form.travel.id);
+
+ applyStorageBlobsToSaveDto(dto, form);
+ return applyReimbursementRelations(dto);
+}
+
+/** 璐圭敤琛ㄥ崟 鈫� FinReimbursementDto */
+export function buildCostReimbursementSaveDto(form) {
+ const details = mapDetailsToApi(form.expenseDetails);
+ const detailTotal = sumDetailAmount(form.expenseDetails);
+ const applyAmount = toNumber(form.applyAmount) ?? detailTotal;
+
+ const dto = {
+ reimbursementType: FIN_REIMBURSEMENT_TYPE.COST,
+ expenseType: expenseCategoryToType(form.expenseCategory),
+ applicantId: toNumber(form.applicantId),
+ applicantCode: form.employeeNo || form.applicantNo || "",
+ applicantName: form.employeeName || form.applicantName || "",
+ applicantDeptId: toNumber(form.applicantDeptId),
+ applicantDeptName: form.applicantDeptName || form.deptName || "",
+ reason: (form.reimburseReason || "").trim(),
+ applyAmount,
+ detailTotalAmount: detailTotal,
+ payeeName: form.payee || "",
+ payeeAccount: form.payeeAccount || "",
+ payeeBank: form.bankBranch || form.payeeBank || "",
+ billStatus: "IN_APPROVAL",
+ deptId: toNumber(form.deptId),
+ details,
+ nodes: mapApprovalFlowNodesToApi(
+ resolveFormApprovalFlowNodes(form),
+ form.templateId
+ ),
+ };
+
+ const id = resolveReimbursementId(form);
+ if (id != null) dto.id = id;
+ if (form.billNo || form.reimburseNo) {
+ dto.billNo = form.billNo || form.reimburseNo;
+ }
+ if (form.approvalInstanceId != null) {
+ dto.approvalInstanceId = toNumber(form.approvalInstanceId);
+ }
+ if (form.approveProcessId != null) {
+ dto.approveProcessId = toNumber(form.approveProcessId);
+ }
+
+ applyStorageBlobsToSaveDto(dto, form);
+ return applyReimbursementRelations(dto);
+}
+
+/** 鍒楄〃琛屼富閿紙鍒犻櫎/淇敼鐢� fin_reimbursement.id锛� */
+export function resolveReimbursementDeleteId(row) {
+ const raw = row?.reimbursementId ?? row?.id;
+ if (raw == null || raw === "" || String(raw).startsWith("local_")) {
+ return undefined;
+ }
+ const n = toNumber(raw);
+ return n != null ? n : raw;
+}
+
+/** 鏄惁鍏佽鍒犻櫎锛堝鎵逛腑銆佸凡閫氳繃銆佸凡浠樻涓嶅彲鍒狅級 */
+export function canDeleteReimbursementRow(row) {
+ const key = mapBillStatusToApprovalResult(
+ row?.billStatus ?? row?.approvalResult ?? row?.status
+ );
+ return key !== "pending" && key !== "approved" && key !== "paid";
+}
+
+/** 鏄惁鍏佽缂栬緫锛堜笌鍒犻櫎瑙勫垯涓�鑷达級 */
+export function canEditReimbursementRow(row) {
+ return canDeleteReimbursementRow(row);
+}
+
+/** 淇敼鍦烘櫙蹇呴』甯︿富閿� ID */
+export function validateReimbursementPersistDto(dto, isEdit) {
+ if (!isEdit) return { ok: true };
+ if (dto?.id != null && dto.id !== "") return { ok: true };
+ return { ok: false, message: "鏃犳硶淇敼锛氱己灏戞姤閿�鍗� ID" };
+}
diff --git a/src/views/officeProcessAutomation/ReimburseManage/shared/reimburseApproveBridge.js b/src/views/officeProcessAutomation/ReimburseManage/shared/reimburseApproveBridge.js
new file mode 100644
index 0000000..664d646
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/shared/reimburseApproveBridge.js
@@ -0,0 +1,124 @@
+import { getFinReimbursementDetail } from "@/api/officeProcessAutomation/finReimbursement.js";
+import { matchBusinessTypeValue } from "../../ApproveManage/approve-list/approveListConstants.js";
+import {
+ APPROVAL_MODULE_KEYS,
+ getApprovalModuleConfig,
+} from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import {
+ getModuleKeyByReimbursementType,
+ mapFinReimbursementDetailRow,
+ resolveReimbursementType,
+ unwrapFinReimbursementDetail,
+} from "./finReimbursementMappers.js";
+
+export const REIMBURSE_EDIT_FROM_APPROVE_KEY = "oa_reimburse_edit_from_approve";
+
+const REIMBURSE_MODULE_KEYS = [
+ APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE,
+ APPROVAL_MODULE_KEYS.COST_REIMBURSE,
+];
+
+/** 瀹℃壒瀹炰緥鏄惁宸梾/璐圭敤鎶ラ攢 */
+export function inferReimburseModuleKeyFromInstance(row) {
+ if (!row) return "";
+ for (const moduleKey of REIMBURSE_MODULE_KEYS) {
+ const cfg = getApprovalModuleConfig(moduleKey);
+ if (!cfg) continue;
+ if (
+ cfg.businessType != null &&
+ cfg.businessType !== "" &&
+ matchBusinessTypeValue(row.businessType, cfg.businessType)
+ ) {
+ return moduleKey;
+ }
+ if (matchBusinessTypeValue(row.businessType, cfg.approvalType)) {
+ return moduleKey;
+ }
+ const text = `${row.templateName || ""}${row.title || ""}${row.businessName || ""}`;
+ if ((cfg.typeLabels || []).some((l) => l && text.includes(l))) {
+ return moduleKey;
+ }
+ }
+ return "";
+}
+
+export function isReimburseApprovalInstance(row) {
+ return Boolean(inferReimburseModuleKeyFromInstance(row));
+}
+
+/** 瀹℃壒瀹炰緥鍏宠仈鐨� fin_reimbursement.id */
+export function resolveFinReimbursementIdFromInstance(row) {
+ const raw = row?.businessId ?? row?.formPayload?.reimbursementId;
+ if (raw == null || raw === "") return undefined;
+ const n = Number(raw);
+ return Number.isNaN(n) ? raw : n;
+}
+
+/** 鎷夊彇鎶ラ攢璇︽儏骞舵槧灏勪负宸梾/璐圭敤椤甸潰琛岋紙浠ユ帴鍙� reimbursementType 涓哄噯锛� */
+export async function loadReimburseDetailForInstance(instanceRow, moduleKey) {
+ const mk = moduleKey || inferReimburseModuleKeyFromInstance(instanceRow);
+ const id = resolveFinReimbursementIdFromInstance(instanceRow);
+ if (id == null) {
+ throw new Error("missing reimbursement id");
+ }
+ const res = await getFinReimbursementDetail(id);
+ const raw = unwrapFinReimbursementDetail(res);
+ const reimburseRow = mapFinReimbursementDetailRow(raw, mk);
+ const reimbursementType = resolveReimbursementType(raw, mk);
+ const resolvedMk =
+ getModuleKeyByReimbursementType(reimbursementType) || mk;
+ return {
+ reimburseRow,
+ instanceRow,
+ moduleKey: resolvedMk,
+ reimbursementType,
+ };
+}
+
+export function stashReimburseEditFromApprove(moduleKey, reimbursementId) {
+ sessionStorage.setItem(
+ REIMBURSE_EDIT_FROM_APPROVE_KEY,
+ JSON.stringify({ moduleKey, reimbursementId })
+ );
+}
+
+export function consumeReimburseEditFromApprove() {
+ const raw = sessionStorage.getItem(REIMBURSE_EDIT_FROM_APPROVE_KEY);
+ if (!raw) return null;
+ sessionStorage.removeItem(REIMBURSE_EDIT_FROM_APPROVE_KEY);
+ try {
+ return JSON.parse(raw);
+ } catch {
+ return null;
+ }
+}
+
+/** 浠庡凡娉ㄥ唽璺敱瑙f瀽宸梾/璐圭敤鎶ラ攢鑿滃崟 path锛堥伩鍏嶅啓姝� path 瀵艰嚧 404锛� */
+export function resolveReimburseManageRoutePath(router, moduleKey) {
+ if (!router?.getRoutes) return "";
+ const needle =
+ moduleKey === APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE
+ ? "travel-reimburse"
+ : moduleKey === APPROVAL_MODULE_KEYS.COST_REIMBURSE
+ ? "cost-reimburse"
+ : "";
+ if (!needle) return "";
+ const labelHint =
+ moduleKey === APPROVAL_MODULE_KEYS.TRAVEL_REIMBURSE ? "宸梾" : "璐圭敤";
+ const hit = router.getRoutes().find((r) => {
+ const path = r.path || "";
+ if (path.includes(needle)) return true;
+ const title = r.meta?.title || "";
+ return title.includes(labelHint) && title.includes("鎶ラ攢");
+ });
+ return hit?.path || "";
+}
+
+export async function navigateToReimburseManageForEdit(router, moduleKey, reimbursementId) {
+ stashReimburseEditFromApprove(moduleKey, reimbursementId);
+ const path = resolveReimburseManageRoutePath(router, moduleKey);
+ if (!path) {
+ throw new Error("route not found");
+ }
+ await router.push(path);
+}
diff --git a/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/ApprovalFlowProgress.vue b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/ApprovalFlowProgress.vue
new file mode 100644
index 0000000..03a5fa3
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/ApprovalFlowProgress.vue
@@ -0,0 +1,49 @@
+<!-- 宸梾鎶ラ攢锛氬鎵规祦绋嬭繘搴﹀睍绀� -->
+<template>
+ <el-steps :active="activeStep" finish-status="success" align-center>
+ <el-step
+ v-for="(node, index) in sortedNodes"
+ :key="index"
+ :title="`鑺傜偣 ${index + 1}`"
+ :description="stepDescription(node)"
+ :status="stepStatus(node, index)"
+ />
+ </el-steps>
+</template>
+
+<script setup>
+import { computed } from "vue";
+
+const props = defineProps({
+ nodes: { type: Array, default: () => [] },
+ currentIndex: { type: Number, default: 0 },
+});
+
+const sortedNodes = computed(() => {
+ const list = props.nodes || [];
+ return [...list].sort((a, b) => (a.sortOrder ?? a.nodeOrder ?? 0) - (b.sortOrder ?? b.nodeOrder ?? 0));
+});
+
+const activeStep = computed(() => {
+ const list = sortedNodes.value;
+ if (!list.length) return 0;
+ const finished = list.filter((n) => n.nodeStatus === "finish").length;
+ const hasError = list.some((n) => n.nodeStatus === "error");
+ if (hasError) return Math.max(0, props.currentIndex);
+ return finished;
+});
+
+function stepDescription(node) {
+ const name = (node.approverName || "").trim() || "鏈寚瀹�";
+ const opinion = (node.approveOpinion || "").trim();
+ if (opinion) return `${name}锛�${opinion}`;
+ return name;
+}
+
+function stepStatus(node, index) {
+ if (node.nodeStatus === "error") return "error";
+ if (node.nodeStatus === "finish") return "success";
+ if (node.nodeStatus === "process" || index === props.currentIndex) return "process";
+ return "wait";
+}
+</script>
diff --git a/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/DetailPanel.vue b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/DetailPanel.vue
new file mode 100644
index 0000000..2c1d8a4
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/components/DetailPanel.vue
@@ -0,0 +1,82 @@
+<!-- 宸梾鎶ラ攢锛氳鎯呭彧璇婚潰鏉� -->
+<template>
+ <el-descriptions :column="2" border>
+ <el-descriptions-item label="鎶ラ攢鍗曞彿">{{ row.reimburseNo || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐘舵��">
+ <el-tag :type="statusTagType(row.approvalResult)" size="small">{{ statusLabel(row.approvalResult) }}</el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item label="鍛樺伐缂栧彿">{{ row.employeeNo || row.applicantNo || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鍛樺伐濮撳悕">{{ row.employeeName || row.applicantName || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鎶ラ攢鍘熷洜" :span="2">{{ row.reimburseReason || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鍑哄樊寮�濮�">{{ row.travelStartTime || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鍑哄樊缁撴潫">{{ row.travelEndTime || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鍑哄樊鍦�">{{ row.departurePlace || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐩殑鍦�">{{ row.destination || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="閰掑簵鏍囧噯">{{ row.hotelStandard != null ? `${row.hotelStandard} 鍏�/鏅歚 : "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="浣忓澶╂暟">{{ row.hotelDays ?? "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐢熸椿琛ヨ创">{{ row.livingSubsidy != null ? `${row.livingSubsidy} 鍏僠 : "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐢宠閲戦">{{ row.applyAmount != null ? `${row.applyAmount} 鍏僠 : "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鏀舵浜�">{{ row.payee || "鈥�" }}</el-descriptions-item>
+ <el-descriptions-item label="鐗规壒">
+ <el-tag :type="row.needSpecialApproval ? 'danger' : 'info'" size="small">
+ {{ row.needSpecialApproval ? "瓒呮敮闇�鐗规壒" : "鏍囧噯鍐�" }}
+ </el-tag>
+ </el-descriptions-item>
+ <el-descriptions-item v-if="row.rejectReason" label="椹冲洖鍘熷洜" :span="2">
+ <span class="reject-text">{{ row.rejectReason }}</span>
+ </el-descriptions-item>
+ <el-descriptions-item label="鍒涘缓鏃堕棿" :span="2">{{ row.createTime || "鈥�" }}</el-descriptions-item>
+ </el-descriptions>
+
+ <el-divider content-position="left">鎶ラ攢鏄庣粏</el-divider>
+ <el-table v-if="row.expenseDetails?.length" :data="row.expenseDetails" border size="small">
+ <el-table-column type="index" label="搴忓彿" width="55" align="center" />
+ <el-table-column prop="invoiceDate" label="鍙戠エ鏃ユ湡" width="120" />
+ <el-table-column label="璐圭敤绉戠洰" width="100">
+ <template #default="{ row: d }">{{ expenseSubjectLabel(d.expenseSubject) }}</template>
+ </el-table-column>
+ <el-table-column prop="amount" label="閲戦" width="100" />
+ <el-table-column prop="description" label="鎻忚堪" min-width="140" show-overflow-tooltip />
+ </el-table>
+ <el-empty v-else description="鏆傛棤鏄庣粏" :image-size="48" />
+
+ <el-divider content-position="left">鍙戠エ闄勪欢</el-divider>
+ <template v-if="attachmentFiles.length">
+ <el-tag v-for="(f, i) in attachmentFiles" :key="i" class="file-tag" type="info" @click="openFile(f)">
+ {{ f.name }}
+ </el-tag>
+ </template>
+ <el-empty v-else description="鏆傛棤闄勪欢" :image-size="48" />
+</template>
+
+<script setup>
+import { computed } from "vue";
+import { expenseSubjectLabel, statusLabel, statusTagType } from "../travelReimburseUtils.js";
+
+const props = defineProps({
+ row: { type: Object, default: () => ({}) },
+});
+
+const attachmentFiles = computed(() => {
+ const list =
+ props.row?.attachmentList ||
+ props.row?.storageBlobVOList ||
+ props.row?.invoiceAttachments;
+ return Array.isArray(list) ? list : [];
+});
+
+function openFile(f) {
+ const url = f?.url || f?.downloadURL || f?.previewURL;
+ if (url) window.open(url, "_blank");
+}
+</script>
+
+<style scoped>
+.reject-text {
+ color: var(--el-color-danger);
+}
+.file-tag {
+ margin: 0 8px 8px 0;
+ cursor: pointer;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/index.vue b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/index.vue
new file mode 100644
index 0000000..17737e3
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/index.vue
@@ -0,0 +1,614 @@
+<!--OA妯″潡锛氬樊鏃呮姤閿�锛堝垪琛� /finReimbursement/listPage锛宺eimbursementType=1锛�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">鐢宠浜猴細</span>
+ <el-input
+ v-model="searchForm.applicantKeyword"
+ style="width: 220px"
+ placeholder="濮撳悕鎴栫紪鍙�"
+ clearable
+ :prefix-icon="Search"
+ @keyup.enter="handleQuery"
+ />
+ <el-button type="primary" style="margin-left: 10px" @click="handleQuery">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div class="search_actions">
+ <el-button type="success" plain @click="handleImportClick">瀵煎叆</el-button>
+ <el-button type="warning" plain @click="handleExport">瀵煎嚭</el-button>
+ <el-button type="primary" @click="openFormDialog('add')">鏂板宸梾鎶ラ攢</el-button>
+ </div>
+ </div>
+
+ <input ref="importInputRef" type="file" accept="application/json,.json" class="sr-only-input" @change="onImportFile" />
+
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ :total="page.total"
+ @pagination="pagination"
+ />
+ </div>
+
+ <!-- 鏂板 / 缂栬緫 -->
+ <el-dialog
+ v-model="formDialog.visible"
+ :title="formDialog.title"
+ width="1120px"
+ append-to-body
+ destroy-on-close
+ class="travel-reimburse-form-dialog"
+ @closed="onFormClosed"
+ >
+ <el-alert
+ v-if="budgetHint.visible"
+ :title="budgetHint.title"
+ :type="budgetHint.type"
+ :description="budgetHint.description"
+ show-icon
+ :closable="false"
+ class="mb16"
+ />
+ <el-alert v-if="overBudgetWarnings.length" type="warning" show-icon :closable="false" class="mb16">
+ <template #title>宸梾鏍囧噯瓒呮敮鎻愰啋锛堥渶鐗规壒锛�</template>
+ <ul class="warn-list">
+ <li v-for="(w, i) in overBudgetWarnings" :key="i">{{ w }}</li>
+ </ul>
+ </el-alert>
+
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="formRules"
+ label-width="120px"
+ class="travel-reimburse-form"
+ :disabled="formDialog.readonly"
+ >
+ <el-card class="form-section" shadow="never">
+ <template #header><span class="card-header-title">鍩烘湰淇℃伅</span></template>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍛樺伐缂栧彿">
+ <el-input v-model="form.employeeNo" readonly placeholder="閫夋嫨鍛樺伐鍚庤嚜鍔ㄥ甫鍑�" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍛樺伐濮撳悕" prop="applicantId">
+ <el-select
+ v-model="form.applicantId"
+ filterable
+ remote
+ clearable
+ reserve-keyword
+ placeholder="璇烽�夋嫨鎴栨悳绱㈠憳宸�"
+ style="width: 100%"
+ :remote-method="remoteSearchApplicantForm"
+ :loading="applicantFormSearchLoading"
+ @change="onApplicantChange"
+ >
+ <el-option
+ v-for="u in applicantFormOptions"
+ :key="u.userId"
+ :label="userSelectLabel(u)"
+ :value="u.userId"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="24">
+ <el-form-item label="鎶ラ攢鍘熷洜" prop="reimburseReason">
+ <el-input
+ v-model="form.reimburseReason"
+ type="textarea"
+ :rows="3"
+ placeholder="璇峰~鍐欏嚭宸強鎶ラ攢鍘熷洜"
+ maxlength="2000"
+ show-word-limit
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍑哄樊寮�濮�" prop="travelStartTime">
+ <el-date-picker
+ v-model="form.travelStartTime"
+ type="datetime"
+ placeholder="寮�濮嬫椂闂�"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ style="width: 100%"
+ @change="onTravelRangeChange"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍑哄樊缁撴潫" prop="travelEndTime">
+ <el-date-picker
+ v-model="form.travelEndTime"
+ type="datetime"
+ placeholder="缁撴潫鏃堕棿"
+ format="YYYY-MM-DD HH:mm:ss"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ style="width: 100%"
+ @change="onTravelRangeChange"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <el-form-item label="鍑哄樊澶╂暟">
+ <el-input :model-value="travelDaysDisplay" readonly>
+ <template #append>澶�</template>
+ </el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鍑哄樊鍦�" prop="departurePlace">
+ <el-input v-model="form.departurePlace" placeholder="鍑哄彂鍩庡競" @blur="recalcTravelStandards" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鐩殑鍦�" prop="destination">
+ <el-input v-model="form.destination" placeholder="鐩殑鍩庡競" @blur="recalcTravelStandards" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header>
+ <div class="card-header-row">
+ <span class="card-header-title">宸梾鏍囧噯</span>
+ <el-text type="info" size="small">{{ travelTierLabel }} 路 鐢熸椿琛ヨ创寤鸿 {{ suggestedLivingSubsidy }} 鍏�</el-text>
+ </div>
+ </template>
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <el-form-item label="閰掑簵鏍囧噯">
+ <el-input-number
+ v-model="form.hotelStandard"
+ :min="0"
+ :precision="2"
+ controls-position="right"
+ style="width: 100%"
+ @change="recalcTravelStandards"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="浣忓澶╂暟">
+ <el-input-number
+ v-model="form.hotelDays"
+ :min="0"
+ :max="365"
+ :precision="0"
+ controls-position="right"
+ style="width: 100%"
+ @change="recalcTravelStandards"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鐢熸椿琛ヨ创">
+ <el-input-number
+ v-model="form.livingSubsidy"
+ :min="0"
+ :precision="2"
+ controls-position="right"
+ style="width: 100%"
+ @change="recalcTravelStandards"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <el-form-item label="浜ら�氳ˉ璐�">
+ <el-input :model-value="String(suggestedTransportSubsidy)" readonly><template #append>鍏�</template></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="浣忓闄愰">
+ <el-input :model-value="String(suggestedHotelLimit)" readonly><template #append>鍏�</template></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鐗规壒鏍囪">
+ <el-tag :type="form.needSpecialApproval ? 'danger' : 'success'" effect="plain">
+ {{ form.needSpecialApproval ? "瓒呮敮闇�鐗规壒" : "鍦ㄦ爣鍑嗚寖鍥村唴" }}
+ </el-tag>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header><span class="card-header-title">閲戦涓庢敹娆�</span></template>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鐢宠閲戦" prop="applyAmount">
+ <div class="amount-row">
+ <el-input-number v-model="form.applyAmount" :min="0" :precision="2" controls-position="right" class="amount-input" />
+ <el-button v-if="!formDialog.readonly" type="primary" link @click="syncApplyAmountFromDetails">
+ 鎸夋槑缁嗘眹鎬� {{ detailTotalAmount }} 鍏�
+ </el-button>
+ </div>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏀舵浜�" prop="payee">
+ <el-input v-model="form.payee" placeholder="璇疯緭鍏ユ敹娆句汉" maxlength="50" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header>
+ <div class="card-header-row">
+ <span class="card-header-title">鎶ラ攢鏄庣粏</span>
+ <el-button v-if="!formDialog.readonly" type="primary" plain size="small" @click="addExpenseDetail">鏂板鏄庣粏</el-button>
+ </div>
+ </template>
+
+ <el-table :data="form.expenseDetails" border size="small" class="detail-table">
+ <el-table-column type="index" label="搴忓彿" width="55" align="center" />
+ <el-table-column label="鍙戠エ鏃ユ湡" width="150">
+ <template #default="{ row }">
+ <el-date-picker
+ v-if="!formDialog.readonly"
+ v-model="row.invoiceDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ size="small"
+ style="width: 100%"
+ />
+ <span v-else>{{ row.invoiceDate || "鈥�" }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="璐圭敤绉戠洰" width="130">
+ <template #default="{ row }">
+ <el-select
+ v-if="!formDialog.readonly"
+ v-model="row.expenseSubject"
+ size="small"
+ style="width: 100%"
+ @change="recalcTravelStandards"
+ >
+ <el-option
+ v-for="opt in EXPENSE_SUBJECT_OPTIONS"
+ :key="opt.value"
+ :label="opt.label"
+ :value="opt.value"
+ />
+ </el-select>
+ <span v-else>{{ expenseSubjectLabel(row.expenseSubject) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="閲戦" width="120">
+ <template #default="{ row }">
+ <el-input-number
+ v-if="!formDialog.readonly"
+ v-model="row.amount"
+ :min="0"
+ :precision="2"
+ size="small"
+ controls-position="right"
+ style="width: 100%"
+ @change="onDetailAmountChange"
+ />
+ <span v-else>{{ row.amount ?? "鈥�" }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎻忚堪" min-width="140">
+ <template #default="{ row }">
+ <el-input v-if="!formDialog.readonly" v-model="row.description" size="small" placeholder="璇存槑" />
+ <span v-else>{{ row.description || "鈥�" }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column v-if="!formDialog.readonly" label="鎿嶄綔" width="70" align="center">
+ <template #default="{ $index }">
+ <el-button type="danger" link size="small" @click="removeExpenseDetail($index)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header><span class="card-header-title">闄勪欢锛堝彂绁級</span></template>
+ <el-form-item label-width="0" class="attachment-form-item">
+ <div class="upload-block">
+ <FileUpload v-model:file-list="form.attachmentList" :limit="20" button-text="鐐瑰嚮閫夋嫨鏂囦欢" />
+ </div>
+ </el-form-item>
+ </el-card>
+
+ <el-card class="form-section" shadow="never">
+ <template #header><span class="card-header-title">瀹℃壒娴佺▼</span></template>
+ <el-form-item prop="approvalFlowNodes" label-width="0">
+ <ApprovalFlowEditor
+ v-if="!formDialog.readonly"
+ v-model="form.approvalFlowNodes"
+ :user-options="flowUserOptions"
+ @update:model-value="onApprovalFlowChange"
+ />
+ <ApprovalFlowProgress v-else :nodes="form.approvalFlowNodes" :current-index="form.currentNodeIndex" />
+ <p v-if="!formDialog.readonly" class="flow-tip">鑷冲皯淇濈暀涓�涓妭鐐癸紱瀹℃牳涓�佸凡閫氳繃鐨勫崟鎹笉鍙紪杈戙��</p>
+ </el-form-item>
+ </el-card>
+ </el-form>
+ <template #footer>
+ <el-button
+ v-if="!formDialog.readonly"
+ type="primary"
+ :loading="submitSaving"
+ @click="submitForm"
+ >
+ 鎻� 浜�
+ </el-button>
+ <el-button @click="formDialog.visible = false">{{ formDialog.readonly ? "鍏� 闂�" : "鍙� 娑�" }}</el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 璇︽儏 -->
+ <el-dialog v-model="detailDialog.visible" title="宸梾鎶ラ攢璇︽儏" width="900px" append-to-body destroy-on-close>
+ <div v-loading="detailLoading">
+ <DetailPanel :row="detailRow" />
+ <ApprovalFlowProgress
+ class="mt16"
+ :nodes="detailRow.approvalFlowProgressNodes ?? detailRow.approvalFlowNodes"
+ :current-index="detailRow.currentNodeIndex ?? 0"
+ />
+ <el-divider content-position="left">瀹℃壒璁板綍锛堝叏娴佺▼鐣欑棔锛�</el-divider>
+ <el-timeline v-if="detailRow.approvalRecords?.length">
+ <el-timeline-item
+ v-for="(rec, i) in detailRow.approvalRecords"
+ :key="i"
+ :type="rec.result === 'approved' ? 'success' : rec.result === 'rejected' ? 'danger' : 'primary'"
+ :timestamp="rec.time"
+ >
+ {{ rec.operatorName }} 鈥� {{ approvalActionLabel(rec.result) }}锛歿{ rec.opinion || "鏃犳剰瑙�" }}
+ </el-timeline-item>
+ </el-timeline>
+ <el-empty v-else description="鏆傛棤瀹℃壒璁板綍" :image-size="60" />
+ </div>
+ <template #footer>
+ <el-button type="primary" @click="detailDialog.visible = false">鍏� 闂�</el-button>
+ </template>
+ </el-dialog>
+
+ <!-- 瀹℃壒 -->
+ <el-dialog
+ v-model="approveDialog.visible"
+ title="宸梾鎶ラ攢瀹℃壒"
+ width="1000px"
+ append-to-body
+ destroy-on-close
+ @closed="approveOpinion = ''"
+ >
+ <DetailPanel :row="approveDialog.row" />
+ <el-divider content-position="left">娴佺▼杩涘害</el-divider>
+ <ApprovalFlowProgress
+ :nodes="approveDialog.row?.approvalFlowProgressNodes ?? approveDialog.row?.approvalFlowNodes"
+ :current-index="approveDialog.row?.currentNodeIndex ?? 0"
+ />
+ <el-form label-width="100px" class="mt16">
+ <el-form-item label="瀹℃壒鎰忚">
+ <el-input
+ v-model="approveOpinion"
+ type="textarea"
+ :rows="3"
+ maxlength="500"
+ show-word-limit
+ placeholder="閫氳繃鍙暀绌猴紱椹冲洖璇峰~鍐欏師鍥�"
+ />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button type="success" @click="submitApprove('approved')">閫� 杩�</el-button>
+ <el-button type="danger" @click="submitApprove('rejected')">椹� 鍥�</el-button>
+ <el-button @click="approveDialog.visible = false">鍙� 娑�</el-button>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+import ApprovalFlowEditor from "@/views/officeProcessAutomation/AttendManage/overtime-apply/components/ApprovalFlowEditor.vue";
+import ApprovalFlowProgress from "./components/ApprovalFlowProgress.vue";
+import DetailPanel from "./components/DetailPanel.vue";
+import { useTravelReimburse } from "./useTravelReimburse.js";
+
+const tr = useTravelReimburse();
+const {
+ Search,
+ EXPENSE_SUBJECT_OPTIONS,
+ expenseSubjectLabel,
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ tableColumn,
+ importInputRef,
+ formRef,
+ form,
+ formDialog,
+ formRules,
+ detailDialog,
+ detailLoading,
+ detailRow,
+ approveDialog,
+ approveOpinion,
+ applicantFormSearchLoading,
+ applicantFormOptions,
+ flowUserOptions,
+ travelDaysDisplay,
+ travelTierLabel,
+ suggestedLivingSubsidy,
+ suggestedTransportSubsidy,
+ suggestedHotelLimit,
+ detailTotalAmount,
+ overBudgetWarnings,
+ budgetHint,
+ handleQuery,
+ resetSearch,
+ pagination,
+ remoteSearchApplicantForm,
+ userSelectLabel,
+ onApplicantChange,
+ recalcTravelStandards,
+ onTravelRangeChange,
+ onDetailAmountChange,
+ onApprovalFlowChange,
+ addExpenseDetail,
+ removeExpenseDetail,
+ syncApplyAmountFromDetails,
+ openFormDialog,
+ onFormClosed,
+ submitForm,
+ submitSaving,
+ openDetail,
+ approvalActionLabel,
+ submitApprove,
+ handleExport,
+ handleImportClick,
+ onImportFile,
+} = tr;
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.mb16 {
+ margin-bottom: 16px;
+}
+.mb8 {
+ margin-bottom: 8px;
+}
+.mt16 {
+ margin-top: 16px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+.sr-only-input {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.form-section {
+ margin-bottom: 16px;
+ border: 1px solid var(--el-border-color-lighter);
+}
+.form-section :deep(.el-card__header) {
+ padding: 12px 16px;
+ background: var(--el-fill-color-lighter);
+}
+.form-section :deep(.el-card__body) {
+ padding: 16px 16px 4px;
+}
+.card-header-title {
+ font-size: 15px;
+ font-weight: 600;
+}
+.card-header-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.amount-row {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ width: 100%;
+}
+.amount-input {
+ flex: 1;
+ min-width: 160px;
+}
+.w-full {
+ width: 100%;
+}
+.attachment-form-item {
+ margin-bottom: 0;
+}
+.detail-table {
+ margin-bottom: 0;
+}
+.section-title {
+ font-size: 15px;
+ font-weight: 600;
+ margin: 8px 0 12px;
+ color: var(--el-text-color-primary);
+ border-left: 3px solid var(--el-color-primary);
+ padding-left: 8px;
+}
+.field-tip {
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ margin-top: 4px;
+}
+.warn-list {
+ margin: 0;
+ padding-left: 18px;
+}
+.detail-toolbar {
+ margin-bottom: 8px;
+}
+.upload-block {
+ width: 100%;
+}
+.flow-tip {
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ margin-top: 8px;
+}
+.sync-btn {
+ margin-top: 4px;
+}
+.travel-reimburse-form-dialog :deep(.el-dialog__body) {
+ padding-top: 12px;
+}
+.travel-reimburse-form :deep(.el-form-item) {
+ margin-bottom: 18px;
+}
+.travel-reimburse-form :deep(.el-input-number) {
+ width: 100%;
+}
+.travel-reimburse-form :deep(.el-row) {
+ margin-bottom: 0;
+}
+</style>
diff --git a/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js
new file mode 100644
index 0000000..6c94c61
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/travelReimburseUtils.js
@@ -0,0 +1,189 @@
+import dayjs from "dayjs";
+
+/** 璐圭敤绉戠洰 */
+export const EXPENSE_SUBJECT_OPTIONS = [
+ { label: "浜ら�氳垂", value: "transport" },
+ { label: "浣忓璐�", value: "hotel" },
+ { label: "椁愰ギ璐�", value: "meal" },
+ { label: "鍏朵粬", value: "other" },
+];
+
+const TIER1_CITIES = ["鍖椾含", "涓婃捣", "骞垮窞", "娣卞湷"];
+
+export function expenseSubjectLabel(v) {
+ return EXPENSE_SUBJECT_OPTIONS.find((x) => x.value === v)?.label || "鈥�";
+}
+
+export function statusLabel(v) {
+ if (v === "draft") return "鑽夌";
+ if (v === "approved") return "閫氳繃";
+ if (v === "paid") return "宸蹭粯娆�";
+ if (v === "rejected") return "椹冲洖";
+ if (v === "cancelled") return "宸叉挙鍥�";
+ return "瀹℃牳涓�";
+}
+
+export function statusTagType(v) {
+ if (v === "draft") return "info";
+ if (v === "approved" || v === "paid") return "success";
+ if (v === "rejected") return "danger";
+ if (v === "cancelled") return "info";
+ return "warning";
+}
+
+export function detectTravelTier(destination) {
+ const city = (destination || "").trim();
+ if (!city) return "tier3";
+ if (TIER1_CITIES.some((c) => city.includes(c))) return "tier1";
+ const tier2Keywords = ["鏉窞", "鍗椾含", "姝︽眽", "鎴愰兘", "閲嶅簡", "瑗垮畨", "澶╂触", "鑻忓窞", "闀挎矙", "閮戝窞"];
+ if (tier2Keywords.some((c) => city.includes(c))) return "tier2";
+ return "tier3";
+}
+
+export function getTravelStandardByTier(tier) {
+ const map = {
+ tier1: { hotelPerNight: 600, transportPerDay: 80, mealPerDay: 100, label: "涓�绾垮煄甯�" },
+ tier2: { hotelPerNight: 450, transportPerDay: 60, mealPerDay: 80, label: "浜岀嚎鍩庡競" },
+ tier3: { hotelPerNight: 350, transportPerDay: 40, mealPerDay: 60, label: "鍏朵粬鍩庡競" },
+ };
+ return map[tier] || map.tier3;
+}
+
+export function computeTravelDays(startStr, endStr) {
+ if (!startStr || !endStr) return null;
+ const t0 = dayjs(startStr);
+ const t1 = dayjs(endStr);
+ if (!t0.isValid() || !t1.isValid() || !t1.isAfter(t0)) return null;
+ const days = Math.ceil(t1.diff(t0, "day", true));
+ return Math.max(1, days);
+}
+
+export function createEmptyExpenseDetail() {
+ return {
+ id: `ed_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
+ invoiceDate: "",
+ expenseSubject: "",
+ amount: undefined,
+ description: "",
+ };
+}
+
+export function createEmptyForm() {
+ return {
+ id: undefined,
+ reimburseNo: "",
+ applicantId: "",
+ employeeNo: "",
+ employeeName: "",
+ reimburseReason: "",
+ travelStartTime: "",
+ travelEndTime: "",
+ travelDays: undefined,
+ departurePlace: "",
+ destination: "",
+ hotelStandard: undefined,
+ hotelDays: undefined,
+ livingSubsidy: undefined,
+ applyAmount: undefined,
+ payee: "",
+ expenseDetails: [],
+ attachmentList: [],
+ approvalFlowNodes: [],
+ currentNodeIndex: 0,
+ needSpecialApproval: false,
+ deptId: "",
+ deptName: "",
+ travelTier: "tier3",
+ };
+}
+
+export function initApprovalFlowNodes(nodes) {
+ return (nodes || []).map((n, i) => ({
+ ...n,
+ sortOrder: i + 1,
+ nodeOrder: i + 1,
+ nodeStatus: i === 0 ? "process" : "wait",
+ approveOpinion: n.approveOpinion || "",
+ approveTime: n.approveTime || "",
+ }));
+}
+
+export function advanceApprovalFlow(row, opinion) {
+ const nodes = [...(row.approvalFlowNodes || [])];
+ const idx = row.currentNodeIndex ?? 0;
+ if (!nodes.length) return { nodes, currentNodeIndex: idx, approvalResult: row.approvalResult };
+ const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
+ nodes[idx] = {
+ ...nodes[idx],
+ nodeStatus: "finish",
+ approveOpinion: opinion || "鍚屾剰",
+ approveTime: now,
+ };
+ const next = idx + 1;
+ if (next >= nodes.length) {
+ return { nodes, currentNodeIndex: idx, approvalResult: "approved" };
+ }
+ nodes[next] = { ...nodes[next], nodeStatus: "process" };
+ return { nodes, currentNodeIndex: next, approvalResult: "pending" };
+}
+
+export function rejectApprovalFlow(row, opinion) {
+ const nodes = [...(row.approvalFlowNodes || [])];
+ const idx = row.currentNodeIndex ?? 0;
+ const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
+ if (nodes[idx]) {
+ nodes[idx] = {
+ ...nodes[idx],
+ nodeStatus: "error",
+ approveOpinion: opinion || "椹冲洖",
+ approveTime: now,
+ };
+ }
+ return { nodes, currentNodeIndex: idx, approvalResult: "rejected", rejectReason: opinion || "椹冲洖" };
+}
+
+/** 閮ㄩ棬棰勭畻锛堝鎺ラ绠楃郴缁熷墠杩斿洖绌猴級 */
+export function mockDeptBudget(deptId) {
+ if (!deptId) return null;
+ return null;
+}
+
+export function normalizeImportedRow(raw, idx) {
+ const id = raw.id != null && String(raw.id).length ? `imp_${String(raw.id)}_${idx}` : `imp_${Date.now()}_${idx}`;
+ const travelDays =
+ raw.travelDays != null
+ ? Number(raw.travelDays)
+ : computeTravelDays(raw.travelStartTime, raw.travelEndTime);
+ return {
+ id,
+ reimburseNo: raw.reimburseNo || `TR${dayjs().format("YYYYMMDD")}${String(idx).padStart(4, "0")}`,
+ applicantId: raw.applicantId != null ? String(raw.applicantId) : `imp_user_${idx}`,
+ employeeNo: raw.employeeNo ?? raw.applicantNo ?? "",
+ employeeName: raw.employeeName ?? raw.applicantName ?? "鏈煡",
+ applicantNo: raw.employeeNo ?? raw.applicantNo ?? "",
+ applicantName: raw.employeeName ?? raw.applicantName ?? "鏈煡",
+ reimburseReason: raw.reimburseReason ?? "",
+ travelStartTime: raw.travelStartTime ?? "",
+ travelEndTime: raw.travelEndTime ?? "",
+ travelDays: travelDays == null || Number.isNaN(travelDays) ? 1 : travelDays,
+ departurePlace: raw.departurePlace ?? "",
+ destination: raw.destination ?? "",
+ hotelStandard: raw.hotelStandard,
+ hotelDays: raw.hotelDays,
+ livingSubsidy: raw.livingSubsidy,
+ applyAmount: raw.applyAmount ?? 0,
+ payee: raw.payee ?? "",
+ expenseDetails: Array.isArray(raw.expenseDetails) ? raw.expenseDetails : [],
+ invoiceAttachments: Array.isArray(raw.invoiceAttachments) ? raw.invoiceAttachments : [],
+ approvalFlowNodes: Array.isArray(raw.approvalFlowNodes) ? raw.approvalFlowNodes : [],
+ currentNodeIndex: raw.currentNodeIndex ?? 0,
+ approvalResult: ["pending", "approved", "rejected"].includes(raw.approvalResult) ? raw.approvalResult : "pending",
+ rejectReason: raw.rejectReason ?? "",
+ approvalRecords: Array.isArray(raw.approvalRecords) ? raw.approvalRecords : [],
+ needSpecialApproval: !!raw.needSpecialApproval,
+ deptId: raw.deptId ?? "",
+ deptName: raw.deptName ?? "",
+ travelTier: raw.travelTier || detectTravelTier(raw.destination),
+ createTime: raw.createTime || dayjs().format("YYYY-MM-DD HH:mm:ss"),
+ };
+}
diff --git a/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/useTravelReimburse.js b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/useTravelReimburse.js
new file mode 100644
index 0000000..c92d88c
--- /dev/null
+++ b/src/views/officeProcessAutomation/ReimburseManage/travel-reimburse/useTravelReimburse.js
@@ -0,0 +1,696 @@
+import { Search } from "@element-plus/icons-vue";
+import dayjs from "dayjs";
+import {
+ deleteFinReimbursement,
+ getFinReimbursementDetail,
+ listFinReimbursementPage,
+ persistFinReimbursement,
+} from "@/api/officeProcessAutomation/finReimbursement.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { computed, getCurrentInstance, nextTick, onMounted, reactive, ref } from "vue";
+import {
+ buildFinReimbursementListParams,
+ filterReimbursementRowsBySearch,
+ hasActiveReimbursementSearch,
+ buildTravelReimbursementSaveDto,
+ canDeleteReimbursementRow,
+ canEditReimbursementRow,
+ enrichReimbursementListRowsWithApprovalFlow,
+ filterRowsByReimbursementType,
+ FIN_REIMBURSEMENT_TYPE,
+ mapFinReimbursementDetailRow,
+ mapTravelReimbursementRow,
+ resolveReimbursementDeleteId,
+ unwrapFinReimbursementDetail,
+ unwrapFinReimbursementPage,
+ validateReimbursementApprovalNodes,
+ validateReimbursementPersistDto,
+} from "../shared/finReimbursementMappers.js";
+import { consumeReimburseEditFromApprove } from "../shared/reimburseApproveBridge.js";
+import {
+ EXPENSE_SUBJECT_OPTIONS,
+ expenseSubjectLabel,
+ statusLabel,
+ statusTagType,
+ detectTravelTier,
+ getTravelStandardByTier,
+ computeTravelDays,
+ createEmptyExpenseDetail,
+ createEmptyForm,
+ initApprovalFlowNodes,
+ advanceApprovalFlow,
+ rejectApprovalFlow,
+ mockDeptBudget,
+ normalizeImportedRow,
+} from "./travelReimburseUtils.js";
+
+function unwrapArray(payload) {
+ if (Array.isArray(payload)) return payload;
+ if (payload?.data && Array.isArray(payload.data)) return payload.data;
+ if (payload?.rows && Array.isArray(payload.rows)) return payload.rows;
+ return [];
+}
+
+function isActiveUser(u) {
+ if (u.delFlag === "2" || u.delFlag === 2) return false;
+ if (u.status == null) return true;
+ return String(u.status) === "0";
+}
+
+export function useTravelReimburse() {
+ const { proxy } = getCurrentInstance();
+
+ const allRows = ref([]);
+
+ const searchForm = reactive({ applicantKeyword: "" });
+ const tableLoading = ref(false);
+ const page = reactive({ current: 1, size: 10, total: 0 });
+ const importInputRef = ref(null);
+ const allUsersCache = ref([]);
+ const applicantFormSearchLoading = ref(false);
+ const applicantFormOptions = ref([]);
+ const formRef = ref();
+ const form = reactive(createEmptyForm());
+ const formDialog = reactive({ visible: false, title: "", mode: "add", readonly: false });
+ const detailDialog = reactive({ visible: false });
+ const detailLoading = ref(false);
+ const detailRow = ref({});
+ const approveDialog = reactive({ visible: false, row: null });
+ const approveOpinion = ref("");
+ const submitSaving = ref(false);
+
+ const tableData = computed(() => allRows.value);
+
+ async function fetchList() {
+ tableLoading.value = true;
+ try {
+ const res = await listFinReimbursementPage(
+ buildFinReimbursementListParams({
+ page,
+ searchForm,
+ reimbursementType: FIN_REIMBURSEMENT_TYPE.TRAVEL,
+ })
+ );
+ const { records, total } = unwrapFinReimbursementPage(res);
+ const filtered = filterRowsByReimbursementType(
+ records,
+ FIN_REIMBURSEMENT_TYPE.TRAVEL
+ );
+ let mapped = filtered.map(mapTravelReimbursementRow);
+ mapped = await enrichReimbursementListRowsWithApprovalFlow(
+ mapped,
+ FIN_REIMBURSEMENT_TYPE.TRAVEL
+ );
+ if (hasActiveReimbursementSearch(searchForm)) {
+ mapped = filterReimbursementRowsBySearch(mapped, searchForm);
+ }
+ allRows.value = mapped;
+ const dropped = records.length - filtered.length;
+ let nextTotal =
+ dropped > 0 ? Math.max(0, Number(total) - dropped) : Number(total);
+ if (hasActiveReimbursementSearch(searchForm)) {
+ nextTotal = mapped.length;
+ }
+ page.total = nextTotal;
+ } catch {
+ allRows.value = [];
+ page.total = 0;
+ proxy?.$modal?.msgError?.("宸梾鎶ラ攢鍒楄〃鍔犺浇澶辫触");
+ } finally {
+ tableLoading.value = false;
+ }
+ }
+
+ const flowUserOptions = computed(() => allUsersCache.value.filter(isActiveUser));
+
+ const travelDaysDisplay = computed(() => {
+ const d = computeTravelDays(form.travelStartTime, form.travelEndTime);
+ return d == null ? "" : String(d);
+ });
+
+ const travelTierLabel = computed(() => {
+ const std = getTravelStandardByTier(form.travelTier || detectTravelTier(form.destination));
+ return `鎸�${std.label}鏍囧噯`;
+ });
+
+ const suggestedLivingSubsidy = computed(() => {
+ const days = computeTravelDays(form.travelStartTime, form.travelEndTime) || form.hotelDays || 0;
+ const std = getTravelStandardByTier(form.travelTier);
+ return Math.round(std.mealPerDay * days * 100) / 100;
+ });
+
+ const suggestedTransportSubsidy = computed(() => {
+ const days = computeTravelDays(form.travelStartTime, form.travelEndTime) || 0;
+ const std = getTravelStandardByTier(form.travelTier);
+ return Math.round(std.transportPerDay * days * 100) / 100;
+ });
+
+ const suggestedHotelLimit = computed(() => {
+ const nights = form.hotelDays || 0;
+ const perNight = form.hotelStandard ?? getTravelStandardByTier(form.travelTier).hotelPerNight;
+ return Math.round(perNight * nights * 100) / 100;
+ });
+
+ const detailTotalAmount = computed(() => {
+ const sum = (form.expenseDetails || []).reduce((s, d) => s + (Number(d.amount) || 0), 0);
+ return Math.round(sum * 100) / 100;
+ });
+
+ const overBudgetWarnings = computed(() => buildOverBudgetWarnings(form, detailTotalAmount.value, suggestedHotelLimit.value, suggestedTransportSubsidy.value, suggestedLivingSubsidy.value));
+
+ const budgetHint = computed(() => {
+ if (!form.deptId) return { visible: false };
+ const b = mockDeptBudget(form.deptId);
+ const apply = Number(form.applyAmount) || detailTotalAmount.value || 0;
+ const after = b.remainingAmount - apply;
+ return {
+ visible: true,
+ type: after < 0 ? "error" : "info",
+ title: `閮ㄩ棬棰勭畻鑱斿姩锛�${form.deptName || b.deptId}锛塦,
+ description: `骞村害棰勭畻 ${b.totalBudget} 鍏冿紝宸茬敤 ${b.usedAmount} 鍏冿紝鍓╀綑 ${b.remainingAmount} 鍏冿紱鏈崟鐢宠鍚庨璁″墿浣� ${Math.round(after * 100) / 100} 鍏冦�俙,
+ };
+ });
+
+ const tableColumn = ref([
+ { label: "鎶ラ攢鍗曞彿", prop: "reimburseNo", width: 150 },
+ { label: "鐢宠浜虹紪鍙�", prop: "applicantNo", width: 110 },
+ { label: "鐢宠浜�", prop: "applicantName", minWidth: 90 },
+ { label: "鍑哄樊寮�濮�", prop: "travelStartTime", width: 165 },
+ { label: "鍑哄樊缁撴潫", prop: "travelEndTime", width: 165 },
+ { label: "鍒涘缓鏃堕棿", prop: "createTime", width: 165 },
+ {
+ label: "鐘舵��",
+ prop: "approvalResult",
+ width: 100,
+ dataType: "tag",
+ formatData: (v) => statusLabel(v),
+ formatType: (v) => statusTagType(v),
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 220,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ disabled: (row) => !canEditReimbursementRow(row),
+ clickFun: (row) => openFormDialog("edit", row),
+ },
+ { name: "璇︽儏", type: "text", clickFun: (row) => openDetail(row) },
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ disabled: (row) => !canDeleteReimbursementRow(row),
+ clickFun: (row) => confirmRemoveRow(row),
+ },
+ ],
+ },
+ ]);
+
+ const formRules = {
+ applicantId: [{ required: true, message: "璇烽�夋嫨鍛樺伐", trigger: "change" }],
+ reimburseReason: [{ required: true, message: "璇峰~鍐欐姤閿�鍘熷洜", trigger: "blur" }],
+ travelStartTime: [{ required: true, message: "璇烽�夋嫨鍑哄樊寮�濮嬫椂闂�", trigger: "change" }],
+ travelEndTime: [
+ { required: true, message: "璇烽�夋嫨鍑哄樊缁撴潫鏃堕棿", trigger: "change" },
+ {
+ validator: (_r, val, cb) => {
+ if (!form.travelStartTime || !val) { cb(); return; }
+ if (computeTravelDays(form.travelStartTime, val) == null) cb(new Error("缁撴潫鏃堕棿椤绘櫄浜庡紑濮嬫椂闂�"));
+ else cb();
+ },
+ trigger: "change",
+ },
+ ],
+ departurePlace: [{ required: true, message: "璇峰~鍐欏嚭宸湴", trigger: "blur" }],
+ destination: [{ required: true, message: "璇峰~鍐欑洰鐨勫湴", trigger: "blur" }],
+ applyAmount: [{ required: true, message: "璇峰~鍐欑敵璇烽噾棰�", trigger: "blur" }],
+ payee: [{ required: true, message: "璇峰~鍐欐敹娆句汉", trigger: "blur" }],
+ approvalFlowNodes: [
+ {
+ validator: (_r, _v, cb) => {
+ const nodes = form.approvalFlowNodes || [];
+ if (!nodes.length) { cb(new Error("璇疯嚦灏戦厤缃竴涓鎵硅妭鐐�")); return; }
+ if (nodes.some((n) => n.approverId == null || n.approverId === "")) { cb(new Error("姣忎釜鑺傜偣椤婚�夋嫨瀹℃壒浜�")); return; }
+ cb();
+ },
+ trigger: "change",
+ },
+ ],
+ };
+
+ function buildOverBudgetWarnings(f, detailTotal, hotelLimit, transportLimit, mealLimit) {
+ const warnings = [];
+ const bySubject = { transport: 0, hotel: 0, meal: 0, other: 0 };
+ (f.expenseDetails || []).forEach((d) => {
+ const key = d.expenseSubject || "other";
+ bySubject[key] = (bySubject[key] || 0) + (Number(d.amount) || 0);
+ });
+ if (bySubject.transport > transportLimit && transportLimit > 0) {
+ warnings.push(`浜ら�氳垂 ${bySubject.transport} 鍏冭秴鍑烘爣鍑� ${transportLimit} 鍏僠);
+ }
+ if (bySubject.hotel > hotelLimit && hotelLimit > 0) {
+ warnings.push(`浣忓璐� ${bySubject.hotel} 鍏冭秴鍑洪檺棰� ${hotelLimit} 鍏僠);
+ }
+ if (bySubject.meal > mealLimit && mealLimit > 0) {
+ warnings.push(`椁愰ギ璐� ${bySubject.meal} 鍏冭秴鍑虹敓娲昏ˉ璐村缓璁� ${mealLimit} 鍏僠);
+ }
+ const std = getTravelStandardByTier(f.travelTier);
+ if (f.hotelStandard > std.hotelPerNight) {
+ warnings.push(`閰掑簵鏍囧噯 ${f.hotelStandard} 鍏�/鏅氶珮浜�${std.label}鏍囧噯 ${std.hotelPerNight} 鍏�/鏅歚);
+ }
+ const apply = Number(f.applyAmount) || detailTotal;
+ const standardTotal = transportLimit + hotelLimit + mealLimit;
+ if (apply > standardTotal && standardTotal > 0) {
+ warnings.push(`鐢宠鎬婚 ${apply} 鍏冮珮浜庡樊鏃呮爣鍑嗗悎璁$害 ${standardTotal} 鍏僠);
+ }
+ return warnings;
+ }
+
+ async function loadUserPool() {
+ try {
+ allUsersCache.value = unwrapArray(await userListNoPageByTenantId());
+ } catch {
+ allUsersCache.value = [];
+ }
+ }
+
+ function userSelectLabel(u) {
+ const nick = u.nickName || "";
+ const name = u.userName || "";
+ if (nick && name && nick !== name) return `${nick}锛�${name}锛塦;
+ return nick || name || `鐢ㄦ埛${u.userId ?? u.id ?? ""}`;
+ }
+
+ function userById(id) {
+ return allUsersCache.value.find((u) => String(u.userId ?? u.id) === String(id));
+ }
+
+ function employeeNoFromUser(u) {
+ if (!u) return "";
+ return u.userName ?? u.userCode ?? u.jobNumber ?? u.workNo ?? (u.userId != null ? String(u.userId) : "");
+ }
+
+ function filterUsersByQuery(query) {
+ const list = allUsersCache.value.filter(isActiveUser);
+ const q = (query || "").trim().toLowerCase();
+ if (!q) return [...list];
+ return list.filter((u) => {
+ const nick = (u.nickName || "").toLowerCase();
+ const uname = (u.userName || "").toLowerCase();
+ return nick.includes(q) || uname.includes(q);
+ });
+ }
+
+ async function remoteSearchApplicantForm(query) {
+ applicantFormSearchLoading.value = true;
+ try {
+ if (!allUsersCache.value.length) await loadUserPool();
+ applicantFormOptions.value = filterUsersByQuery(query);
+ } finally {
+ applicantFormSearchLoading.value = false;
+ }
+ }
+
+ function onApplicantChange(uid) {
+ const u = userById(uid);
+ if (u) {
+ form.employeeName = u.nickName || u.userName || "";
+ form.employeeNo = employeeNoFromUser(u);
+ form.payee = form.payee || form.employeeName;
+ form.deptId = String(u.deptId ?? u.sysDeptId ?? "");
+ form.deptName = u.dept?.deptName ?? u.deptName ?? "";
+ } else {
+ form.employeeName = "";
+ form.employeeNo = "";
+ }
+ }
+
+ function recalcTravelStandards() {
+ form.travelTier = detectTravelTier(form.destination);
+ const std = getTravelStandardByTier(form.travelTier);
+ if (form.hotelStandard == null || form.hotelStandard === 0) form.hotelStandard = std.hotelPerNight;
+ const days = computeTravelDays(form.travelStartTime, form.travelEndTime);
+ if (days != null) {
+ form.travelDays = days;
+ if (form.hotelDays == null) form.hotelDays = Math.max(0, days - 1);
+ if (form.livingSubsidy == null || form.livingSubsidy === 0) form.livingSubsidy = suggestedLivingSubsidy.value;
+ }
+ form.needSpecialApproval = buildOverBudgetWarnings(form, detailTotalAmount.value, suggestedHotelLimit.value, suggestedTransportSubsidy.value, suggestedLivingSubsidy.value).length > 0;
+ }
+
+ function onTravelRangeChange() {
+ recalcTravelStandards();
+ nextTick(() => formRef.value?.validateField?.("travelEndTime"));
+ }
+
+ function onDetailAmountChange() {
+ recalcTravelStandards();
+ }
+
+ function onApprovalFlowChange() {
+ nextTick(() => formRef.value?.validateField?.("approvalFlowNodes"));
+ }
+
+ function addExpenseDetail() {
+ form.expenseDetails.push(createEmptyExpenseDetail());
+ }
+
+ function removeExpenseDetail(index) {
+ form.expenseDetails.splice(index, 1);
+ recalcTravelStandards();
+ }
+
+ function mapAttachmentList(list) {
+ return (list || []).map((f, i) => ({
+ id: f.id ?? f.uid ?? `inv_${Date.now()}_${i}`,
+ name: f.name || f.fileName || f.originalFilename || "鏈懡鍚�",
+ url: f.url || f.downloadURL || f.previewURL || f.previewUrl || "",
+ }));
+ }
+
+ function syncApplyAmountFromDetails() {
+ form.applyAmount = detailTotalAmount.value;
+ recalcTravelStandards();
+ }
+
+ function handleQuery() {
+ page.current = 1;
+ return fetchList();
+ }
+
+ function resetSearch() {
+ searchForm.applicantKeyword = "";
+ handleQuery();
+ }
+
+ function pagination(obj) {
+ page.current = obj.page;
+ page.size = obj.limit;
+ return fetchList();
+ }
+
+ async function loadTravelDetailRow(row) {
+ const id = resolveReimbursementDeleteId(row);
+ if (id == null) {
+ throw new Error("missing id");
+ }
+ const res = await getFinReimbursementDetail(id);
+ const raw = unwrapFinReimbursementDetail(res);
+ return mapFinReimbursementDetailRow(raw, FIN_REIMBURSEMENT_TYPE.TRAVEL);
+ }
+
+ async function openDetail(row) {
+ const id = resolveReimbursementDeleteId(row);
+ if (id == null) {
+ proxy?.$modal?.msgWarning?.("鏃犳硶鏌ョ湅璇︽儏锛氱己灏戞姤閿�鍗� ID");
+ return;
+ }
+ detailDialog.visible = true;
+ detailLoading.value = true;
+ detailRow.value = { ...row };
+ try {
+ detailRow.value = await loadTravelDetailRow(row);
+ } catch {
+ proxy?.$modal?.msgError?.("鍔犺浇璇︽儏澶辫触");
+ detailDialog.visible = false;
+ } finally {
+ detailLoading.value = false;
+ }
+ }
+
+ async function confirmRemoveRow(row) {
+ const id = resolveReimbursementDeleteId(row);
+ if (id == null) {
+ proxy?.$modal?.msgWarning?.("鏃犳硶鍒犻櫎锛氱己灏戞姤閿�鍗� ID");
+ return;
+ }
+ const title = row.reimburseNo || row.billNo || row.reimburseReason || "璇ユ姤閿�鍗�";
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゃ��${title}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+ "鍒犻櫎纭",
+ {
+ type: "warning",
+ confirmButtonText: "纭畾鍒犻櫎",
+ cancelButtonText: "鍙栨秷",
+ distinguishCancelAndClose: true,
+ autofocus: false,
+ }
+ );
+ } catch {
+ return;
+ }
+ try {
+ await deleteFinReimbursement([id]);
+ proxy?.$modal?.msgSuccess?.("鍒犻櫎鎴愬姛");
+ if (detailDialog.visible && resolveReimbursementDeleteId(detailRow.value) === id) {
+ detailDialog.visible = false;
+ }
+ await handleQuery();
+ } catch {
+ proxy?.$modal?.msgError?.("鍒犻櫎澶辫触");
+ }
+ }
+
+ function openApprove(row) {
+ approveDialog.row = { ...row };
+ approveDialog.visible = true;
+ }
+
+ function approvalActionLabel(v) {
+ if (v === "approved") return "閫氳繃";
+ if (v === "rejected") return "椹冲洖";
+ return "鎻愪氦";
+ }
+
+ async function openFormDialog(mode, row) {
+ formDialog.mode = mode;
+ formDialog.readonly = false;
+ formDialog.title = mode === "add" ? "鏂板宸梾鎶ラ攢" : "缂栬緫宸梾鎶ラ攢";
+ if (!allUsersCache.value.length) await loadUserPool();
+ Object.assign(form, createEmptyForm());
+ if (mode === "edit" && row) {
+ let editRow = row;
+ try {
+ editRow = await loadTravelDetailRow(row);
+ } catch {
+ proxy?.$modal?.msgError?.("鍔犺浇鎶ラ攢璇︽儏澶辫触");
+ return;
+ }
+ Object.assign(form, {
+ ...JSON.parse(JSON.stringify(editRow)),
+ reimbursementId: editRow.reimbursementId ?? editRow.id,
+ attachmentList: JSON.parse(JSON.stringify(editRow.attachmentList || editRow.invoiceAttachments || [])),
+ approvalFlowNodes: JSON.parse(JSON.stringify(editRow.approvalFlowNodes || [])),
+ expenseDetails: JSON.parse(JSON.stringify(editRow.expenseDetails || [])),
+ });
+ const u = userById(editRow.applicantId);
+ applicantFormOptions.value = u
+ ? [u]
+ : [{ userId: editRow.applicantId, nickName: editRow.employeeName, userName: editRow.employeeNo }];
+ } else {
+ form.approvalFlowNodes = [{ approverId: null, approverName: "", sortOrder: 1, nodeOrder: 1 }];
+ remoteSearchApplicantForm("");
+ }
+ formDialog.visible = true;
+ nextTick(() => {
+ formRef.value?.clearValidate?.();
+ recalcTravelStandards();
+ });
+ }
+
+ function onFormClosed() {
+ formRef.value?.resetFields?.();
+ }
+
+ async function submitForm() {
+ try {
+ await formRef.value?.validate?.();
+ } catch {
+ return;
+ }
+ if (!(form.expenseDetails || []).length) {
+ proxy?.$modal?.msgWarning?.("璇疯嚦灏戞坊鍔犱竴鏉℃姤閿�鏄庣粏");
+ return;
+ }
+ recalcTravelStandards();
+ if (form.needSpecialApproval) {
+ try {
+ await proxy.$modal.confirm("瀛樺湪瓒呮敮椤癸紝鎻愪氦鍚庡皢鏍囪涓洪渶鐗规壒锛屾槸鍚︾户缁紵");
+ } catch {
+ return;
+ }
+ }
+ if (submitSaving.value) return;
+ const isEdit = formDialog.mode === "edit";
+ const dto = buildTravelReimbursementSaveDto(form, { computeTravelDays });
+ const check = validateReimbursementPersistDto(dto, isEdit);
+ if (!check.ok) {
+ proxy?.$modal?.msgWarning?.(check.message);
+ return;
+ }
+ const nodeCheck = validateReimbursementApprovalNodes(dto);
+ if (!nodeCheck.ok) {
+ proxy?.$modal?.msgWarning?.(nodeCheck.message);
+ return;
+ }
+ submitSaving.value = true;
+ try {
+ await persistFinReimbursement(dto, isEdit);
+ proxy?.$modal?.msgSuccess?.(isEdit ? "淇濆瓨鎴愬姛" : "鎻愪氦鎴愬姛");
+ formDialog.visible = false;
+ await handleQuery();
+ } catch {
+ proxy?.$modal?.msgError?.(isEdit ? "淇濆瓨澶辫触" : "鎻愪氦澶辫触");
+ } finally {
+ submitSaving.value = false;
+ }
+ }
+
+ async function submitApprove(result) {
+ const row = approveDialog.row;
+ if (!row) return;
+ if (result === "rejected" && !(approveOpinion.value || "").trim()) {
+ proxy?.$modal?.msgWarning?.("椹冲洖椤诲~鍐欏鎵规剰瑙�");
+ return;
+ }
+ const idx = allRows.value.findIndex((r) => r.id === row.id);
+ if (idx === -1) return;
+ const cur = allRows.value[idx];
+ const operatorName = "褰撳墠瀹℃壒浜�";
+ const record = {
+ operatorName,
+ result,
+ opinion: approveOpinion.value || (result === "approved" ? "鍚屾剰" : "椹冲洖"),
+ time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
+ };
+ const records = [...(cur.approvalRecords || []), record];
+ let flowUpdate;
+ if (result === "approved") {
+ flowUpdate = advanceApprovalFlow(cur, approveOpinion.value);
+ } else {
+ flowUpdate = rejectApprovalFlow(cur, approveOpinion.value);
+ }
+ allRows.value[idx] = {
+ ...cur,
+ approvalFlowNodes: flowUpdate.nodes,
+ currentNodeIndex: flowUpdate.currentNodeIndex,
+ approvalResult: flowUpdate.approvalResult,
+ rejectReason: flowUpdate.rejectReason ?? cur.rejectReason,
+ approvalRecords: records,
+ };
+ proxy?.$modal?.msgSuccess?.(result === "approved" ? "宸查�氳繃" : "宸查┏鍥�");
+ approveDialog.visible = false;
+ handleQuery();
+ }
+
+ function handleExport() {
+ const data = allRows.value;
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json;charset=utf-8" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `宸梾鎶ラ攢瀵煎嚭_${dayjs().format("YYYYMMDDHHmmss")}.json`;
+ a.click();
+ URL.revokeObjectURL(url);
+ proxy?.$modal?.msgSuccess?.(`宸插鍑� ${data.length} 鏉);
+ }
+
+ function handleImportClick() {
+ importInputRef.value?.click?.();
+ }
+
+ function onImportFile(e) {
+ const file = e.target.files?.[0];
+ e.target.value = "";
+ if (!file) return;
+ const reader = new FileReader();
+ reader.onload = () => {
+ try {
+ const parsed = JSON.parse(String(reader.result || ""));
+ const arr = Array.isArray(parsed) ? parsed : parsed?.rows || parsed?.data;
+ if (!Array.isArray(arr) || !arr.length) {
+ proxy?.$modal?.msgWarning?.("瀵煎叆鏍煎紡椤讳负宸梾鎶ラ攢 JSON 鏁扮粍");
+ return;
+ }
+ arr.forEach((raw, i) => allRows.value.unshift(normalizeImportedRow(raw, i)));
+ proxy?.$modal?.msgSuccess?.(`鎴愬姛瀵煎叆 ${arr.length} 鏉);
+ handleQuery();
+ } catch {
+ proxy?.$modal?.msgError?.("瑙f瀽澶辫触");
+ }
+ };
+ reader.readAsText(file, "utf-8");
+ }
+
+ onMounted(async () => {
+ loadUserPool();
+ await fetchList();
+ const editPayload = consumeReimburseEditFromApprove();
+ if (editPayload?.reimbursementId != null) {
+ await openFormDialog("edit", { reimbursementId: editPayload.reimbursementId });
+ }
+ });
+
+ return {
+ Search,
+ EXPENSE_SUBJECT_OPTIONS,
+ expenseSubjectLabel,
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ tableColumn,
+ importInputRef,
+ formRef,
+ form,
+ formDialog,
+ formRules,
+ detailDialog,
+ detailLoading,
+ detailRow,
+ approveDialog,
+ approveOpinion,
+ applicantFormSearchLoading,
+ applicantFormOptions,
+ flowUserOptions,
+ travelDaysDisplay,
+ travelTierLabel,
+ suggestedLivingSubsidy,
+ suggestedTransportSubsidy,
+ suggestedHotelLimit,
+ detailTotalAmount,
+ overBudgetWarnings,
+ budgetHint,
+ handleQuery,
+ resetSearch,
+ pagination,
+ remoteSearchApplicantForm,
+ userSelectLabel,
+ onApplicantChange,
+ recalcTravelStandards,
+ onTravelRangeChange,
+ onDetailAmountChange,
+ onApprovalFlowChange,
+ addExpenseDetail,
+ removeExpenseDetail,
+ syncApplyAmountFromDetails,
+ openFormDialog,
+ onFormClosed,
+ submitForm,
+ submitSaving,
+ openDetail,
+ confirmRemoveRow,
+ openApprove,
+ approvalActionLabel,
+ submitApprove,
+ handleExport,
+ handleImportClick,
+ onImportFile,
+ };
+}
diff --git a/src/views/officeProcessAutomation/SysAdmin/dept-manage/index.vue b/src/views/officeProcessAutomation/SysAdmin/dept-manage/index.vue
new file mode 100644
index 0000000..9dd4e90
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/dept-manage/index.vue
@@ -0,0 +1,291 @@
+<!--OA妯″潡锛氶儴闂ㄧ鐞�-->
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
+ <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptName">
+ <el-input
+ v-model="queryParams.deptName"
+ placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�"
+ clearable
+ style="width: 200px"
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select v-model="queryParams.status" placeholder="閮ㄩ棬鐘舵��" clearable style="width: 200px">
+ <el-option
+ v-for="dict in sys_normal_disable"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="handleAdd"
+ v-hasPermi="['system:dept:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="info"
+ plain
+ icon="Sort"
+ @click="toggleExpandAll"
+ >灞曞紑/鎶樺彔</el-button>
+ </el-col>
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+ <el-table
+ v-if="refreshTable"
+ v-loading="loading"
+ :data="deptList"
+ row-key="deptId"
+ :default-expand-all="isExpandAll"
+ :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+ >
+ <el-table-column prop="deptName" label="閮ㄩ棬鍚嶇О" width="260"></el-table-column>
+ <el-table-column prop="orderNum" label="鎺掑簭" width="200"></el-table-column>
+ <el-table-column prop="status" label="鐘舵��" width="100">
+ <template #default="scope">
+ <dict-tag :options="sys_normal_disable" :value="scope.row.status" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="200">
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.createTime) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template #default="scope">
+ <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dept:edit']">淇敼</el-button>
+ <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:dept:add']">鏂板</el-button>
+ <el-button v-if="scope.row.parentId != 0" link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dept:remove']">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 娣诲姞鎴栦慨鏀归儴闂ㄥ璇濇 -->
+ <el-dialog :title="title" v-model="open" width="600px" append-to-body>
+ <el-form ref="deptRef" :model="form" :rules="rules" label-width="80px">
+ <el-row>
+ <el-col :span="24" v-if="form.parentId !== 0">
+ <el-form-item label="涓婄骇閮ㄩ棬" prop="parentId">
+ <el-tree-select
+ v-model="form.parentId"
+ :data="deptOptions"
+ :props="{ value: 'deptId', label: 'deptName', children: 'children' }"
+ value-key="deptId"
+ placeholder="閫夋嫨涓婄骇閮ㄩ棬"
+ check-strictly
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptName">
+ <el-input v-model="form.deptName" placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏄剧ず鎺掑簭" prop="orderNum">
+ <el-input-number v-model="form.orderNum" controls-position="right" :min="0"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璐熻矗浜�" prop="leader">
+ <el-input v-model="form.leader" placeholder="璇疯緭鍏ヨ礋璐d汉" maxlength="20" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鑱旂郴鐢佃瘽" prop="phone">
+ <el-input v-model="form.phone" placeholder="璇疯緭鍏ヨ仈绯荤數璇�" maxlength="11" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閭" prop="email">
+ <el-input v-model="form.email" placeholder="璇疯緭鍏ラ偖绠�" maxlength="50" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閮ㄩ棬鐘舵��">
+ <el-radio-group v-model="form.status">
+ <el-radio
+ v-for="dict in sys_normal_disable"
+ :key="dict.value"
+ :value="dict.value"
+ >{{ dict.label }}</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閮ㄩ棬缂栧彿" prop="deptNick">
+ <el-input v-model="form.deptNick" placeholder="璇疯緭鍏ラ儴闂ㄧ紪鍙�" maxlength="50" />
+ </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="cancel">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup name="Dept">
+import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept"
+
+const { proxy } = getCurrentInstance()
+const { sys_normal_disable } = proxy.useDict("sys_normal_disable")
+
+const deptList = ref([])
+const open = ref(false)
+const loading = ref(true)
+const showSearch = ref(true)
+const title = ref("")
+const deptOptions = ref([])
+const isExpandAll = ref(true)
+const refreshTable = ref(true)
+
+const data = reactive({
+ form: {},
+ queryParams: {
+ deptName: undefined,
+ status: undefined
+ },
+ rules: {
+ parentId: [{ required: true, message: "涓婄骇閮ㄩ棬涓嶈兘涓虹┖", trigger: "blur" }],
+ deptName: [{ required: true, message: "閮ㄩ棬鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }],
+ orderNum: [{ required: true, message: "鏄剧ず鎺掑簭涓嶈兘涓虹┖", trigger: "blur" }],
+ email: [{ type: "email", message: "璇疯緭鍏ユ纭殑閭鍦板潃", trigger: ["blur", "change"] }],
+ phone: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", trigger: "blur" }],
+ deptNick: [{ required: true, message: "閮ㄩ棬缂栧彿涓嶈兘涓虹┖", trigger: "blur" }],
+ },
+})
+
+const { queryParams, form, rules } = toRefs(data)
+
+/** 鏌ヨ閮ㄩ棬鍒楄〃 */
+function getList() {
+ loading.value = true
+ listDept(queryParams.value).then(response => {
+ deptList.value = proxy.handleTree(response.data, "deptId")
+ loading.value = false
+ })
+}
+
+/** 鍙栨秷鎸夐挳 */
+function cancel() {
+ open.value = false
+ reset()
+}
+
+/** 琛ㄥ崟閲嶇疆 */
+function reset() {
+ form.value = {
+ deptId: undefined,
+ parentId: undefined,
+ deptName: undefined,
+ orderNum: 0,
+ leader: undefined,
+ phone: undefined,
+ email: undefined,
+ status: "0",
+ deptNick: undefined,
+ }
+ proxy.resetForm("deptRef")
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+ getList()
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+ proxy.resetForm("queryRef")
+ handleQuery()
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd(row) {
+ reset()
+ listDept().then(response => {
+ deptOptions.value = proxy.handleTree(response.data, "deptId")
+ })
+ if (row != undefined) {
+ form.value.parentId = row.deptId
+ }
+ open.value = true
+ title.value = "娣诲姞閮ㄩ棬"
+}
+
+/** 灞曞紑/鎶樺彔鎿嶄綔 */
+function toggleExpandAll() {
+ refreshTable.value = false
+ isExpandAll.value = !isExpandAll.value
+ nextTick(() => {
+ refreshTable.value = true
+ })
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+ reset()
+ listDeptExcludeChild(row.deptId).then(response => {
+ deptOptions.value = proxy.handleTree(response.data, "deptId")
+ })
+ getDept(row.deptId).then(response => {
+ form.value = response.data
+ open.value = true
+ title.value = "淇敼閮ㄩ棬"
+ })
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+ proxy.$refs["deptRef"].validate(valid => {
+ if (valid) {
+ if (form.value.deptId != undefined) {
+ updateDept(form.value).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ open.value = false
+ getList()
+ })
+ } else {
+ addDept(form.value).then(response => {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛")
+ open.value = false
+ getList()
+ })
+ }
+ }
+ })
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+ proxy.$modal.confirm('鏄惁纭鍒犻櫎鍚嶇О涓�"' + row.deptName + '"鐨勬暟鎹」?').then(function() {
+ return delDept(row.deptId)
+ }).then(() => {
+ getList()
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
+ }).catch(() => {})
+}
+
+getList()
+</script>
+
diff --git a/src/views/officeProcessAutomation/SysAdmin/log-manage/index.vue b/src/views/officeProcessAutomation/SysAdmin/log-manage/index.vue
new file mode 100644
index 0000000..2701c1a
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/log-manage/index.vue
@@ -0,0 +1,315 @@
+<!--OA妯″潡锛氭棩蹇楃鐞�-->
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+ <el-form-item label="鎿嶄綔鍦板潃" prop="operIp">
+ <el-input
+ v-model="queryParams.operIp"
+ placeholder="璇疯緭鍏ユ搷浣滃湴鍧�"
+ clearable
+ style="width: 240px;"
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="绯荤粺妯″潡" prop="title">
+ <el-input
+ v-model="queryParams.title"
+ placeholder="璇疯緭鍏ョ郴缁熸ā鍧�"
+ clearable
+ style="width: 240px;"
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鎿嶄綔浜哄憳" prop="operName">
+ <el-input
+ v-model="queryParams.operName"
+ placeholder="璇疯緭鍏ユ搷浣滀汉鍛�"
+ clearable
+ style="width: 240px;"
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="绫诲瀷" prop="businessType">
+ <el-select
+ v-model="queryParams.businessType"
+ placeholder="鎿嶄綔绫诲瀷"
+ clearable
+ style="width: 240px"
+ >
+ <el-option
+ v-for="dict in sys_oper_type"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select
+ v-model="queryParams.status"
+ placeholder="鎿嶄綔鐘舵��"
+ clearable
+ style="width: 240px"
+ >
+ <el-option
+ v-for="dict in sys_common_status"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鎿嶄綔鏃堕棿" style="width: 308px">
+ <el-date-picker
+ v-model="dateRange"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
+ ></el-date-picker>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="danger"
+ plain
+ icon="Delete"
+ :disabled="multiple"
+ @click="handleDelete"
+ v-hasPermi="['monitor:operlog:remove']"
+ >鍒犻櫎</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="danger"
+ plain
+ icon="Delete"
+ @click="handleClean"
+ v-hasPermi="['monitor:operlog:remove']"
+ >娓呯┖</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="warning"
+ plain
+ icon="Download"
+ @click="handleExport"
+ v-hasPermi="['monitor:operlog:export']"
+ >瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table ref="operlogRef" v-loading="loading" :data="operlogList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
+ <el-table-column type="selection" width="50" align="center" />
+ <el-table-column label="鏃ュ織缂栧彿" align="center" prop="operId" />
+ <el-table-column label="绯荤粺妯″潡" align="center" prop="title" :show-overflow-tooltip="true" />
+ <el-table-column label="鎿嶄綔绫诲瀷" align="center" prop="businessType">
+ <template #default="scope">
+ <dict-tag :options="sys_oper_type" :value="scope.row.businessType" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔浜哄憳" align="center" width="110" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" />
+ <el-table-column label="鎿嶄綔鍦板潃" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
+ <el-table-column label="鎿嶄綔鐘舵��" align="center" prop="status">
+ <template #default="scope">
+ <dict-tag :options="sys_common_status" :value="scope.row.status" />
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔鏃ユ湡" align="center" prop="operTime" width="180" sortable="custom" :sort-orders="['descending', 'ascending']">
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.operTime) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="娑堣�楁椂闂�" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']">
+ <template #default="scope">
+ <span>{{ scope.row.costTime }}姣</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template #default="scope">
+ <el-button link type="primary" icon="View" @click="handleView(scope.row, scope.index)" v-hasPermi="['monitor:operlog:query']">璇︾粏</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ v-model:page="queryParams.pageNum"
+ v-model:limit="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 鎿嶄綔鏃ュ織璇︾粏 -->
+ <el-dialog title="鎿嶄綔鏃ュ織璇︾粏" v-model="open" width="800px" append-to-body>
+ <el-form :model="form" label-width="100px">
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鎿嶄綔妯″潡锛�">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
+ <el-form-item
+ label="鐧诲綍淇℃伅锛�"
+ >{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璇锋眰鍦板潃锛�">{{ form.operUrl }}</el-form-item>
+ <el-form-item label="璇锋眰鏂瑰紡锛�">{{ form.requestMethod }}</el-form-item>
+ </el-col>
+ <el-col :span="24">
+ <el-form-item label="鎿嶄綔鏂规硶锛�">{{ form.method }}</el-form-item>
+ </el-col>
+ <el-col :span="24">
+ <el-form-item label="璇锋眰鍙傛暟锛�">{{ form.operParam }}</el-form-item>
+ </el-col>
+ <el-col :span="24">
+ <el-form-item label="杩斿洖鍙傛暟锛�">{{ form.jsonResult }}</el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鎿嶄綔鐘舵�侊細">
+ <div v-if="form.status === 0">姝e父</div>
+ <div v-else-if="form.status === 1">澶辫触</div>
+ </el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="娑堣�楁椂闂达細">{{ form.costTime }}姣</el-form-item>
+ </el-col>
+ <el-col :span="8">
+ <el-form-item label="鎿嶄綔鏃堕棿锛�">{{ parseTime(form.operTime) }}</el-form-item>
+ </el-col>
+ <el-col :span="24">
+ <el-form-item label="寮傚父淇℃伅锛�" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="open = false">鍏� 闂�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup name="Operlog">
+import { list, delOperlog, cleanOperlog } from "@/api/monitor/operlog"
+import {onMounted} from "vue";
+
+const { proxy } = getCurrentInstance()
+const { sys_oper_type, sys_common_status } = proxy.useDict("sys_oper_type","sys_common_status")
+
+const operlogList = ref([])
+const open = ref(false)
+const loading = ref(true)
+const showSearch = ref(true)
+const ids = ref([])
+const single = ref(true)
+const multiple = ref(true)
+const total = ref(0)
+const title = ref("")
+const dateRange = ref([])
+const defaultSort = ref({ prop: "operTime", order: "descending" })
+
+const data = reactive({
+ form: {},
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ operIp: undefined,
+ title: undefined,
+ operName: undefined,
+ businessType: undefined,
+ status: undefined
+ }
+})
+
+const { queryParams, form } = toRefs(data)
+
+/** 鏌ヨ鐧诲綍鏃ュ織 */
+function getList() {
+ loading.value = true
+ list(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
+ operlogList.value = response.rows
+ total.value = response.total
+ loading.value = false
+ })
+}
+
+/** 鎿嶄綔鏃ュ織绫诲瀷瀛楀吀缈昏瘧 */
+function typeFormat(row, column) {
+ return proxy.selectDictLabel(sys_oper_type.value, row.businessType)
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+ queryParams.value.pageNum = 1
+ getList()
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+ dateRange.value = []
+ proxy.resetForm("queryRef")
+ queryParams.value.pageNum = 1
+ proxy.$refs["operlogRef"].sort(defaultSort.value.prop, defaultSort.value.order)
+}
+
+/** 澶氶�夋閫変腑鏁版嵁 */
+function handleSelectionChange(selection) {
+ ids.value = selection.map(item => item.operId)
+ multiple.value = !selection.length
+}
+
+/** 鎺掑簭瑙﹀彂浜嬩欢 */
+function handleSortChange(column, prop, order) {
+ queryParams.value.orderByColumn = column.prop
+ queryParams.value.isAsc = column.order
+ getList()
+}
+
+/** 璇︾粏鎸夐挳鎿嶄綔 */
+function handleView(row) {
+ open.value = true
+ form.value = row
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+ const operIds = row.operId || ids.value
+ proxy.$modal.confirm('鏄惁纭鍒犻櫎鏃ュ織缂栧彿涓�"' + operIds + '"鐨勬暟鎹」?').then(function () {
+ return delOperlog(operIds)
+ }).then(() => {
+ getList()
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
+ }).catch(() => {})
+}
+
+/** 娓呯┖鎸夐挳鎿嶄綔 */
+function handleClean() {
+ proxy.$modal.confirm("鏄惁纭娓呯┖鎵�鏈夋搷浣滄棩蹇楁暟鎹」?").then(function () {
+ return cleanOperlog()
+ }).then(() => {
+ getList()
+ proxy.$modal.msgSuccess("娓呯┖鎴愬姛")
+ }).catch(() => {})
+}
+
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+ proxy.download("monitor/operlog/export",{
+ ...queryParams.value,
+ }, `config_${new Date().getTime()}.xlsx`)
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
diff --git a/src/views/officeProcessAutomation/SysAdmin/user-manage/authRole.vue b/src/views/officeProcessAutomation/SysAdmin/user-manage/authRole.vue
new file mode 100644
index 0000000..a7546aa
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/user-manage/authRole.vue
@@ -0,0 +1,123 @@
+<template>
+ <div class="app-container">
+ <h4 class="form-header h4">鍩烘湰淇℃伅</h4>
+ <el-form :model="form" label-width="80px">
+ <el-row>
+ <el-col :span="8" :offset="2">
+ <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName">
+ <el-input v-model="form.nickName" disabled />
+ </el-form-item>
+ </el-col>
+ <el-col :span="8" :offset="2">
+ <el-form-item label="鐧诲綍璐﹀彿" prop="userName">
+ <el-input v-model="form.userName" disabled />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+
+ <h4 class="form-header h4">瑙掕壊淇℃伅</h4>
+ <el-table v-loading="loading" :row-key="getRowKey" @row-click="clickRow" ref="roleRef" @selection-change="handleSelectionChange" :data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)">
+ <el-table-column label="搴忓彿" width="55" type="index" align="center">
+ <template #default="scope">
+ <span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column type="selection" :reserve-selection="true" :selectable="checkSelectable" width="55"></el-table-column>
+ <el-table-column label="瑙掕壊缂栧彿" align="center" prop="roleId" />
+ <el-table-column label="瑙掕壊鍚嶇О" align="center" prop="roleName" />
+ <el-table-column label="鏉冮檺瀛楃" align="center" prop="roleKey" />
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.createTime) }}</span>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination v-show="total > 0" :total="total" v-model:page="pageNum" v-model:limit="pageSize" />
+
+ <el-form label-width="100px">
+ <div style="text-align: center;margin-left:-120px;margin-top:30px;">
+ <el-button type="primary" @click="submitForm()">鎻愪氦</el-button>
+ <el-button @click="close()">杩斿洖</el-button>
+ </div>
+ </el-form>
+ </div>
+</template>
+
+<script setup name="AuthRole">
+import { getAuthRole, updateAuthRole } from "@/api/system/user"
+
+const route = useRoute()
+const { proxy } = getCurrentInstance()
+
+const loading = ref(true)
+const total = ref(0)
+const pageNum = ref(1)
+const pageSize = ref(10)
+const roleIds = ref([])
+const roles = ref([])
+const form = ref({
+ nickName: undefined,
+ userName: undefined,
+ userId: undefined
+})
+
+/** 鍗曞嚮閫変腑琛屾暟鎹� */
+function clickRow(row) {
+ if (checkSelectable(row)) {
+ proxy.$refs["roleRef"].toggleRowSelection(row)
+ }
+}
+
+/** 澶氶�夋閫変腑鏁版嵁 */
+function handleSelectionChange(selection) {
+ roleIds.value = selection.map(item => item.roleId)
+}
+
+/** 淇濆瓨閫変腑鐨勬暟鎹紪鍙� */
+function getRowKey(row) {
+ return row.roleId
+}
+
+// 妫�鏌ヨ鑹茬姸鎬�
+function checkSelectable(row) {
+ return row.status === "0" ? true : false
+}
+
+/** 鍏抽棴鎸夐挳 */
+function close() {
+ const obj = { path: "/system/user" }
+ proxy.$tab.closeOpenPage(obj)
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+ const userId = form.value.userId
+ const rIds = roleIds.value.join(",")
+ updateAuthRole({ userId: userId, roleIds: rIds }).then(response => {
+ proxy.$modal.msgSuccess("鎺堟潈鎴愬姛")
+ close()
+ })
+}
+
+(() => {
+ const userId = route.params && route.params.userId
+ if (userId) {
+ loading.value = true
+ getAuthRole(userId).then(response => {
+ form.value = response.user
+ roles.value = response.roles
+ total.value = roles.value.length
+ nextTick(() => {
+ roles.value.forEach(row => {
+ if (row.flag) {
+ proxy.$refs["roleRef"].toggleRowSelection(row)
+ }
+ })
+ })
+ loading.value = false
+ })
+ }
+})()
+</script>
diff --git a/src/views/officeProcessAutomation/SysAdmin/user-manage/index.vue b/src/views/officeProcessAutomation/SysAdmin/user-manage/index.vue
new file mode 100644
index 0000000..97a06b1
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/user-manage/index.vue
@@ -0,0 +1,550 @@
+<!--OA妯″潡锛氱敤鎴风鐞�-->
+<template>
+ <div class="app-container">
+ <el-row :gutter="20" style="height: calc(100vh - 8em)">
+ <splitpanes :horizontal="appStore.device === 'mobile'" class="default-theme">
+ <!--閮ㄩ棬鏁版嵁-->
+ <pane size="16">
+ <el-col style="padding: 10px">
+ <div class="head-container">
+ <el-input v-model="deptNames" placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" clearable prefix-icon="Search" style="margin-bottom: 20px" />
+ </div>
+ <div class="head-container">
+ <el-tree :data="deptOptions" :props="{ label: 'label', children: 'children' }" :expand-on-click-node="false" :filter-node-method="filterNode" ref="deptTreeRef" node-key="id" highlight-current default-expand-all @node-click="handleNodeClick" />
+ </div>
+ </el-col>
+ </pane>
+ <!--鐢ㄦ埛鏁版嵁-->
+ <pane size="84">
+ <el-col style="padding: 10px; height: 100%; display: flex; flex-direction: column;">
+ <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+ <el-form-item label="鐧诲綍璐﹀彿" prop="userName">
+ <el-input v-model="queryParams.userName" placeholder="璇疯緭鍏ョ櫥褰曡处鍙�" clearable style="width: 240px" @keyup.enter="handleQuery" />
+ </el-form-item>
+ <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+ <el-input v-model="queryParams.phonenumber" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" clearable style="width: 240px" @keyup.enter="handleQuery" />
+ </el-form-item>
+ <el-form-item label="鐘舵��" prop="status">
+ <el-select v-model="queryParams.status" placeholder="鐢ㄦ埛鐘舵��" clearable style="width: 240px">
+ <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿" style="width: 308px">
+ <el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="寮�濮嬫棩鏈�" end-placeholder="缁撴潫鏃ユ湡"></el-date-picker>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:user:add']">鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['system:user:edit']">淇敼</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:user:remove']">鍒犻櫎</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button type="info" plain icon="Upload" @click="handleImport" v-hasPermi="['system:user:import']">瀵煎叆</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:user:export']">瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
+ </el-row>
+
+ <div style="flex: 1; overflow: hidden;">
+ <el-table v-loading="loading" :data="userList" height="100%" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="50" align="center" />
+ <el-table-column label="鐢ㄦ埛缂栧彿" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
+ <el-table-column label="鐧诲綍璐﹀彿" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
+ <el-table-column label="鐢ㄦ埛鏄电О" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
+ <el-table-column label="閮ㄩ棬" align="center" key="deptNames" prop="deptNames" v-if="columns[3].visible" :show-overflow-tooltip="true" />
+ <el-table-column label="鎵嬫満鍙风爜" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
+ <el-table-column label="鐘舵��" align="center" key="status" v-if="columns[5].visible">
+ <template #default="scope">
+ <el-switch
+ v-model="scope.row.status"
+ active-value="0"
+ inactive-value="1"
+ @change="handleStatusChange(scope.row)"
+ ></el-switch>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" v-if="columns[6].visible" width="160">
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.createTime) }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" align="center" width="150" class-name="small-padding fixed-width">
+ <template #default="scope">
+ <el-tooltip content="淇敼" placement="top" v-if="scope.row.userId !== 1">
+ <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
+ </el-tooltip>
+ <el-tooltip content="鍒犻櫎" placement="top" v-if="scope.row.userId !== 1">
+ <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']"></el-button>
+ </el-tooltip>
+ <el-tooltip content="閲嶇疆瀵嗙爜" placement="top" v-if="scope.row.userId !== 1">
+ <el-button link type="primary" icon="Key" @click="handleResetPwd(scope.row)" v-hasPermi="['system:user:resetPwd']"></el-button>
+ </el-tooltip>
+ <el-tooltip content="鍒嗛厤瑙掕壊" placement="top" v-if="scope.row.userId !== 1">
+ <el-button link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+ </el-col>
+ </pane>
+ </splitpanes>
+ </el-row>
+
+ <!-- 娣诲姞鎴栦慨鏀圭敤鎴烽厤缃璇濇 -->
+ <el-dialog :title="title" v-model="open" width="600px" append-to-body>
+ <el-form :model="form" :rules="rules" ref="userRef" label-width="80px">
+ <el-row>
+ <el-col :span="12">
+ <el-form-item v-if="form.userId == undefined" label="鐧诲綍璐﹀彿" prop="userName">
+ <el-input v-model="form.userName" placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" maxlength="30" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item v-if="form.userId == undefined" label="鐢ㄦ埛瀵嗙爜" prop="password">
+ <el-input v-model="form.password" placeholder="璇疯緭鍏ョ敤鎴峰瘑鐮�" type="password" maxlength="20" show-password />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName">
+ <el-input v-model="form.nickName" placeholder="璇疯緭鍏ョ敤鎴锋樀绉�" maxlength="30" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+ <el-tree-select v-model="form.deptId" :data="enabledDeptOptions" :props="{ value: 'id', label: 'label', children: 'children' }" value-key="id" placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" check-strictly />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="宀椾綅" prop="postIds">
+ <el-select v-model="form.postIds" multiple placeholder="璇烽�夋嫨">
+ <el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" :disabled="item.status == 1"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瑙掕壊" prop="roleIds">
+ <el-select v-model="form.roleIds" multiple placeholder="璇烽�夋嫨">
+ <el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+ <el-input v-model="form.phonenumber" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" maxlength="11" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閭" prop="email">
+ <el-input v-model="form.email" placeholder="璇疯緭鍏ラ偖绠�" maxlength="50" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鐢ㄦ埛鎬у埆">
+ <el-select v-model="form.sex" placeholder="璇烽�夋嫨">
+ <el-option v-for="dict in sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐘舵��">
+ <el-radio-group v-model="form.status">
+ <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row>
+ <el-col :span="24">
+ <el-form-item label="澶囨敞">
+ <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+ </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="cancel">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+
+ <!-- 鐢ㄦ埛瀵煎叆瀵硅瘽妗� -->
+ <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
+ <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :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">
+ <div class="el-upload__tip">
+ <el-checkbox v-model="upload.updateSupport" />鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ </div>
+ <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 name="User">
+import { getToken } from "@/utils/auth"
+import useAppStore from '@/store/modules/app'
+import { changeUserStatus, listUser, resetUserPwd, delUser, getUser, updateUser, addUser, deptTreeSelect } from "@/api/system/user"
+import { Splitpanes, Pane } from "splitpanes"
+import "splitpanes/dist/splitpanes.css"
+
+const router = useRouter()
+const appStore = useAppStore()
+const { proxy } = getCurrentInstance()
+const { sys_normal_disable, sys_user_sex } = proxy.useDict("sys_normal_disable", "sys_user_sex")
+
+const userList = ref([])
+const open = ref(false)
+const loading = ref(true)
+const showSearch = ref(true)
+const ids = ref([])
+const single = ref(true)
+const multiple = ref(true)
+const total = ref(0)
+const title = ref("")
+const dateRange = ref([])
+const deptNames = ref("")
+const deptOptions = ref(undefined)
+const enabledDeptOptions = ref(undefined)
+const initPassword = ref(undefined)
+const postOptions = ref([])
+const roleOptions = ref([])
+/*** 鐢ㄦ埛瀵煎叆鍙傛暟 */
+const upload = reactive({
+ // 鏄惁鏄剧ず寮瑰嚭灞傦紙鐢ㄦ埛瀵煎叆锛�
+ open: false,
+ // 寮瑰嚭灞傛爣棰橈紙鐢ㄦ埛瀵煎叆锛�
+ title: "",
+ // 鏄惁绂佺敤涓婁紶
+ isUploading: false,
+ // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹�
+ updateSupport: 0,
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/system/user/importData"
+})
+// 鍒楁樉闅愪俊鎭�
+const columns = ref([
+ { key: 0, label: `鐢ㄦ埛缂栧彿`, visible: true },
+ { key: 1, label: `鐧诲綍璐﹀彿`, visible: true },
+ { key: 2, label: `鐢ㄦ埛鏄电О`, visible: true },
+ { key: 3, label: `閮ㄩ棬`, visible: true },
+ { key: 4, label: `鎵嬫満鍙风爜`, visible: true },
+ { key: 5, label: `鐘舵�乣, visible: true },
+ { key: 6, label: `鍒涘缓鏃堕棿`, visible: true }
+])
+
+const data = reactive({
+ form: {},
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ userName: undefined,
+ phonenumber: undefined,
+ status: undefined,
+ deptId: undefined
+ },
+ rules: {
+ userName: [{ required: true, message: "鐢ㄦ埛鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }, { min: 2, max: 20, message: "鐢ㄦ埛鍚嶇О闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿", trigger: "blur" }],
+ nickName: [{ required: true, message: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", trigger: "blur" }],
+ password: [{ required: true, message: "鐢ㄦ埛瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" }, { min: 5, max: 20, message: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > \" ' \\\ |", trigger: "blur" }],
+ email: [{ type: "email", message: "璇疯緭鍏ユ纭殑閭鍦板潃", trigger: ["blur", "change"] }],
+ phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", trigger: "blur" }],
+ deptId: [{ required: true, message: "褰掑睘閮ㄩ棬涓嶈兘涓虹┖", trigger: "change" }],
+ postIds: [{ required: true, message: "宀椾綅涓嶈兘涓虹┖", trigger: "change" }],
+ roleIds: [{ required: true, message: "瑙掕壊涓嶈兘涓虹┖", trigger: "change" }]
+ }
+})
+
+const { queryParams, form, rules } = toRefs(data)
+
+/** 閫氳繃鏉′欢杩囨护鑺傜偣 */
+const filterNode = (value, data) => {
+ if (!value) return true
+ return data.label.indexOf(value) !== -1
+}
+
+/** 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲 */
+watch(deptNames, val => {
+ proxy.$refs["deptTreeRef"].filter(val)
+})
+
+/** 鏌ヨ鐢ㄦ埛鍒楄〃 */
+function getList() {
+ loading.value = true
+ listUser(proxy.addDateRange(queryParams.value, dateRange.value)).then(res => {
+ loading.value = false
+ userList.value = res.rows
+ total.value = res.total
+ })
+}
+
+/** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */
+function getDeptTree() {
+ deptTreeSelect().then(response => {
+ deptOptions.value = response.data
+ enabledDeptOptions.value = filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
+ })
+}
+
+/** 杩囨护绂佺敤鐨勯儴闂� */
+function filterDisabledDept(deptList) {
+ return deptList.filter(dept => {
+ if (dept.disabled) {
+ return false
+ }
+ if (dept.children && dept.children.length) {
+ dept.children = filterDisabledDept(dept.children)
+ }
+ return true
+ })
+}
+
+/** 鑺傜偣鍗曞嚮浜嬩欢 */
+function handleNodeClick(data) {
+ queryParams.value.deptId = data.id
+ handleQuery()
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+ queryParams.value.pageNum = 1
+ getList()
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+ dateRange.value = []
+ proxy.resetForm("queryRef")
+ queryParams.value.deptId = undefined
+ proxy.$refs.deptTreeRef.setCurrentKey(null)
+ handleQuery()
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+ const userIds = row.userId || ids.value
+ proxy.$modal.confirm('鏄惁纭鍒犻櫎鐢ㄦ埛缂栧彿涓�"' + userIds + '"鐨勬暟鎹」锛�').then(function () {
+ return delUser(userIds)
+ }).then(() => {
+ getList()
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
+ }).catch(() => {})
+}
+
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+ proxy.download("system/user/export", {
+ ...queryParams.value,
+ },`user_${new Date().getTime()}.xlsx`)
+}
+
+/** 鐢ㄦ埛鐘舵�佷慨鏀� */
+function handleStatusChange(row) {
+ let text = row.status === "0" ? "鍚敤" : "鍋滅敤"
+ proxy.$modal.confirm('纭瑕�"' + text + '""' + row.userName + '"鐢ㄦ埛鍚�?').then(function () {
+ return changeUserStatus(row.userId, row.status)
+ }).then(() => {
+ proxy.$modal.msgSuccess(text + "鎴愬姛")
+ }).catch(function () {
+ row.status = row.status === "0" ? "1" : "0"
+ })
+}
+
+/** 鏇村鎿嶄綔 */
+function handleCommand(command, row) {
+ switch (command) {
+ case "handleResetPwd":
+ handleResetPwd(row)
+ break
+ case "handleAuthRole":
+ handleAuthRole(row)
+ break
+ default:
+ break
+ }
+}
+
+/** 璺宠浆瑙掕壊鍒嗛厤 */
+function handleAuthRole(row) {
+ const userId = row.userId
+ router.push("/system/user-auth/role/" + userId)
+}
+
+/** 閲嶇疆瀵嗙爜鎸夐挳鎿嶄綔 */
+function handleResetPwd(row) {
+ proxy.$prompt('璇疯緭鍏�"' + row.userName + '"鐨勬柊瀵嗙爜', "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ closeOnClickModal: false,
+ inputPattern: /^.{5,20}$/,
+ inputErrorMessage: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿",
+ inputValidator: (value) => {
+ if (/<|>|"|'|\||\\/.test(value)) {
+ return "涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > \" ' \\\ |"
+ }
+ },
+ }).then(({ value }) => {
+ resetUserPwd(row.userId, value).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛锛屾柊瀵嗙爜鏄細" + value)
+ })
+ }).catch(() => {})
+}
+
+/** 閫夋嫨鏉℃暟 */
+function handleSelectionChange(selection) {
+ ids.value = selection.map(item => item.userId)
+ single.value = selection.length != 1
+ multiple.value = !selection.length
+}
+
+/** 瀵煎叆鎸夐挳鎿嶄綔 */
+function handleImport() {
+ upload.title = "鐢ㄦ埛瀵煎叆"
+ upload.open = true
+}
+
+/** 涓嬭浇妯℃澘鎿嶄綔 */
+function importTemplate() {
+ proxy.download("system/user/importTemplate", {
+ }, `user_template_${new Date().getTime()}.xlsx`)
+}
+
+/**鏂囦欢涓婁紶涓鐞� */
+const handleFileUploadProgress = (event, file, fileList) => {
+ upload.isUploading = true
+}
+
+/** 鏂囦欢涓婁紶鎴愬姛澶勭悊 */
+const handleFileSuccess = (response, file, fileList) => {
+ upload.open = false
+ upload.isUploading = false
+ proxy.$refs["uploadRef"].handleRemove(file)
+ proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "瀵煎叆缁撴灉", { dangerouslyUseHTMLString: true })
+ getList()
+}
+
+/** 鎻愪氦涓婁紶鏂囦欢 */
+function submitFileForm() {
+ proxy.$refs["uploadRef"].submit()
+}
+
+/** 閲嶇疆鎿嶄綔琛ㄥ崟 */
+function reset() {
+ form.value = {
+ userId: undefined,
+ deptId: undefined,
+ userName: undefined,
+ nickName: undefined,
+ password: undefined,
+ phonenumber: undefined,
+ email: undefined,
+ sex: undefined,
+ status: "0",
+ remark: undefined,
+ postIds: [],
+ roleIds: []
+ }
+ proxy.resetForm("userRef")
+}
+
+/** 鍙栨秷鎸夐挳 */
+function cancel() {
+ open.value = false
+ reset()
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd() {
+ reset()
+ getUser().then(response => {
+ postOptions.value = response.posts
+ roleOptions.value = response.roles
+ open.value = true
+ title.value = "娣诲姞鐢ㄦ埛"
+ form.value.password = initPassword.value
+ })
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+ reset()
+ const userId = row.userId || ids.value
+ getUser(userId).then(response => {
+ form.value = response.data
+ postOptions.value = response.posts
+ roleOptions.value = response.roles
+ form.value.postIds = response.postIds
+ form.value.roleIds = response.roleIds
+ open.value = true
+ title.value = "淇敼鐢ㄦ埛"
+ form.password = ""
+ })
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+ proxy.$refs["userRef"].validate(valid => {
+ if (valid) {
+ // 褰掑睘閮ㄩ棬铏界劧鏄崟閫夛紝浣嗗悗绔渶瑕佷紶鏁扮粍瀛楁 deptIds
+ const payload = {
+ ...form.value,
+ deptIds: form.value.deptId ? [form.value.deptId] : []
+ }
+ if (form.value.userId != undefined) {
+ updateUser(payload).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ open.value = false
+ getList()
+ })
+ } else {
+ addUser(payload).then(response => {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛")
+ open.value = false
+ getList()
+ })
+ }
+ }
+ })
+}
+
+getDeptTree()
+getList()
+</script>
+
diff --git a/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/index.vue b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/index.vue
new file mode 100644
index 0000000..719a028
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/index.vue
@@ -0,0 +1,87 @@
+<template>
+ <div class="app-container">
+ <el-row :gutter="20">
+ <el-col :span="6" :xs="24">
+ <el-card class="box-card">
+ <template v-slot:header>
+ <div class="clearfix">
+ <span>涓汉淇℃伅</span>
+ </div>
+ </template>
+ <div>
+ <div class="text-center">
+ <userAvatar />
+ </div>
+ <ul class="list-group list-group-striped">
+ <li class="list-group-item">
+ <svg-icon icon-class="user" />鐢ㄦ埛鍚嶇О
+ <div class="pull-right">{{ state.user.userName }}</div>
+ </li>
+ <li class="list-group-item">
+ <svg-icon icon-class="phone" />鎵嬫満鍙风爜
+ <div class="pull-right">{{ state.user.phonenumber }}</div>
+ </li>
+ <li class="list-group-item">
+ <svg-icon icon-class="email" />鐢ㄦ埛閭
+ <div class="pull-right">{{ state.user.email }}</div>
+ </li>
+ <li class="list-group-item">
+ <svg-icon icon-class="tree" />鎵�灞為儴闂�
+ <div class="pull-right" v-if="state.user.dept">{{ state.user.dept.deptName }} / {{ state.postGroup }}</div>
+ </li>
+ <li class="list-group-item">
+ <svg-icon icon-class="peoples" />鎵�灞炶鑹�
+ <div class="pull-right">{{ state.roleGroup }}</div>
+ </li>
+ <li class="list-group-item">
+ <svg-icon icon-class="date" />鍒涘缓鏃ユ湡
+ <div class="pull-right">{{ state.user.createTime }}</div>
+ </li>
+ </ul>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="18" :xs="24">
+ <el-card>
+ <template v-slot:header>
+ <div class="clearfix">
+ <span>鍩烘湰璧勬枡</span>
+ </div>
+ </template>
+ <el-tabs v-model="activeTab">
+ <el-tab-pane label="鍩烘湰璧勬枡" name="userinfo">
+ <userInfo :user="state.user" />
+ </el-tab-pane>
+ <el-tab-pane label="淇敼瀵嗙爜" name="resetPwd">
+ <resetPwd />
+ </el-tab-pane>
+ </el-tabs>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+</template>
+
+<script setup name="Profile">
+import userAvatar from "./userAvatar"
+import userInfo from "./userInfo"
+import resetPwd from "./resetPwd"
+import { getUserProfile } from "@/api/system/user"
+
+const activeTab = ref("userinfo")
+const state = reactive({
+ user: {},
+ roleGroup: {},
+ postGroup: {}
+})
+
+function getUser() {
+ getUserProfile().then(response => {
+ state.user = response.data
+ state.roleGroup = response.roleGroup
+ state.postGroup = response.postGroup
+ })
+}
+
+getUser()
+</script>
diff --git a/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/resetPwd.vue b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/resetPwd.vue
new file mode 100644
index 0000000..73c6b18
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/resetPwd.vue
@@ -0,0 +1,59 @@
+<template>
+ <el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px">
+ <el-form-item label="鏃у瘑鐮�" prop="oldPassword">
+ <el-input v-model="user.oldPassword" placeholder="璇疯緭鍏ユ棫瀵嗙爜" type="password" show-password />
+ </el-form-item>
+ <el-form-item label="鏂板瘑鐮�" prop="newPassword">
+ <el-input v-model="user.newPassword" placeholder="璇疯緭鍏ユ柊瀵嗙爜" type="password" show-password />
+ </el-form-item>
+ <el-form-item label="纭瀵嗙爜" prop="confirmPassword">
+ <el-input v-model="user.confirmPassword" placeholder="璇风‘璁ゆ柊瀵嗙爜" type="password" show-password/>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="submit">淇濆瓨</el-button>
+ <el-button type="danger" @click="close">鍏抽棴</el-button>
+ </el-form-item>
+ </el-form>
+</template>
+
+<script setup>
+import { updateUserPwd } from "@/api/system/user"
+
+const { proxy } = getCurrentInstance()
+
+const user = reactive({
+ oldPassword: undefined,
+ newPassword: undefined,
+ confirmPassword: undefined
+})
+
+const equalToPassword = (rule, value, callback) => {
+ if (user.newPassword !== value) {
+ callback(new Error("涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�"))
+ } else {
+ callback()
+ }
+}
+
+const rules = ref({
+ oldPassword: [{ required: true, message: "鏃у瘑鐮佷笉鑳戒负绌�", trigger: "blur" }],
+ newPassword: [{ required: true, message: "鏂板瘑鐮佷笉鑳戒负绌�", trigger: "blur" }, { min: 6, max: 20, message: "闀垮害鍦� 6 鍒� 20 涓瓧绗�", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > \" ' \\\ |", trigger: "blur" }],
+ confirmPassword: [{ required: true, message: "纭瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" }, { required: true, validator: equalToPassword, trigger: "blur" }]
+})
+
+/** 鎻愪氦鎸夐挳 */
+function submit() {
+ proxy.$refs.pwdRef.validate(valid => {
+ if (valid) {
+ updateUserPwd(user.oldPassword, user.newPassword).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ })
+ }
+ })
+}
+
+/** 鍏抽棴鎸夐挳 */
+function close() {
+ proxy.$tab.closePage()
+}
+</script>
diff --git a/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userAvatar.vue b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userAvatar.vue
new file mode 100644
index 0000000..2594543
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userAvatar.vue
@@ -0,0 +1,168 @@
+<template>
+ <div class="user-info-head" @click="editCropper()">
+ <img :src="options.img" title="鐐瑰嚮涓婁紶澶村儚" class="img-circle img-lg" />
+ <el-dialog :title="title" v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
+ <el-row>
+ <el-col :xs="24" :md="12" :style="{ height: '350px' }">
+ <vue-cropper ref="cropper" :img="options.img" :info="true" :autoCrop="options.autoCrop"
+ :autoCropWidth="options.autoCropWidth" :autoCropHeight="options.autoCropHeight" :fixedBox="options.fixedBox"
+ :outputType="options.outputType" @realTime="realTime" v-if="visible" />
+ </el-col>
+ <el-col :xs="24" :md="12" :style="{ height: '350px' }">
+ <div class="avatar-upload-preview">
+ <img :src="options.previews.url" :style="options.previews.img" />
+ </div>
+ </el-col>
+ </el-row>
+ <br />
+ <el-row>
+ <el-col :lg="2" :md="2">
+ <el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
+ <el-button>
+ 閫夋嫨
+ <el-icon class="el-icon--right">
+ <Upload />
+ </el-icon>
+ </el-button>
+ </el-upload>
+ </el-col>
+ <el-col :lg="{ span: 1, offset: 2 }" :md="2">
+ <el-button icon="Plus" @click="changeScale(1)"></el-button>
+ </el-col>
+ <el-col :lg="{ span: 1, offset: 1 }" :md="2">
+ <el-button icon="Minus" @click="changeScale(-1)"></el-button>
+ </el-col>
+ <el-col :lg="{ span: 1, offset: 1 }" :md="2">
+ <el-button icon="RefreshLeft" @click="rotateLeft()"></el-button>
+ </el-col>
+ <el-col :lg="{ span: 1, offset: 1 }" :md="2">
+ <el-button icon="RefreshRight" @click="rotateRight()"></el-button>
+ </el-col>
+ <el-col :lg="{ span: 2, offset: 6 }" :md="2">
+ <el-button type="primary" @click="uploadImg()">鎻� 浜�</el-button>
+ </el-col>
+ </el-row>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import "vue-cropper/dist/index.css"
+import { VueCropper } from "vue-cropper"
+import { uploadAvatar } from "@/api/system/user"
+import useUserStore from "@/store/modules/user"
+
+const userStore = useUserStore()
+const { proxy } = getCurrentInstance()
+
+const open = ref(false)
+const visible = ref(false)
+const title = ref("淇敼澶村儚")
+
+//鍥剧墖瑁佸壀鏁版嵁
+const options = reactive({
+ img: userStore.avatar, // 瑁佸壀鍥剧墖鐨勫湴鍧�
+ autoCrop: true, // 鏄惁榛樿鐢熸垚鎴浘妗�
+ autoCropWidth: 200, // 榛樿鐢熸垚鎴浘妗嗗搴�
+ autoCropHeight: 200, // 榛樿鐢熸垚鎴浘妗嗛珮搴�
+ fixedBox: true, // 鍥哄畾鎴浘妗嗗ぇ灏� 涓嶅厑璁告敼鍙�
+ outputType: "png", // 榛樿鐢熸垚鎴浘涓篜NG鏍煎紡
+ filename: 'avatar', // 鏂囦欢鍚嶇О
+ previews: {} //棰勮鏁版嵁
+})
+
+/** 缂栬緫澶村儚 */
+function editCropper() {
+ open.value = true
+}
+
+/** 鎵撳紑寮瑰嚭灞傜粨鏉熸椂鐨勫洖璋� */
+function modalOpened() {
+ visible.value = true
+}
+
+/** 瑕嗙洊榛樿涓婁紶琛屼负 */
+function requestUpload() { }
+
+/** 鍚戝乏鏃嬭浆 */
+function rotateLeft() {
+ proxy.$refs.cropper.rotateLeft()
+}
+
+/** 鍚戝彸鏃嬭浆 */
+function rotateRight() {
+ proxy.$refs.cropper.rotateRight()
+}
+
+/** 鍥剧墖缂╂斁 */
+function changeScale(num) {
+ num = num || 1
+ proxy.$refs.cropper.changeScale(num)
+}
+
+/** 涓婁紶棰勫鐞� */
+function beforeUpload(file) {
+ if (file.type.indexOf("image/") == -1) {
+ proxy.$modal.msgError("鏂囦欢鏍煎紡閿欒锛岃涓婁紶鍥剧墖绫诲瀷,濡傦細JPG锛孭NG鍚庣紑鐨勬枃浠躲��")
+ } else {
+ const reader = new FileReader()
+ reader.readAsDataURL(file)
+ reader.onload = () => {
+ options.img = reader.result
+ options.filename = file.name
+ }
+ }
+}
+
+/** 涓婁紶鍥剧墖 */
+function uploadImg() {
+ proxy.$refs.cropper.getCropBlob(data => {
+ let formData = new FormData()
+ formData.append("avatarfile", data, options.filename)
+ uploadAvatar(formData).then(response => {
+ open.value = false
+ options.img = import.meta.env.VITE_APP_BASE_API + '/profile/' + response.imgUrl
+ userStore.avatar = options.img
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ visible.value = false
+ })
+ })
+}
+
+/** 瀹炴椂棰勮 */
+function realTime(data) {
+ options.previews = data
+}
+
+/** 鍏抽棴绐楀彛 */
+function closeDialog() {
+ options.img = userStore.avatar
+ options.visible = false
+}
+</script>
+
+<style lang='scss' scoped>
+.user-info-head {
+ position: relative;
+ display: inline-block;
+ height: 120px;
+}
+
+.user-info-head:hover:after {
+ content: "+";
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ color: #eee;
+ background: rgba(0, 0, 0, 0.5);
+ font-size: 24px;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ cursor: pointer;
+ line-height: 110px;
+ border-radius: 50%;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userInfo.vue b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userInfo.vue
new file mode 100644
index 0000000..5099ffa
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysAdmin/user-manage/profile/userInfo.vue
@@ -0,0 +1,67 @@
+<template>
+ <el-form ref="userRef" :model="form" :rules="rules" label-width="80px">
+ <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName">
+ <el-input v-model="form.nickName" maxlength="30" />
+ </el-form-item>
+ <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber">
+ <el-input v-model="form.phonenumber" maxlength="11" />
+ </el-form-item>
+ <el-form-item label="閭" prop="email">
+ <el-input v-model="form.email" maxlength="50" />
+ </el-form-item>
+ <el-form-item label="鎬у埆">
+ <el-radio-group v-model="form.sex">
+ <el-radio value="0">鐢�</el-radio>
+ <el-radio value="1">濂�</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="submit">淇濆瓨</el-button>
+ <el-button type="danger" @click="close">鍏抽棴</el-button>
+ </el-form-item>
+ </el-form>
+</template>
+
+<script setup>
+import { updateUserProfile } from "@/api/system/user"
+
+const props = defineProps({
+ user: {
+ type: Object
+ }
+})
+
+const { proxy } = getCurrentInstance()
+
+const form = ref({})
+const rules = ref({
+ nickName: [{ required: true, message: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", trigger: "blur" }],
+ email: [{ required: true, message: "閭鍦板潃涓嶈兘涓虹┖", trigger: "blur" }, { type: "email", message: "璇疯緭鍏ユ纭殑閭鍦板潃", trigger: ["blur", "change"] }],
+ phonenumber: [{ required: true, message: "鎵嬫満鍙风爜涓嶈兘涓虹┖", trigger: "blur" }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", trigger: "blur" }],
+})
+
+/** 鎻愪氦鎸夐挳 */
+function submit() {
+ proxy.$refs.userRef.validate(valid => {
+ if (valid) {
+ updateUserProfile(form.value).then(response => {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛")
+ props.user.phonenumber = form.value.phonenumber
+ props.user.email = form.value.email
+ })
+ }
+ })
+}
+
+/** 鍏抽棴鎸夐挳 */
+function close() {
+ proxy.$tab.closePage()
+}
+
+// 鍥炴樉褰撳墠鐧诲綍鐢ㄦ埛淇℃伅
+watch(() => props.user, user => {
+ if (user) {
+ form.value = { nickName: user.nickName, phonenumber: user.phonenumber, email: user.email, sex: user.sex }
+ }
+},{ immediate: true })
+</script>
diff --git a/src/views/officeProcessAutomation/SysMonitor/cache-monitor/index.vue b/src/views/officeProcessAutomation/SysMonitor/cache-monitor/index.vue
new file mode 100644
index 0000000..d5a90b0
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysMonitor/cache-monitor/index.vue
@@ -0,0 +1,134 @@
+<!--OA妯″潡锛氱紦瀛樼洃鎺�-->
+<template>
+ <div class="app-container">
+ <el-row :gutter="10">
+ <el-col :span="24" class="card-box">
+ <el-card>
+ <template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">鍩烘湰淇℃伅</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <table cellspacing="0" style="width: 100%">
+ <tbody>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">Redis鐗堟湰</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">杩愯妯″紡</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "鍗曟満" : "闆嗙兢" }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">绔彛</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">瀹㈡埛绔暟</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">杩愯鏃堕棿(澶�)</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">浣跨敤鍐呭瓨</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">浣跨敤CPU</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">鍐呭瓨閰嶇疆</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">AOF鏄惁寮�鍚�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "鍚�" : "鏄�" }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">RDB鏄惁鎴愬姛</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">Key鏁伴噺</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">缃戠粶鍏ュ彛/鍑哄彛</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="12" class="card-box">
+ <el-card>
+ <template #header><PieChart style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">鍛戒护缁熻</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <div ref="commandstats" style="height: 420px" />
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="12" class="card-box">
+ <el-card>
+ <template #header><Odometer style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">鍐呭瓨淇℃伅</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <div ref="usedmemory" style="height: 420px" />
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+</template>
+
+<script setup name="Cache">
+import { getCache } from '@/api/monitor/cache'
+import * as echarts from 'echarts'
+
+const cache = ref([])
+const commandstats = ref(null)
+const usedmemory = ref(null)
+const { proxy } = getCurrentInstance()
+
+function getList() {
+ proxy.$modal.loading("姝e湪鍔犺浇缂撳瓨鐩戞帶鏁版嵁锛岃绋嶅�欙紒")
+ getCache().then(response => {
+ proxy.$modal.closeLoading()
+ cache.value = response.data
+
+ const commandstatsIntance = echarts.init(commandstats.value, "macarons")
+ commandstatsIntance.setOption({
+ tooltip: {
+ trigger: "item",
+ formatter: "{a} <br/>{b} : {c} ({d}%)"
+ },
+ series: [
+ {
+ name: "鍛戒护",
+ type: "pie",
+ roseType: "radius",
+ radius: [15, 95],
+ center: ["50%", "38%"],
+ data: response.data.commandStats,
+ animationEasing: "cubicInOut",
+ animationDuration: 1000
+ }
+ ]
+ })
+ const usedmemoryInstance = echarts.init(usedmemory.value, "macarons")
+ usedmemoryInstance.setOption({
+ tooltip: {
+ formatter: "{b} <br/>{a} : " + cache.value.info.used_memory_human
+ },
+ series: [
+ {
+ name: "宄板��",
+ type: "gauge",
+ min: 0,
+ max: 1000,
+ detail: {
+ formatter: cache.value.info.used_memory_human
+ },
+ data: [
+ {
+ value: parseFloat(cache.value.info.used_memory_human),
+ name: "鍐呭瓨娑堣��"
+ }
+ ]
+ }
+ ]
+ })
+ window.addEventListener("resize", () => {
+ commandstatsIntance.resize()
+ usedmemoryInstance.resize()
+ })
+ })
+}
+
+getList()
+</script>
+
diff --git a/src/views/officeProcessAutomation/SysMonitor/data-monitor/index.vue b/src/views/officeProcessAutomation/SysMonitor/data-monitor/index.vue
new file mode 100644
index 0000000..fe13414
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysMonitor/data-monitor/index.vue
@@ -0,0 +1,14 @@
+<!--OA妯″潡锛氭暟鎹洃鎺�-->
+<template>
+ <div>
+ <i-frame v-model:src="url"></i-frame>
+ </div>
+</template>
+
+<script setup>
+import iFrame from '@/components/iFrame'
+
+import { ref } from 'vue'
+
+const url = ref(import.meta.env.VITE_APP_BASE_API + '/druid/login.html')
+</script>
diff --git a/src/views/officeProcessAutomation/SysMonitor/server-monitor/index.vue b/src/views/officeProcessAutomation/SysMonitor/server-monitor/index.vue
new file mode 100644
index 0000000..053d55e
--- /dev/null
+++ b/src/views/officeProcessAutomation/SysMonitor/server-monitor/index.vue
@@ -0,0 +1,191 @@
+<!--OA妯″潡锛氭湇鍔″櫒鐩戞帶-->
+<template>
+ <div class="app-container">
+ <el-row :gutter="10">
+ <el-col :span="12" class="card-box">
+ <el-card>
+ <template #header><Cpu style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">CPU</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <table cellspacing="0" style="width: 100%;">
+ <thead>
+ <tr>
+ <th class="el-table__cell is-leaf"><div class="cell">灞炴��</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">鍊�</div></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">鏍稿績鏁�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.cpuNum }}</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">鐢ㄦ埛浣跨敤鐜�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.used }}%</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">绯荤粺浣跨敤鐜�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.sys }}%</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">褰撳墠绌洪棽鐜�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.free }}%</div></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="12" class="card-box">
+ <el-card>
+ <template #header><Tickets style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">鍐呭瓨</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <table cellspacing="0" style="width: 100%;">
+ <thead>
+ <tr>
+ <th class="el-table__cell is-leaf"><div class="cell">灞炴��</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">鍐呭瓨</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">JVM</div></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">鎬诲唴瀛�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.total }}G</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.total }}M</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">宸茬敤鍐呭瓨</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.used}}G</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.used}}M</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">鍓╀綑鍐呭瓨</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.free }}G</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.free }}M</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">浣跨敤鐜�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem" :class="{'text-danger': server.mem.usage > 80}">{{ server.mem.usage }}%</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm" :class="{'text-danger': server.jvm.usage > 80}">{{ server.jvm.usage }}%</div></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="24" class="card-box">
+ <el-card>
+ <template #header><Monitor style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">鏈嶅姟鍣ㄤ俊鎭�</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <table cellspacing="0" style="width: 100%;">
+ <tbody>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">鏈嶅姟鍣ㄥ悕绉�</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerName }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">鎿嶄綔绯荤粺</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osName }}</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">鏈嶅姟鍣↖P</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerIp }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">绯荤粺鏋舵瀯</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osArch }}</div></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="24" class="card-box">
+ <el-card>
+ <template #header><CoffeeCup style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">Java铏氭嫙鏈轰俊鎭�</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <table cellspacing="0" style="width: 100%;table-layout:fixed;">
+ <tbody>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">Java鍚嶇О</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.name }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">Java鐗堟湰</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.version }}</div></td>
+ </tr>
+ <tr>
+ <td class="el-table__cell is-leaf"><div class="cell">鍚姩鏃堕棿</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.startTime }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">杩愯鏃堕暱</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.runTime }}</div></td>
+ </tr>
+ <tr>
+ <td colspan="1" class="el-table__cell is-leaf"><div class="cell">瀹夎璺緞</div></td>
+ <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.home }}</div></td>
+ </tr>
+ <tr>
+ <td colspan="1" class="el-table__cell is-leaf"><div class="cell">椤圭洰璺緞</div></td>
+ <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td>
+ </tr>
+ <tr>
+ <td colspan="1" class="el-table__cell is-leaf"><div class="cell">杩愯鍙傛暟</div></td>
+ <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.inputArgs }}</div></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="24" class="card-box">
+ <el-card>
+ <template #header><MessageBox style="width: 1em; height: 1em; vertical-align: middle;" /> <span style="vertical-align: middle;">纾佺洏鐘舵��</span></template>
+ <div class="el-table el-table--enable-row-hover el-table--medium">
+ <table cellspacing="0" style="width: 100%;">
+ <thead>
+ <tr>
+ <th class="el-table__cell el-table__cell is-leaf"><div class="cell">鐩樼璺緞</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">鏂囦欢绯荤粺</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">鐩樼绫诲瀷</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">鎬诲ぇ灏�</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">鍙敤澶у皬</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">宸茬敤澶у皬</div></th>
+ <th class="el-table__cell is-leaf"><div class="cell">宸茬敤鐧惧垎姣�</div></th>
+ </tr>
+ </thead>
+ <tbody v-if="server.sysFiles">
+ <tr v-for="(sysFile, index) in server.sysFiles" :key="index">
+ <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.dirName }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.sysTypeName }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.typeName }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.total }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.free }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.used }}</div></td>
+ <td class="el-table__cell is-leaf"><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+</template>
+
+<script setup>
+import { getServer } from '@/api/monitor/server'
+import {onMounted} from "vue";
+
+const server = ref([])
+const { proxy } = getCurrentInstance()
+
+function getList() {
+ proxy.$modal.loading("姝e湪鍔犺浇鏈嶅姟鐩戞帶鏁版嵁锛岃绋嶅�欙紒")
+ getServer().then(response => {
+ server.value = response.data
+ proxy.$modal.closeLoading()
+ })
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
diff --git a/src/views/personnelManagement/contractManagement/components/formDia.vue b/src/views/personnelManagement/contractManagement/components/formDia.vue
index 54b2ef9..3db1bee 100644
--- a/src/views/personnelManagement/contractManagement/components/formDia.vue
+++ b/src/views/personnelManagement/contractManagement/components/formDia.vue
@@ -1,96 +1,93 @@
<template>
<div>
- <el-dialog
- v-model="dialogFormVisible"
- title="璇︽儏"
- width="70%"
- @close="closeDia"
- >
- <PIMTable
- rowKey="id"
- :column="tableColumn"
- :tableData="tableData"
- :tableLoading="tableLoading"
- height="600"
- ></PIMTable>
+ <el-dialog v-model="dialogFormVisible"
+ title="璇︽儏"
+ width="70%"
+ @close="closeDia">
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :tableLoading="tableLoading"
+ height="600"></PIMTable>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
</el-dialog>
- <Files ref="filesDia"></Files>
+ <FileList v-if="fileDialogVisible"
+ v-model:visible="fileDialogVisible"
+ :record-type="'staff_contract'"
+ :record-id="recordId" />
</div>
</template>
<script setup>
-import {ref} from "vue";
-import {findStaffContractListPage} from "@/api/personnelManagement/staffContract.js";
-const Files = defineAsyncComponent(() => import( "@/views/personnelManagement/contractManagement/filesDia.vue"));
-const { proxy } = getCurrentInstance()
-const emit = defineEmits(['close'])
-const filesDia = ref()
-const dialogFormVisible = ref(false);
-const operationType = ref('')
-const tableColumn = ref([
- {
- label: "鍚堝悓骞撮檺",
- prop: "contractTerm",
- },
- {
- label: "鍚堝悓寮�濮嬫棩鏈�",
- prop: "contractStartTime",
- },
- {
- label: "鍚堝悓缁撴潫鏃ユ湡",
- prop: "contractEndTime",
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: 'right',
- width: 120,
- operation: [
- {
- name: "涓婁紶闄勪欢",
- type: "text",
- clickFun: (row) => {
- filesDia.value.openDialog( row,'鍚堝悓')
+ import { ref, defineAsyncComponent, getCurrentInstance } from "vue";
+ import { findStaffContractListPage } from "@/api/personnelManagement/staffContract.js";
+ const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
+ );
+ const { proxy } = getCurrentInstance();
+ const emit = defineEmits(["close"]);
+ const fileDialogVisible = ref(false);
+ const recordId = ref(0);
+ const dialogFormVisible = ref(false);
+ const operationType = ref("");
+ const tableColumn = ref([
+ {
+ label: "鍚堝悓骞撮檺",
+ prop: "contractTerm",
+ },
+ {
+ label: "鍚堝悓寮�濮嬫棩鏈�",
+ prop: "contractStartTime",
+ },
+ {
+ label: "鍚堝悓缁撴潫鏃ユ湡",
+ prop: "contractEndTime",
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 120,
+ operation: [
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: row => {
+ recordId.value = row.id;
+ fileDialogVisible.value = true;
+ },
},
- }
- ],
- },
-]);
-const tableData = ref([]);
-const tableLoading = ref(false);
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const tableLoading = ref(false);
-// 鎵撳紑寮规
-const openDialog = (type, row) => {
- operationType.value = type;
- dialogFormVisible.value = true;
- if (operationType.value === 'edit') {
- findStaffContractListPage({staffOnJobId: row.id}).then(res => {
- tableData.value = res.data.records
- })
- }
-}
+ // 鎵撳紑寮规
+ const openDialog = (type, row) => {
+ operationType.value = type;
+ dialogFormVisible.value = true;
+ if (operationType.value === "edit") {
+ findStaffContractListPage({ staffOnJobId: row.id }).then(res => {
+ tableData.value = res.data.records;
+ });
+ }
+ };
-const openUploadFile = (row) => {
- filesDia.value.open = true
- filesDia.value.row = row
-}
-
-// 鍏抽棴寮规
-const closeDia = () => {
- dialogFormVisible.value = false;
- emit('close')
-};
-defineExpose({
- openDialog,
-});
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ dialogFormVisible.value = false;
+ emit("close");
+ };
+ defineExpose({
+ openDialog,
+ });
</script>
<style scoped>
-
</style>
\ No newline at end of file
diff --git a/src/views/personnelManagement/contractManagement/index.vue b/src/views/personnelManagement/contractManagement/index.vue
index 074b9ac..ae0087e 100644
--- a/src/views/personnelManagement/contractManagement/index.vue
+++ b/src/views/personnelManagement/contractManagement/index.vue
@@ -136,7 +136,7 @@
},
{
label: "宀椾綅",
- prop: "postJob",
+ prop: "postName",
},
{
label: "鐜颁綇鍧�",
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 9bbe87e..43203b2 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -40,8 +40,14 @@
</div>
<div class="table_list">
<div style="display: flex;justify-content: flex-end;margin-bottom: 20px;">
- <el-button type="primary" @click="openForm('add')">鏂板鍙拌处</el-button>
- <el-button type="primary" plain @click="handleImport">瀵煎叆</el-button>
+ <el-button type="success"
+ plain
+ @click="handleBatchGenerate">鎵归噺鐢熸垚鏁版嵁</el-button>
+ <el-button type="primary"
+ @click="openForm('add')">鏂板鍙拌处</el-button>
+ <el-button type="primary"
+ plain
+ @click="handleImport">瀵煎叆</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
<el-button type="danger" plain @click="handleDelete">鍒犻櫎
</el-button>
@@ -52,12 +58,23 @@
<el-table-column align="center" type="selection" width="55" />
<el-table-column type="expand">
<template #default="props">
- <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column label="浜у搧澶х被" prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
- <el-table-column label="鍗曚綅" prop="unit" />
- <el-table-column label="鍏ュ簱瀹℃牳鐘舵��" prop="stockInApprovalStatus" width="120">
+ <el-table :data="props.row.children"
+ border
+ show-summary
+ :summary-method="summarizeChildrenTable">
+ <el-table-column align="center"
+ label="搴忓彿"
+ type="index"
+ width="60" />
+ <el-table-column label="浜у搧澶х被"
+ prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="specificationModel" />
+ <el-table-column label="鍗曚綅"
+ prop="unit" />
+ <el-table-column label="鍏ュ簱瀹℃牳鐘舵��"
+ prop="stockInApprovalStatus"
+ width="120">
<template #default="scope">
<el-tag :type="getStockInApprovalStatusType(scope.row.stockInApprovalStatus)" size="small">
{{ scope.row.stockInApprovalStatus || '--' }}
@@ -370,133 +387,45 @@
</template>
<script setup>
-import FormDialog from "@/components/Dialog/FormDialog.vue";
-import FileListDialog from "@/components/Dialog/FileListDialog.vue";
-import Detail from "./detail.vue";
-import { getToken } from "@/utils/auth";
-import pagination from "@/components/PIMTable/Pagination.vue";
-import {
- ref,
- onMounted,
- reactive,
- toRefs,
- getCurrentInstance,
- nextTick,
-} from "vue";
-import { Search, Delete } from "@element-plus/icons-vue";
-import { ElMessageBox, ElMessage } from "element-plus";
-import { userListNoPage } from "@/api/system/user.js";
-import {
- addOrUpdateSalesLedgerProduct,
- delProduct,
- delLedgerFile,
- getProductInfoByContractNo,
-} from "@/api/salesManagement/salesLedger.js";
-import {
- addOrEditPurchase,
- addPurchaseTemplate,
- updatePurchaseTemplate,
- createPurchaseNo,
- delPurchase,
- getSalesNo,
- purchaseListPage,
- productList,
- getPurchaseById,
- getOptions,
- getPurchaseTemplateList,
- delPurchaseTemplate,
-} from "@/api/procurementManagement/procurementLedger.js";
-import useFormData from "@/hooks/useFormData.js";
-const FileList = defineAsyncComponent(() =>
- import("@/components/Dialog/FileList.vue")
-);
-
-const detailRef = ref(null);
-
-const { proxy } = getCurrentInstance();
-const { tax_rate } = proxy.useDict("tax_rate");
-const tableData = ref([]);
-const productData = ref([]);
-const selectedRows = ref([]);
-const productSelectedRows = ref([]);
-const modelOptions = ref([]);
-const userList = ref([]);
-const productOptions = ref([]);
-const salesContractList = ref([]);
-const supplierList = ref([]);
-const tableLoading = ref(false);
-const recordId = ref();
-const fileListDialogVisible = ref(false);
-const page = reactive({
- current: 1,
- size: 100,
-});
-const total = ref(0);
-const fileList = ref([]);
-import useUserStore from "@/store/modules/user";
-import { modelList, productTreeList } from "@/api/basicData/product.js";
-import dayjs from "dayjs";
-import FileUpload from "@/components/AttachmentUpload/file/index.vue";
-
-const userStore = useUserStore();
-
-// 鏄惁鏄剧ず閿�鍞悎鍚屽彿缁戝畾
-const showSalesContractBinding = false;
-
-// 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
-const approvalStatusText = {
- 1: "寰呭鏍�",
- 2: "瀹℃壒涓�",
- 3: "瀹℃壒閫氳繃",
- 4: "瀹℃壒澶辫触",
-};
-
-// 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
-const getApprovalStatusType = status => {
- const typeMap = {
- 1: "info", // 寰呭鏍� - 鐏拌壊
- 2: "warning", // 瀹℃壒涓� - 姗欒壊
- 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
- 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
- };
- return typeMap[status] || "";
-};
-
-// 鑾峰彇鍏ュ簱鐘舵�佹爣绛剧被鍨�
-const getStockInStatusType = status => {
- const typeMap = {
- "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
- "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
- "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
- };
- return typeMap[status] || "";
-};
-
-// 鑾峰彇鍏ュ簱瀹℃牳鐘舵�佹爣绛剧被鍨�
-const getStockInApprovalStatusType = status => {
- const typeMap = {
- "寰呭叆搴�": "info", // 寰呭叆搴� - 鐏拌壊
- "鍏ュ簱涓�": "warning", // 鍏ュ簱涓� - 姗欒壊
- "瀹屽叏鍏ュ簱": "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
- };
- return typeMap[status] || "";
-};
-
-const templateName = ref("");
-const filterInputValue = ref("");
-const templateList = ref([]);
-const isTemplateNameDuplicate = ref(false); // 鏍囪妯℃澘鍚嶇О鏄惁閲嶅
-// 褰撳墠閫変腑鐨勬ā鏉縄D锛堢敤浜庡尯鍒嗘柊澧炴ā鏉胯繕鏄洿鏂版ā鏉匡級
-const currentTemplateId = ref(null);
-
-// 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
-const checkTemplateNameDuplicate = name => {
- if (!name || name.trim() === "") {
- isTemplateNameDuplicate.value = false;
- return false;
- }
- const isDuplicate = templateList.value.some(
- item => item.templateName === name.trim()
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import FileListDialog from "@/components/Dialog/FileListDialog.vue";
+ import { getToken } from "@/utils/auth";
+ import pagination from "@/components/PIMTable/Pagination.vue";
+ import {
+ ref,
+ onMounted,
+ reactive,
+ toRefs,
+ getCurrentInstance,
+ nextTick,
+ } from "vue";
+ import { Search, Delete } from "@element-plus/icons-vue";
+ import { ElMessageBox, ElMessage } from "element-plus";
+ import { userListNoPage } from "@/api/system/user.js";
+ import {
+ addOrUpdateSalesLedgerProduct,
+ delProduct,
+ delLedgerFile,
+ getProductInfoByContractNo,
+ } from "@/api/salesManagement/salesLedger.js";
+ import {
+ addOrEditPurchase,
+ addPurchaseTemplate,
+ updatePurchaseTemplate,
+ createPurchaseNo,
+ delPurchase,
+ getSalesNo,
+ purchaseListPage,
+ productList,
+ getPurchaseById,
+ getOptions,
+ getPurchaseTemplateList,
+ delPurchaseTemplate,
+ batchGeneratePurchaseInboundSteps,
+ } from "@/api/procurementManagement/procurementLedger.js";
+ import useFormData from "@/hooks/useFormData.js";
+ const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
);
isTemplateNameDuplicate.value = isDuplicate;
return isDuplicate;
@@ -509,18 +438,353 @@
return ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'].includes(ext);
};
-// 闃叉姈瀹氭椂鍣�
-let duplicateCheckTimer = null;
-const onTemplateFilterChange = val => {
- filterInputValue.value = val ?? "";
- // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
- if (duplicateCheckTimer) {
- clearTimeout(duplicateCheckTimer);
- }
- // 瀹炴椂妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶嶏紙闃叉姈澶勭悊锛岄伩鍏嶉绻佹彁绀猴級
- if (val && val.trim()) {
- duplicateCheckTimer = setTimeout(() => {
- const isDuplicate = checkTemplateNameDuplicate(val);
+ const userStore = useUserStore();
+
+ // 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
+ const approvalStatusText = {
+ 1: "寰呭鏍�",
+ 2: "瀹℃壒涓�",
+ 3: "瀹℃壒閫氳繃",
+ 4: "瀹℃壒澶辫触",
+ };
+
+ // 鑾峰彇瀹℃壒鐘舵�佹爣绛剧被鍨�
+ const getApprovalStatusType = status => {
+ const typeMap = {
+ 1: "info", // 寰呭鏍� - 鐏拌壊
+ 2: "warning", // 瀹℃壒涓� - 姗欒壊
+ 3: "success", // 瀹℃壒閫氳繃 - 缁胯壊
+ 4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
+ };
+ return typeMap[status] || "";
+ };
+
+ // 鑾峰彇鍏ュ簱鐘舵�佹爣绛剧被鍨�
+ const getStockInStatusType = status => {
+ const typeMap = {
+ 寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
+ 鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
+ 瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+ };
+ return typeMap[status] || "";
+ };
+
+ // 鑾峰彇鍏ュ簱瀹℃牳鐘舵�佹爣绛剧被鍨�
+ const getStockInApprovalStatusType = status => {
+ const typeMap = {
+ 寰呭叆搴�: "info", // 寰呭叆搴� - 鐏拌壊
+ 鍏ュ簱涓�: "warning", // 鍏ュ簱涓� - 姗欒壊
+ 瀹屽叏鍏ュ簱: "success", // 瀹屽叏鍏ュ簱 - 缁胯壊
+ };
+ return typeMap[status] || "";
+ };
+
+ const templateName = ref("");
+ const filterInputValue = ref("");
+ const templateList = ref([]);
+ const isTemplateNameDuplicate = ref(false); // 鏍囪妯℃澘鍚嶇О鏄惁閲嶅
+ // 褰撳墠閫変腑鐨勬ā鏉縄D锛堢敤浜庡尯鍒嗘柊澧炴ā鏉胯繕鏄洿鏂版ā鏉匡級
+ const currentTemplateId = ref(null);
+
+ // 妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶�
+ const checkTemplateNameDuplicate = name => {
+ if (!name || name.trim() === "") {
+ isTemplateNameDuplicate.value = false;
+ return false;
+ }
+ const isDuplicate = templateList.value.some(
+ item => item.templateName === name.trim()
+ );
+ isTemplateNameDuplicate.value = isDuplicate;
+ return isDuplicate;
+ };
+
+ // 闃叉姈瀹氭椂鍣�
+ let duplicateCheckTimer = null;
+ const onTemplateFilterChange = val => {
+ filterInputValue.value = val ?? "";
+ // 娓呴櫎涔嬪墠鐨勫畾鏃跺櫒
+ if (duplicateCheckTimer) {
+ clearTimeout(duplicateCheckTimer);
+ }
+ // 瀹炴椂妫�鏌ユā鏉垮悕绉版槸鍚﹂噸澶嶏紙闃叉姈澶勭悊锛岄伩鍏嶉绻佹彁绀猴級
+ if (val && val.trim()) {
+ duplicateCheckTimer = setTimeout(() => {
+ const isDuplicate = checkTemplateNameDuplicate(val);
+ if (isDuplicate) {
+ ElMessage({
+ message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
+ type: "warning",
+ duration: 2000,
+ });
+ }
+ }, 300); // 300ms 闃叉姈
+ } else {
+ isTemplateNameDuplicate.value = false;
+ }
+ };
+
+ // allow-create 鏃讹紝杈撳叆涓嶅瓨鍦ㄧ殑鍐呭浼氫綔涓� string 鍊艰繑鍥烇紱杩欓噷鍚屾鍥炶緭鍏ユ浠ョ‘淇濇枃瀛椾笉涓�
+ const onTemplateChange = async val => {
+ if (typeof val === "string") {
+ filterInputValue.value = val;
+ // 閫夋嫨鎴栬緭鍏ユ椂妫�鏌ラ噸澶�
+ checkTemplateNameDuplicate(val);
+ }
+
+ // 杩囨护鏁版嵁锛屾煡鎵惧尮閰嶇殑妯℃澘
+ const matchedTemplate = templateList.value.find(
+ item => item.templateName === val
+ );
+
+ if (matchedTemplate?.id) {
+ // 璁板綍褰撳墠閫変腑鐨勬ā鏉縄D锛屽悗缁繚瀛樻椂杩涜鏇存柊鎿嶄綔
+ currentTemplateId.value = matchedTemplate.id;
+ // 閫変腑宸叉湁妯℃澘鏃讹紝涓嶅簲瑙嗕负鈥滄ā鏉垮悕绉伴噸澶嶅鑷翠笉鍙繚瀛樷��
+ isTemplateNameDuplicate.value = false;
+ // 濡傛灉鎵惧埌妯℃澘锛屽彧璧嬪�间緵搴斿晢銆侀」鐩悕绉般�佷粯娆炬柟寮忓拰浜у搧淇℃伅
+ if (matchedTemplate.supplierId) {
+ form.value.supplierId = matchedTemplate.supplierId;
+ }
+ if (matchedTemplate.supplierName) {
+ form.value.supplierName = matchedTemplate.supplierName;
+ }
+ if (matchedTemplate.projectName) {
+ form.value.projectName = matchedTemplate.projectName;
+ }
+ if (matchedTemplate.paymentMethod) {
+ form.value.paymentMethod = matchedTemplate.paymentMethod;
+ }
+ // 妯℃澘鏁版嵁涓殑浜у搧瀛楁鏄� productList锛岄渶瑕佽浆鎹负 productData
+ productData.value =
+ matchedTemplate.productList || matchedTemplate.productData || [];
+ } else {
+ // 鏈尮閰嶅埌宸叉湁妯℃澘锛岃涓烘柊妯℃澘
+ currentTemplateId.value = null;
+ // 濡傛灉娌℃湁鎵惧埌妯℃澘锛岄噸缃〃鍗曪紙淇濇寔褰撳墠琛ㄥ崟鐘舵�侊級
+ const currentFormData = { ...form.value };
+ const currentProductData = [...productData.value];
+
+ // 濡傛灉瀵硅瘽妗嗘湭鎵撳紑锛屽厛鎵撳紑
+ if (!dialogFormVisible.value) {
+ operationType.value = "add";
+ dialogFormVisible.value = true;
+ }
+
+ // 绛夊緟涓嬩竴涓� tick 鍚庢仮澶嶆暟鎹�
+ await nextTick();
+ form.value = {
+ ...form.value,
+ ...currentFormData,
+ };
+ productData.value = currentProductData;
+ }
+ };
+
+ // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+ const operationType = ref("");
+ const dialogFormVisible = ref(false);
+ const data = reactive({
+ searchForm: {
+ supplierName: "", // 渚涘簲鍟嗗悕绉�
+ purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
+ salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+ projectName: "", // 椤圭洰鍚嶇О
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ form: {
+ purchaseContractNumber: "",
+ salesLedgerId: "",
+ projectName: "",
+ recorderId: "",
+ entryDate: "",
+ productData: [],
+ supplierName: "",
+ supplierId: "",
+ paymentMethod: "",
+ executionDate: "",
+ isChecked: false,
+ },
+ rules: {
+ purchaseContractNumber: [
+ { required: false, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ projectName: [
+ { required: true, message: "璇疯緭鍏ラ」鐩悕绉�", trigger: "blur" },
+ ],
+ supplierId: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+ });
+ const { form, rules } = toRefs(data);
+ const { form: searchForm } = useFormData({
+ ...data.searchForm,
+ // 璁剧疆褰曞叆鏃ユ湡鑼冨洿涓哄綋澶�
+ entryDate: [
+ dayjs().startOf("day").format("YYYY-MM-DD"),
+ dayjs().endOf("day").format("YYYY-MM-DD"),
+ ],
+ entryDateStart: dayjs().startOf("day").format("YYYY-MM-DD"),
+ entryDateEnd: dayjs().endOf("day").format("YYYY-MM-DD"),
+ });
+
+ // 浜у搧琛ㄥ崟寮规鏁版嵁
+ const productFormVisible = ref(false);
+ const productOperationType = ref("");
+ const productOperationIndex = ref("");
+ const currentId = ref("");
+ const productFormData = reactive({
+ productForm: {
+ productId: "",
+ productCategory: "",
+ productModelId: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ warnNum: "",
+ isChecked: false,
+ },
+ productRules: {
+ productId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ warnNum: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ isChecked: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+ });
+ const { productForm, productRules } = toRefs(productFormData);
+ const upload = reactive({
+ // 涓婁紶鐨勫湴鍧�
+ url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+ // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+ headers: { Authorization: "Bearer " + getToken() },
+ });
+
+ // 瀵煎叆鐩稿叧
+ const importUploadRef = ref(null);
+ const importUpload = reactive({
+ title: "瀵煎叆閲囪喘鍙拌处",
+ open: false,
+ url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import",
+ headers: { Authorization: "Bearer " + getToken() },
+ isUploading: false,
+ beforeUpload: file => {
+ const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
+ const isLt10M = file.size / 1024 / 1024 < 10;
+ if (!isExcel) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
+ return false;
+ }
+ if (!isLt10M) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+ return false;
+ }
+ return true;
+ },
+ onChange: (file, fileList) => {
+ // noop
+ },
+ onProgress: (event, file, fileList) => {
+ // noop
+ },
+ onSuccess: (response, file, fileList) => {
+ importUpload.isUploading = false;
+ if (response?.code === 200) {
+ proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
+ importUpload.open = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles?.();
+ }
+ getList();
+ } else {
+ proxy.$modal.msgError(response?.msg || "瀵煎叆澶辫触");
+ }
+ },
+ onError: () => {
+ importUpload.isUploading = false;
+ proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
+ },
+ });
+
+ const handleImport = () => {
+ importUpload.title = "瀵煎叆閲囪喘鍙拌处";
+ importUpload.open = true;
+ importUpload.isUploading = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles?.();
+ }
+ };
+
+ // 涓嬭浇瀵煎叆妯℃澘锛堝鍚庣璺緞涓嶅悓锛屽彲鍦ㄦ澶勮皟鏁达級
+ const downloadTemplate = () => {
+ proxy.download(
+ "/purchase/ledger/exportTemplate",
+ {},
+ "閲囪喘鍙拌处瀵煎叆妯℃澘.xlsx"
+ );
+ };
+
+ const submitImportFile = () => {
+ importUpload.isUploading = true;
+ proxy.$refs["importUploadRef"]?.submit?.();
+ };
+
+ const changeDaterange = value => {
+ if (value) {
+ searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ } else {
+ searchForm.entryDateStart = undefined;
+ searchForm.entryDateEnd = undefined;
+ }
+ handleQuery();
+ };
+
+ const formattedNumber = (row, column, cellValue) => {
+ return parseFloat(cellValue).toFixed(2);
+ };
+ // 鏌ヨ鍒楄〃
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ const handleQuery = () => {
+ page.current = 1;
+ getList();
+ };
+
+ // 淇濆瓨妯℃澘
+ const handleButtonClick = async () => {
+ // 妫�鏌ユā鏉垮悕绉版槸鍚︿负绌�
+ if (!templateName.value || templateName.value.trim() === "") {
+ ElMessage({
+ message: "璇疯緭鍏ユā鏉垮悕绉�",
+ type: "warning",
+ });
+ return;
+ }
+
+ // 濡傛灉鏄�滄柊澧炴ā鏉库�濓紙娌℃湁閫変腑宸叉湁妯℃澘锛夛紝鎵嶉渶瑕佸仛閲嶅悕鏍¢獙锛�
+ // 鑻ユ槸閫変腑宸叉湁妯℃澘鍚庝慨鏀癸紝鍒欏厑璁镐娇鐢ㄥ師鍚嶇О锛堣涓烘洿鏂帮級
+ if (!currentTemplateId.value) {
+ const isDuplicate = checkTemplateNameDuplicate(templateName.value);
if (isDuplicate) {
ElMessage({
message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈡ā鏉垮悕绉�",
@@ -997,39 +1261,13 @@
getSalesNo(),
getOptions(),
]);
-
- salesContractList.value = salesRes || [];
- // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
- supplierList.value = (supplierRes.data || []).filter(
- item => item.isWhite === 0
- );
-
- form.value.entryDate = getCurrentDate();
-
- if (type === "add") {
- // 鏂板鏃剁敓鎴愰噰璐悎鍚屽彿
- try {
- const purchaseNoRes = await createPurchaseNo();
- if (purchaseNoRes?.data) {
- form.value.purchaseContractNumber = purchaseNoRes.data;
- }
- } catch (error) {
- console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
- proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
- }
- } else if (type === "edit" && row?.id) {
- // 缂栬緫鏃跺姞杞芥暟鎹�
- currentId.value = row.id;
- try {
- const purchaseRes = await getPurchaseById({ id: row.id, type: 2 });
- form.value = { ...purchaseRes, stockInStatus: row.stockInStatus };
- fileList.value = purchaseRes.storageBlobVOS || [];
- // 浣跨敤 productList 鎺ュ彛鑾峰彇浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
- const productRes = await productList({ salesLedgerId: row.id, type: 2 });
- productData.value = productRes.data || [];
- } catch (error) {
- console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
- proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
+ };
+ // 鎵撳紑寮规
+ const openForm = async (type, row) => {
+ // 缂栬緫鏃舵鏌ュ叆搴撶姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
+ if (type === "edit" && row) {
+ if (row.stockInStatus === "瀹屽叏鍏ュ簱") {
+ proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑璁板綍涓嶈兘缂栬緫");
return;
}
}
@@ -1086,8 +1324,45 @@
if (operationType.value === "edit" && file.id) {
try {
- await delLedgerFile([file.id]);
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ // 骞惰鍔犺浇鍩虹鏁版嵁
+ const [salesRes, supplierRes] = await Promise.all([
+ getSalesNo(),
+ getOptions(),
+ ]);
+
+ salesContractList.value = salesRes || [];
+ // 渚涘簲鍟嗚繃婊ゅ嚭isWhite=0 鐨勬暟鎹�
+ supplierList.value = (supplierRes.data || []).filter(
+ item => item.isWhite === 0
+ );
+
+ form.value.entryDate = getCurrentDate();
+
+ if (type === "edit" && row?.id) {
+ // 缂栬緫鏃跺姞杞芥暟鎹�
+ currentId.value = row.id;
+ try {
+ const purchaseRes = await getPurchaseById({ id: row.id, type: 2 });
+ form.value = { ...purchaseRes, stockInStatus: row.stockInStatus };
+ fileList.value = purchaseRes.storageBlobVOS || [];
+ // 浣跨敤 productList 鎺ュ彛鑾峰彇浜у搧鍒楄〃锛屼互鑾峰彇鍏ュ簱瀹℃牳鐘舵��
+ const productRes = await productList({
+ salesLedgerId: row.id,
+ type: 2,
+ });
+ productData.value = productRes.data || [];
+ } catch (error) {
+ console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
+ proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
+ return;
+ }
+ }
+
+ if (form.value.salesLedgerId == -1) {
+ form.value.salesLedgerId = null;
+ }
+ console.log(form.value, "form.value===========");
+ dialogFormVisible.value = true;
} catch (error) {
console.error("鍒犻櫎鏂囦欢澶辫触:", error);
proxy.$modal.msgError("鍒犻櫎鏂囦欢澶辫触");
@@ -1095,43 +1370,96 @@
}
}
-// 鎻愪氦琛ㄥ崟
-const submitForm = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- if (productData.value.length > 0) {
- // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
- let processedProductData = productData.value;
+ // 绉婚櫎鏂囦欢
+ async function handleRemove(file) {
+ if (!file?.id) {
+ return;
+ }
+ console.log("handleRemove", file.id);
+ if (file.size > 1024 * 1024 * 10) {
+ // 浠呭墠绔竻鐞嗭紝涓嶈皟鐢ㄥ垹闄ゆ帴鍙e拰鎻愮ず
+ return;
+ }
+
+ if (operationType.value === "edit" && file.id) {
+ try {
+ await delLedgerFile([file.id]);
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ } catch (error) {
+ console.error("鍒犻櫎鏂囦欢澶辫触:", error);
+ proxy.$modal.msgError("鍒犻櫎鏂囦欢澶辫触");
+ }
+ }
+ }
+
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = () => {
+ proxy.$refs["formRef"].validate(async valid => {
+ if (valid) {
+ if (productData.value.length > 0) {
+ // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
+ let processedProductData = productData.value;
+ if (operationType.value === "add") {
+ processedProductData = productData.value.map(product => {
+ const { id, ...rest } = product;
+ return rest;
+ });
+ }
+ form.value.productData = proxy.HaveJson(processedProductData);
+ } else {
+ proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+ return;
+ }
+ form.value.storageBlobDTOS = fileList.value;
+ form.value.type = 2;
+
+ // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
+ if (!form.value.salesLedgerId) {
+ form.value.salesContractNo = "";
+ }
+
+ // 鏂板鏃朵笉浼犻�抜d
+ const submitData = { ...form.value };
if (operationType.value === "add") {
processedProductData = productData.value.map(product => {
const { id, ...rest } = product;
return rest;
});
}
- form.value.productData = proxy.HaveJson(processedProductData);
- } else {
- proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
- return;
- }
- form.value.storageBlobDTOS = fileList.value;
- form.value.type = 2;
- // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
- if (!form.value.salesLedgerId) {
- form.value.salesContractNo = "";
- }
+ // 濡傛灉閲囪喘鍚堝悓鍙蜂负绌猴紝鍒欐牴鎹綍鍏ユ棩鏈熻嚜鍔ㄧ敓鎴�
+ if (!submitData.purchaseContractNumber) {
+ try {
+ const purchaseNoRes = await createPurchaseNo(submitData.entryDate);
+ if (purchaseNoRes?.data) {
+ submitData.purchaseContractNumber = purchaseNoRes.data;
+ }
+ } catch (error) {
+ console.error("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�:", error);
+ proxy.$modal.msgWarning("鐢熸垚閲囪喘鍚堝悓鍙峰け璐�");
+ return;
+ }
+ }
- // 鏂板鏃朵笉浼犻�抜d
- const submitData = { ...form.value };
- if (operationType.value === "add") {
- delete submitData.id;
+ addOrEditPurchase(submitData).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
}
-
- addOrEditPurchase(submitData).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- getList();
- });
+ });
+ };
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
+ // 鎵撳紑浜у搧寮规
+ const openProductForm = async (type, row, index) => {
+ // 缂栬緫鏃舵鏌ヤ骇鍝佸叆搴撳鏍哥姸鎬侊紝瀹屽叏鍏ュ簱鏃朵笉鑳界紪杈�
+ if (type === "edit" && row && row.stockInApprovalStatus === "瀹屽叏鍏ュ簱") {
+ proxy.$modal.msgWarning("瀹屽叏鍏ュ簱鐘舵�佺殑浜у搧涓嶈兘缂栬緫");
+ return;
}
});
};
@@ -1482,15 +1810,23 @@
productForm.value.taxInclusiveUnitPrice = "0";
}
}
- // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
- else if (productForm.value.taxInclusiveUnitPrice) {
- productForm.value.quantity = (
- Number(productForm.value.taxInclusiveTotalPrice) /
- Number(productForm.value.taxInclusiveUnitPrice)
- ).toFixed(2);
- // 纭繚缁撴灉涓嶄负璐熸暟
- if (Number(productForm.value.quantity) < 0) {
- productForm.value.quantity = "0";
+ // 妫�鏌ラ�変腑鐨勪骇鍝佷腑鏄惁鏈夊畬鍏ㄥ叆搴撶殑
+ const hasFullyStocked = productSelectedRows.value.some(
+ row => row.stockInApprovalStatus === "瀹屽叏鍏ュ簱"
+ );
+ if (hasFullyStocked) {
+ proxy.$modal.msgWarning("閫変腑鐨勪骇鍝佷腑鍖呭惈瀹屽叏鍏ュ簱鐨勪骇鍝侊紝鏃犳硶鍒犻櫎");
+ return;
+ }
+ if (operationType.value === "add") {
+ productData.value = productData.value.filter(
+ item => !productSelectedRows.value.includes(item)
+ );
+ productSelectedRows.value = [];
+ } else {
+ let ids = [];
+ if (productSelectedRows.value.length > 0) {
+ ids = productSelectedRows.value.map(item => item.id);
}
}
// 鍙嶇畻涓嶅惈绋庢�讳环
@@ -1603,22 +1939,247 @@
message: res?.msg || "鍒犻櫎澶辫触",
type: "error",
});
+ };
+
+ const handleBatchGenerate = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
}
- } catch (error) {
- if (error !== "cancel") {
- console.error("鍒犻櫎妯℃澘澶辫触:", error);
- ElMessage({
- message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
- type: "error",
+ const ids = selectedRows.value.map((item) => item.id);
+
+ ElMessageBox.confirm("纭鎵归噺鐢熸垚鏁版嵁锛�", "鎵归噺鐢熸垚", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "info",
+ })
+ .then(() => {
+ proxy.$modal.loading("姝e湪鎵归噺鐢熸垚鏁版嵁锛岃绋嶅��...");
+ batchGeneratePurchaseInboundSteps({ ids })
+ .then((res) => {
+ proxy.$modal.msgSuccess("鎵归噺鐢熸垚鎴愬姛");
+ getList();
+ })
+ .catch(() => {
+ proxy.$modal.msgError("鎵归噺鐢熸垚澶辫触");
+ })
+ .finally(() => {
+ proxy.$modal.closeLoading();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
});
- }
+ };
+
+ // 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� 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}`;
}
};
-onMounted(() => {
- getList();
- getTemplateList();
-});
+ const mathNum = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (!productForm.value.taxInclusiveUnitPrice) {
+ return;
+ }
+ if (!productForm.value.quantity) {
+ return;
+ }
+ // 鍚◣鎬讳环璁$畻
+ productForm.value.taxInclusiveTotalPrice =
+ proxy.calculateTaxIncludeTotalPrice(
+ productForm.value.taxInclusiveUnitPrice,
+ productForm.value.quantity
+ );
+ if (productForm.value.taxRate) {
+ // 涓嶅惈绋庢�讳环璁$畻
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+ };
+ const reverseMathNum = field => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ const taxRate = Number(productForm.value.taxRate);
+ if (!taxRate) return;
+
+ // 纭繚杈撳叆鍊间笉涓鸿礋鏁�
+ if (
+ field === "taxInclusiveTotalPrice" ||
+ field === "taxExclusiveTotalPrice"
+ ) {
+ const value = Number(productForm.value[field]);
+ if (value < 0) {
+ productForm.value[field] = "0";
+ proxy.$modal.msgWarning("鍊间笉鑳藉皬浜�0");
+ return;
+ }
+ }
+
+ if (field === "taxInclusiveTotalPrice") {
+ // 宸茬煡鍚◣鎬讳环鍜屾暟閲忥紝鍙嶇畻鍚◣鍗曚环
+ if (productForm.value.quantity) {
+ productForm.value.taxInclusiveUnitPrice = (
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.quantity)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
+ productForm.value.taxInclusiveUnitPrice = "0";
+ }
+ }
+ // 宸茬煡鍚◣鎬讳环鍜屽惈绋庡崟浠凤紝鍙嶇畻鏁伴噺
+ else if (productForm.value.taxInclusiveUnitPrice) {
+ productForm.value.quantity = (
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.taxInclusiveUnitPrice)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.quantity) < 0) {
+ productForm.value.quantity = "0";
+ }
+ }
+ // 鍙嶇畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice = (
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ (1 + taxRate / 100)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxExclusiveTotalPrice) < 0) {
+ productForm.value.taxExclusiveTotalPrice = "0";
+ }
+ } else if (field === "taxExclusiveTotalPrice") {
+ // 鍙嶇畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = (
+ Number(productForm.value.taxExclusiveTotalPrice) *
+ (1 + taxRate / 100)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxInclusiveTotalPrice) < 0) {
+ productForm.value.taxInclusiveTotalPrice = "0";
+ }
+ // 宸茬煡鏁伴噺锛屽弽绠楀惈绋庡崟浠�
+ if (productForm.value.quantity) {
+ productForm.value.taxInclusiveUnitPrice = (
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.quantity)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.taxInclusiveUnitPrice) < 0) {
+ productForm.value.taxInclusiveUnitPrice = "0";
+ }
+ }
+ // 宸茬煡鍚◣鍗曚环锛屽弽绠楁暟閲�
+ else if (productForm.value.taxInclusiveUnitPrice) {
+ productForm.value.quantity = (
+ Number(productForm.value.taxInclusiveTotalPrice) /
+ Number(productForm.value.taxInclusiveUnitPrice)
+ ).toFixed(2);
+ // 纭繚缁撴灉涓嶄负璐熸暟
+ if (Number(productForm.value.quantity) < 0) {
+ productForm.value.quantity = "0";
+ }
+ }
+ }
+ };
+ // 閿�鍞悎鍚岄�夋嫨鏀瑰彉鏂规硶
+ const salesLedgerChange = async row => {
+ console.log("row", row);
+ var index = salesContractList.value.findIndex(item => item.id == row);
+ console.log("index", index);
+ if (index > -1) {
+ await querygProductInfoByContractNo();
+ }
+ };
+
+ const querygProductInfoByContractNo = async () => {
+ const { code, data } = await getProductInfoByContractNo({
+ contractNo: form.value.salesLedgerId,
+ });
+ if (code == 200) {
+ productData.value = data || [];
+ }
+ };
+
+ // 鑾峰彇妯℃澘淇℃伅
+ const getTemplateList = async () => {
+ let res = await getPurchaseTemplateList();
+ if (res && res.code === 200 && Array.isArray(res.data)) {
+ templateList.value = res.data;
+ }
+ };
+
+ // 鎵撳紑闄勪欢寮规
+ const openFileDialog = async row => {
+ recordId.value = row.id;
+ fileListDialogVisible.value = true;
+ };
+
+ // 鍒犻櫎妯℃澘
+ const handleDeleteTemplate = async item => {
+ if (!item.id) {
+ proxy.$modal.msgWarning("鏃犳硶鍒犻櫎璇ユā鏉�");
+ return;
+ }
+
+ try {
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゆā鏉�"${item.templateName}"鍚楋紵`,
+ "鍒犻櫎纭",
+ {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }
+ );
+
+ const res = await delPurchaseTemplate([item.id]);
+ if (res && res.code === 200) {
+ ElMessage({
+ message: "鍒犻櫎鎴愬姛",
+ type: "success",
+ });
+ // 濡傛灉鍒犻櫎鐨勬槸褰撳墠閫変腑鐨勬ā鏉匡紝娓呯┖閫夋嫨
+ if (templateName.value === item.templateName) {
+ templateName.value = "";
+ filterInputValue.value = "";
+ }
+ // 閲嶆柊鑾峰彇妯℃澘鍒楄〃
+ await getTemplateList();
+ } else {
+ ElMessage({
+ message: res?.msg || "鍒犻櫎澶辫触",
+ type: "error",
+ });
+ }
+ } catch (error) {
+ if (error !== "cancel") {
+ console.error("鍒犻櫎妯℃澘澶辫触:", error);
+ ElMessage({
+ message: "鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯",
+ type: "error",
+ });
+ }
+ }
+ };
+
+ onMounted(() => {
+ getList();
+ getTemplateList();
+ });
</script>
<style scoped lang="scss">
diff --git a/src/views/procurementManagement/procurementPlan/index.vue b/src/views/procurementManagement/procurementPlan/index.vue
index 42a1bcf..ba9a38c 100644
--- a/src/views/procurementManagement/procurementPlan/index.vue
+++ b/src/views/procurementManagement/procurementPlan/index.vue
@@ -1,158 +1,205 @@
<template>
<div class="app-container">
<!-- 鎼滅储鍖哄煙 -->
- <el-card class="search-card" shadow="never">
- <el-form :model="searchForm" :inline="true" class="search-form">
+ <el-card class="search-card"
+ shadow="never">
+ <el-form :model="searchForm"
+ :inline="true"
+ class="search-form">
<el-form-item label="璁″垝鍚嶇О">
- <el-input v-model="searchForm.planName" placeholder="璇疯緭鍏ヨ鍒掑悕绉�" clearable />
+ <el-input v-model="searchForm.planName"
+ placeholder="璇疯緭鍏ヨ鍒掑悕绉�"
+ clearable />
</el-form-item>
<el-form-item label="鐘舵��">
- <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨鐘舵��" clearable style="width: 150px">
- <el-option label="鍚敤" value="active" />
- <el-option label="绂佺敤" value="disabled" />
+ <el-select v-model="searchForm.status"
+ placeholder="璇烽�夋嫨鐘舵��"
+ clearable
+ style="width: 150px">
+ <el-option label="鍚敤"
+ value="active" />
+ <el-option label="绂佺敤"
+ value="disabled" />
</el-select>
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="handleSearch">
- <el-icon><Search /></el-icon>
+ <el-button type="primary"
+ @click="handleSearch">
+ <el-icon>
+ <Search />
+ </el-icon>
鎼滅储
</el-button>
<el-button @click="handleReset">
- <el-icon><Refresh /></el-icon>
+ <el-icon>
+ <Refresh />
+ </el-icon>
閲嶇疆
</el-button>
</el-form-item>
</el-form>
</el-card>
-
<!-- 鎿嶄綔鎸夐挳 -->
- <el-card class="table-card" shadow="never">
+ <el-card class="table-card"
+ shadow="never">
<div class="table-header">
<div class="table-title">閲囪喘璁″垝鍒楄〃</div>
<div class="table-actions">
- <el-button type="primary" @click="handleAdd">
- <el-icon><Plus /></el-icon>
+ <el-button type="primary"
+ @click="handleAdd">
+ <el-icon>
+ <Plus />
+ </el-icon>
鏂板璁″垝
</el-button>
- <el-button type="info" @click="handleExport">
- <el-icon><Download /></el-icon>
+ <el-button type="info"
+ @click="handleExport">
+ <el-icon>
+ <Download />
+ </el-icon>
瀵煎嚭
</el-button>
</div>
</div>
-
<!-- 鏁版嵁琛ㄦ牸 -->
- <el-table
- v-loading="loading"
- :data="tableData"
- stripe
- border
- style="width: 100%"
- >
- <el-table-column prop="planName" label="璁″垝鍚嶇О" min-width="150" />
- <el-table-column prop="description" label="鎻忚堪" min-width="200" show-overflow-tooltip />
- <el-table-column prop="formula" label="璁$畻鍏紡" min-width="200" show-overflow-tooltip>
+ <el-table v-loading="loading"
+ :data="tableData"
+ stripe
+ border
+ style="width: 100%">
+ <el-table-column prop="planName"
+ label="璁″垝鍚嶇О"
+ min-width="150" />
+ <el-table-column prop="description"
+ label="鎻忚堪"
+ min-width="200"
+ show-overflow-tooltip />
+ <el-table-column prop="formula"
+ label="璁$畻鍏紡"
+ min-width="200"
+ show-overflow-tooltip>
<template #default="{ row }">
- <el-tag type="info" size="small">{{ row.formula }}</el-tag>
+ <el-tag type="info"
+ size="small">{{ row.formula }}</el-tag>
</template>
</el-table-column>
- <el-table-column prop="status" label="鐘舵��" width="80" align="center">
+ <el-table-column prop="status"
+ label="鐘舵��"
+ width="80"
+ align="center">
<template #default="{ row }">
- <el-tag :type="row.status === 'active' ? 'success' : 'info'" size="small">
+ <el-tag :type="row.status === 'active' ? 'success' : 'info'"
+ size="small">
{{ row.status === 'active' ? '鍚敤' : '绂佺敤' }}
</el-tag>
</template>
</el-table-column>
- <el-table-column prop="updateTime" label="鏈�鍚庤绠楁椂闂�" width="160" />
- <el-table-column label="鎿嶄綔" width="200" fixed="right" align="center">
+ <el-table-column prop="updateTime"
+ label="鏈�鍚庤绠楁椂闂�"
+ width="160" />
+ <el-table-column label="鎿嶄綔"
+ width="200"
+ fixed="right"
+ align="center">
<template #default="{ row }">
- <el-button type="primary" link @click="handleEdit(row)">缂栬緫</el-button>
- <el-button type="success" link @click="handleCalculate(row)">璁$畻</el-button>
- <el-button type="danger" link @click="handleDelete(row)">鍒犻櫎</el-button>
+ <el-button type="primary"
+ link
+ @click="handleEdit(row)">缂栬緫</el-button>
+ <el-button type="success"
+ link
+ @click="handleCalculate(row)">璁$畻</el-button>
+ <el-button type="danger"
+ link
+ @click="handleDelete(row)">鍒犻櫎</el-button>
</template>
</el-table-column>
</el-table>
-
<!-- 鍒嗛〉 -->
<div class="pagination-container">
- <el-pagination
- v-model:current-page="pagination.current"
- v-model:page-size="pagination.size"
- :page-sizes="[10, 20, 50, 100]"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange"
- />
+ <el-pagination v-model:current-page="pagination.current"
+ v-model:page-size="pagination.size"
+ :page-sizes="[10, 20, 50, 100]"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange" />
</div>
</el-card>
-
<!-- 鏂板/缂栬緫瀵硅瘽妗� -->
- <FormDialog
- v-model="dialogVisible"
- :title="dialogType === 'add' ? '鏂板閲囪喘璁″垝' : '缂栬緫閲囪喘璁″垝'"
- :width="'1000px'"
- :operation-type="dialogType"
- :close-on-click-modal="false"
- @close="dialogVisible = false"
- @confirm="handleSubmit"
- @cancel="dialogVisible = false"
- >
+ <FormDialog v-model="dialogVisible"
+ :title="dialogType === 'add' ? '鏂板閲囪喘璁″垝' : '缂栬緫閲囪喘璁″垝'"
+ :width="'1000px'"
+ :operation-type="dialogType"
+ :close-on-click-modal="false"
+ @close="dialogVisible = false"
+ @confirm="handleSubmit"
+ @cancel="dialogVisible = false">
<div class="form-container">
<!-- 鍩烘湰淇℃伅 -->
<div class="form-section">
<div class="section-title">鍩烘湰淇℃伅</div>
- <el-form
- ref="formRef"
- :model="formData"
- :rules="formRules"
- label-width="120px"
- >
+ <el-form ref="formRef"
+ :model="formData"
+ :rules="formRules"
+ label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="缂栫爜" prop="code">
- <el-input v-model="formData.code" placeholder="绯荤粺鑷姩鐢熸垚" disabled />
+ <el-form-item label="缂栫爜"
+ prop="code">
+ <el-input v-model="formData.code"
+ placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�"
+ disabled />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鍚嶇О" prop="planName" required>
- <el-input v-model="formData.planName" placeholder="璇疯緭鍏ヨ鍒掑悕绉�" />
+ <el-form-item label="鍚嶇О"
+ prop="planName"
+ required>
+ <el-input v-model="formData.planName"
+ placeholder="璇疯緭鍏ヨ鍒掑悕绉�" />
</el-form-item>
</el-col>
</el-row>
-
- <el-form-item label="鎻忚堪" prop="description">
- <el-input
- v-model="formData.description"
- type="textarea"
- :rows="3"
- placeholder="璇疯緭鍏ヨ鍒掓弿杩�"
- />
+ <el-form-item label="鎻忚堪"
+ prop="description">
+ <el-input v-model="formData.description"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヨ鍒掓弿杩�" />
</el-form-item>
-
<el-row :gutter="20">
<el-col :span="12">
- <el-form-item label="鐘舵��" prop="status">
- <el-select v-model="formData.status" placeholder="璇烽�夋嫨鐘舵��" style="width: 100%">
- <el-option label="鍚敤" value="active" />
- <el-option label="绂佺敤" value="disabled" />
+ <el-form-item label="鐘舵��"
+ prop="status">
+ <el-select v-model="formData.status"
+ placeholder="璇烽�夋嫨鐘舵��"
+ style="width: 100%">
+ <el-option label="鍚敤"
+ value="active" />
+ <el-option label="绂佺敤"
+ value="disabled" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏄惁绯荤粺棰勭疆">
- <el-checkbox v-model="formData.isSystemPreset">鏄�</el-checkbox>
+ <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
+ <el-date-picker v-model="formCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
-
<!-- 璁$畻鍙傛暟 -->
<div class="form-section">
<div class="section-title">璁$畻鍙傛暟</div>
- <el-tabs v-model="activeTab" class="param-tabs">
- <el-tab-pane label="闇�姹傚弬鏁�" name="demand">
+ <el-tabs v-model="activeTab"
+ class="param-tabs">
+ <el-tab-pane label="闇�姹傚弬鏁�"
+ name="demand">
<div class="checkbox-group">
<el-checkbox v-model="formData.considerExistingStock">鑰冭檻鐜版湁搴撳瓨</el-checkbox>
<el-checkbox v-model="formData.warehouseControl">浠撳簱杩愯MRP鐨勬帶鍒�</el-checkbox>
@@ -163,7 +210,8 @@
<el-checkbox v-model="formData.negativeStockAsDemand">璐熷簱瀛樹綔涓洪渶姹�</el-checkbox>
</div>
</el-tab-pane>
- <el-tab-pane label="璁$畻鍙傛暟" name="calculation">
+ <el-tab-pane label="璁$畻鍙傛暟"
+ name="calculation">
<div class="checkbox-group">
<el-checkbox v-model="formData.considerExistingStock">鑰冭檻鐜版湁搴撳瓨</el-checkbox>
<el-checkbox v-model="formData.warehouseControl">浠撳簱杩愯MRP鐨勬帶鍒�</el-checkbox>
@@ -176,7 +224,6 @@
</el-tab-pane>
</el-tabs>
</div>
-
<!-- 姹囨�诲悎骞堕�夐」 -->
<div class="form-section">
<div class="section-title">姹囨�诲悎骞堕�夐」</div>
@@ -186,20 +233,20 @@
<el-checkbox v-model="formData.summaryDemandDate">闇�姹傛棩鏈�</el-checkbox>
</div>
</div>
-
<!-- 璁$畻鍏紡 -->
<div class="form-section">
<div class="section-title">璁$畻鍏紡</div>
<div class="formula-input-section">
- <el-form-item label="璁$畻鍏紡" prop="formula" required>
- <el-input
- v-model="formData.formula"
- placeholder="渚嬪: 棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺"
- @input="validateFormula"
- />
+ <el-form-item label="璁$畻鍏紡"
+ prop="formula"
+ required>
+ <el-input v-model="formData.formula"
+ placeholder="渚嬪: 棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺"
+ @input="validateFormula" />
</el-form-item>
<div class="formula-help">
- <el-text type="info" size="small">
+ <el-text type="info"
+ size="small">
鏀寔鍙橀噺锛氶璁″嚭搴撴暟閲忋�佺幇鏈夊簱瀛樸�佸畨鍏ㄥ簱瀛樸�侀璁″叆搴撴暟閲�
</el-text>
</div>
@@ -207,87 +254,117 @@
</div>
</div>
</FormDialog>
-
<!-- 浜у搧閫夋嫨瀵硅瘽妗� -->
- <FormDialog
- v-model="productSelectDialogVisible"
- title="閫夋嫨浜у搧"
- :width="'800px'"
- :close-on-click-modal="false"
- @close="productSelectDialogVisible = false"
- @confirm="handleConfirmProductSelection"
- @cancel="productSelectDialogVisible = false"
- >
+ <FormDialog v-model="productSelectDialogVisible"
+ title="閫夋嫨浜у搧"
+ :width="'800px'"
+ :close-on-click-modal="false"
+ @close="productSelectDialogVisible = false"
+ @confirm="handleConfirmProductSelection"
+ @cancel="productSelectDialogVisible = false">
<div class="product-select">
- <el-alert
- title="璇烽�夋嫨瑕佽绠楃殑浜у搧"
- type="info"
- :closable="false"
- show-icon
- >
+ <el-alert title="璇烽�夋嫨瑕佽绠楃殑浜у搧"
+ type="info"
+ :closable="false"
+ show-icon>
<template #default>
<p>閫夋嫨浜у搧鍚庯紝绯荤粺灏嗘牴鎹綋鍓嶈绠楀叕寮忓拰浜у搧搴撳瓨鎯呭喌杩涜璁$畻銆�</p>
</template>
</el-alert>
-
- <el-table
- v-loading="productLoading"
- :data="productList"
- @selection-change="handleProductSelectionChange"
- stripe
- border
- style="width: 100%; margin-top: 20px;"
- >
- <el-table-column type="selection" width="55" />
- <el-table-column prop="productCategory" label="浜у搧澶х被" min-width="150" />
- <el-table-column prop="specificationModel" label="浜у搧瑙勬牸" width="120" />
- <el-table-column prop="inboundNum0" label="鐜版湁搴撳瓨" width="100" align="right" />
- <el-table-column prop="inboundNum" label="瀹夊叏搴撳瓨" width="100" align="right" />
- <el-table-column prop="inboundNum" label="棰勮鍑哄簱" width="100" align="right" />
- <el-table-column prop="inboundNum0" label="棰勮鍏ュ簱" width="100" align="right" />
+ <el-table v-loading="productLoading"
+ :data="productList"
+ @selection-change="handleProductSelectionChange"
+ stripe
+ border
+ style="width: 100%; margin-top: 20px;">
+ <el-table-column type="selection"
+ width="55" />
+ <el-table-column prop="productCategory"
+ label="浜у搧澶х被"
+ min-width="150" />
+ <el-table-column prop="specificationModel"
+ label="瑙勬牸鍨嬪彿"
+ width="120" />
+ <el-table-column prop="inboundNum0"
+ label="鐜版湁搴撳瓨"
+ width="100"
+ align="right" />
+ <el-table-column prop="inboundNum"
+ label="瀹夊叏搴撳瓨"
+ width="100"
+ align="right" />
+ <el-table-column prop="inboundNum"
+ label="棰勮鍑哄簱"
+ width="100"
+ align="right" />
+ <el-table-column prop="inboundNum0"
+ label="棰勮鍏ュ簱"
+ width="100"
+ align="right" />
</el-table>
</div>
</FormDialog>
-
<!-- 璁$畻缁撴灉瀵硅瘽妗� -->
- <FormDialog
- v-model="calculateDialogVisible"
- title="閲囪喘璁$畻缁撴灉"
- :width="'1000px'"
- :close-on-click-modal="false"
- @close="calculateDialogVisible = false"
- @confirm="handleCreatePurchaseOrder"
- @cancel="calculateDialogVisible = false"
- >
+ <FormDialog v-model="calculateDialogVisible"
+ title="閲囪喘璁$畻缁撴灉"
+ :width="'1000px'"
+ :close-on-click-modal="false"
+ @close="calculateDialogVisible = false"
+ @confirm="handleCreatePurchaseOrder"
+ @cancel="calculateDialogVisible = false">
<div class="calculate-result">
- <el-alert
- title="璁$畻缁撴灉"
- type="success"
- :closable="false"
- show-icon
- >
+ <el-alert title="璁$畻缁撴灉"
+ type="success"
+ :closable="false"
+ show-icon>
<template #default>
<p>鍩轰簬褰撳墠閰嶇疆鐨勮绠楀叕寮忓拰搴撳瓨鎯呭喌锛岀郴缁熷凡璁$畻鍑哄悇浜у搧鐨勯噰璐渶姹傘��</p>
</template>
</el-alert>
-
- <el-table :data="calculateResult" stripe border style="width: 100%; margin-top: 20px;">
- <el-table-column prop="productCategory" label="浜у搧澶х被" min-width="150" />
- <el-table-column prop="specificationModel" label="浜у搧瑙勬牸" width="120" />
- <el-table-column prop="inboundNum0" label="鐜版湁搴撳瓨" width="100" align="right" />
- <el-table-column prop="inboundNum" label="瀹夊叏搴撳瓨" width="100" align="right" />
- <el-table-column prop="inboundNum" label="棰勮鍑哄簱鏁伴噺" width="120" align="right" />
- <el-table-column prop="inboundNum0" label="棰勮鍏ュ簱鏁伴噺" width="120" align="right" />
- <el-table-column prop="weeklyNetDemand" label="鎸夊懆鍑�闇�姹�" width="120" align="right">
+ <el-table :data="calculateResult"
+ stripe
+ border
+ style="width: 100%; margin-top: 20px;">
+ <el-table-column prop="productCategory"
+ label="浜у搧澶х被"
+ min-width="150" />
+ <el-table-column prop="specificationModel"
+ label="瑙勬牸鍨嬪彿"
+ width="120" />
+ <el-table-column prop="inboundNum0"
+ label="鐜版湁搴撳瓨"
+ width="100"
+ align="right" />
+ <el-table-column prop="inboundNum"
+ label="瀹夊叏搴撳瓨"
+ width="100"
+ align="right" />
+ <el-table-column prop="inboundNum"
+ label="棰勮鍑哄簱鏁伴噺"
+ width="120"
+ align="right" />
+ <el-table-column prop="inboundNum0"
+ label="棰勮鍏ュ簱鏁伴噺"
+ width="120"
+ align="right" />
+ <el-table-column prop="weeklyNetDemand"
+ label="鎸夊懆鍑�闇�姹�"
+ width="120"
+ align="right">
<template #default="{ row }">
- <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'" size="small">
+ <el-tag :type="row.weeklyNetDemand > 0 ? 'warning' : 'success'"
+ size="small">
{{ row.weeklyNetDemand }}
</el-tag>
</template>
</el-table-column>
- <el-table-column prop="suggestedPurchase" label="寤鸿閲囪喘" width="100" align="right">
+ <el-table-column prop="suggestedPurchase"
+ label="寤鸿閲囪喘"
+ width="100"
+ align="right">
<template #default="{ row }">
- <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'" size="small">
+ <el-tag :type="row.suggestedPurchase > 0 ? 'danger' : 'success'"
+ size="small">
{{ row.suggestedPurchase }}
</el-tag>
</template>
@@ -299,214 +376,51 @@
</template>
<script setup>
-import FormDialog from '@/components/Dialog/FormDialog.vue';
-import {ref, reactive, onMounted, getCurrentInstance} from 'vue'
-import { ElMessage, ElMessageBox } from 'element-plus'
-import { Search, Refresh, Plus, Download } from '@element-plus/icons-vue'
-import {listPage,add,update,del,listPageCopy} from "@/api/procurementManagement/procurementPlan.js"
+ import FormDialog from "@/components/Dialog/FormDialog.vue";
+ import { ref, reactive, onMounted, getCurrentInstance, computed } from "vue";
+ import dayjs from "dayjs";
+ import { ElMessage, ElMessageBox } from "element-plus";
+ import { Search, Refresh, Plus, Download } from "@element-plus/icons-vue";
+ import {
+ listPage,
+ add,
+ update,
+ del,
+ listPageCopy,
+ } from "@/api/procurementManagement/procurementPlan.js";
-// 鍝嶅簲寮忔暟鎹�
-const loading = ref(false)
-const submitLoading = ref(false)
-const dialogVisible = ref(false)
-const productSelectDialogVisible = ref(false)
-const calculateDialogVisible = ref(false)
-const dialogType = ref('add')
-const productLoading = ref(false)
-const selectedProducts = ref([])
-const currentPlan = ref(null)
+ // 鍝嶅簲寮忔暟鎹�
+ const loading = ref(false);
+ const submitLoading = ref(false);
+ const dialogVisible = ref(false);
+ const productSelectDialogVisible = ref(false);
+ const calculateDialogVisible = ref(false);
+ const dialogType = ref("add");
+ const productLoading = ref(false);
+ const selectedProducts = ref([]);
+ const currentPlan = ref(null);
-// 鎼滅储琛ㄥ崟
-const searchForm = reactive({
- planName: '',
- status: ''
-})
+ // 鎼滅储琛ㄥ崟
+ const searchForm = reactive({
+ planName: "",
+ status: "",
+ });
-// 鍒嗛〉鏁版嵁
-const pagination = reactive({
- current: 1,
- size: 20
-})
+ // 鍒嗛〉鏁版嵁
+ const pagination = reactive({
+ current: 1,
+ size: 20,
+ });
-// 琛ㄥ崟鏁版嵁
-const formData = reactive({
- code: '',
- planName: '',
- description: '',
- status: '',
- isSystemPreset: false,
- formula: '',
- // 璁$畻鍙傛暟
- considerExistingStock: false,
- warehouseControl: false,
- calculateTotalDemand: false,
- considerSafetyStock: false,
- considerLockedStock: false,
- notConsiderMaterialAux: false,
- negativeStockAsDemand: false,
- // 姹囨�诲悎骞堕�夐」
- summaryMaterial: false,
- summaryAuxAttributes: false,
- summaryDemandDate: false
-})
-
-// 褰撳墠婵�娲荤殑鏍囩椤�
-const activeTab = ref('demand')
-
-// 琛ㄥ崟楠岃瘉瑙勫垯
-const formRules = {
- planName: [
- { required: true, message: '璇疯緭鍏ヨ鍒掑悕绉�', trigger: 'blur' }
- ],
- status: [
- { required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }
- ],
- formula: [
- { required: true, message: '璇疯緭鍏ヨ绠楀叕寮�', trigger: 'blur' }
- ]
-}
-
-// 琛ㄦ牸鏁版嵁
-const tableData = ref([])
-
-// 浜у搧鍒楄〃鏁版嵁
-const productList = ref([
- {
- id: 4,
- productName: '浜у搧D',
- productCode: 'PD004',
- existingStock: 90,
- safetyStock: 40,
- expectedOutbound: 160,
- expectedInbound: 35
- }
-])
-
-// 璁$畻缁撴灉鏁版嵁
-const calculateResult = ref([
- {
- productName: '浜у搧A',
- existingStock: 100,
- safetyStock: 50,
- expectedOutbound: 200,
- expectedInbound: 30,
- weeklyNetDemand: 120,
- suggestedPurchase: 150
- },
- {
- productName: '浜у搧B',
- existingStock: 80,
- safetyStock: 30,
- expectedOutbound: 150,
- expectedInbound: 20,
- weeklyNetDemand: 100,
- suggestedPurchase: 120
- }
-])
-const total = ref(0)
-// 鏂规硶
-const handleSearch = () => {
- pagination.current = 1
- loadData()
-}
-
-const handleReset = () => {
- Object.assign(searchForm, {
- planName: '',
- status: ''
- })
- handleSearch()
-}
-
-const loadData = () => {
- loading.value = true
- listPage({...searchForm,...pagination}).then(res => {
- if(res.code === 200){
- tableData.value = res.data.records
- total.value = res.data.total
- loading.value = false
- }
- })
-}
-
-const handleAdd = () => {
- dialogType.value = 'add'
- resetForm()
- // 鑷姩鐢熸垚缂栫爜
- formData.code = 'CGJH' + String(Date.now()).slice(-4)
- dialogVisible.value = true
-}
-
-const handleEdit = (row) => {
- dialogType.value = 'edit'
- Object.assign(formData, row)
- dialogVisible.value = true
-}
-
-const handleDelete = async (row) => {
- try {
- await ElMessageBox.confirm('纭畾瑕佸垹闄よ繖涓噰璐鍒掑悧锛�', '鎻愮ず', {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning'
- })
- let ids = [row.id]
- del(ids).then(res =>{
- if(res.code === 200){
- ElMessage.success('鍒犻櫎鎴愬姛')
- loadData()
- }
- })
- } catch {
- // 鐢ㄦ埛鍙栨秷鍒犻櫎
- }
-}
-
-const handleSubmit = async () => {
- try {
- // 琛ㄥ崟楠岃瘉
- if (!formData.planName || !formData.formula) {
- ElMessage.error('璇峰~鍐欏繀濉」')
- return
- }
-
- submitLoading.value = true
-
- if (dialogType.value === 'add') {
- add(formData).then(res => {
- if(res.code === 200){
- ElMessage.success('鏂板鎴愬姛')
- dialogVisible.value = false
- loadData()
- }
- })
- } else {
- // 缂栬緫
- update(formData).then(res => {
- if(res.code === 200){
- ElMessage.success('缂栬緫鎴愬姛')
- dialogVisible.value = false
- loadData()
- }
- })
- }
-
-
- } catch (error) {
- ElMessage.error('鎿嶄綔澶辫触')
- } finally {
- submitLoading.value = false
- }
-}
-
-const resetForm = () => {
- Object.assign(formData, {
- code: '',
- planName: '',
- description: '',
- status: '',
+ // 琛ㄥ崟鏁版嵁
+ const formData = reactive({
+ code: "",
+ planName: "",
+ description: "",
+ status: "",
isSystemPreset: false,
- formula: '棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺',
+ formula: "",
+ createTime: "",
// 璁$畻鍙傛暟
considerExistingStock: false,
warehouseControl: false,
@@ -518,255 +432,425 @@
// 姹囨�诲悎骞堕�夐」
summaryMaterial: false,
summaryAuxAttributes: false,
- summaryDemandDate: false
- })
- activeTab.value = 'demand'
-}
+ summaryDemandDate: false,
+ });
+ const formCreateTimeDate = computed({
+ get: () => (formData.createTime ? String(formData.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ formData.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
+ });
-const validateFormula = () => {
- // 绠�鍗曠殑鍏紡楠岃瘉
- const formula = formData.formula
- if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) {
- ElMessage.warning('鍏紡鏍煎紡鍙兘涓嶆纭紝璇锋鏌�')
- }
-}
+ // 褰撳墠婵�娲荤殑鏍囩椤�
+ const activeTab = ref("demand");
-const handleCalculate = (row) => {
- currentPlan.value = row
- productSelectDialogVisible.value = true
- loadProductList()
-}
+ // 琛ㄥ崟楠岃瘉瑙勫垯
+ const formRules = {
+ planName: [{ required: true, message: "璇疯緭鍏ヨ鍒掑悕绉�", trigger: "blur" }],
+ status: [{ required: true, message: "璇烽�夋嫨鐘舵��", trigger: "change" }],
+ formula: [{ required: true, message: "璇疯緭鍏ヨ绠楀叕寮�", trigger: "blur" }],
+ };
-const loadProductList = () => {
- productLoading.value = true
- // 妯℃嫙鍔犺浇浜у搧鏁版嵁
- listPageCopy({size:-1}).then(res => {
- if(res.code === 200){
- productList.value = res.data.records
- productLoading.value = false
+ // 琛ㄦ牸鏁版嵁
+ const tableData = ref([]);
+
+ // 浜у搧鍒楄〃鏁版嵁
+ const productList = ref([
+ {
+ id: 4,
+ productName: "浜у搧D",
+ productCode: "PD004",
+ existingStock: 90,
+ safetyStock: 40,
+ expectedOutbound: 160,
+ expectedInbound: 35,
+ },
+ ]);
+
+ // 璁$畻缁撴灉鏁版嵁
+ const calculateResult = ref([
+ {
+ productName: "浜у搧A",
+ existingStock: 100,
+ safetyStock: 50,
+ expectedOutbound: 200,
+ expectedInbound: 30,
+ weeklyNetDemand: 120,
+ suggestedPurchase: 150,
+ },
+ {
+ productName: "浜у搧B",
+ existingStock: 80,
+ safetyStock: 30,
+ expectedOutbound: 150,
+ expectedInbound: 20,
+ weeklyNetDemand: 100,
+ suggestedPurchase: 120,
+ },
+ ]);
+ const total = ref(0);
+ // 鏂规硶
+ const handleSearch = () => {
+ pagination.current = 1;
+ loadData();
+ };
+
+ const handleReset = () => {
+ Object.assign(searchForm, {
+ planName: "",
+ status: "",
+ });
+ handleSearch();
+ };
+
+ const loadData = () => {
+ loading.value = true;
+ listPage({ ...searchForm, ...pagination }).then(res => {
+ if (res.code === 200) {
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ loading.value = false;
+ }
+ });
+ };
+
+ const handleAdd = () => {
+ dialogType.value = "add";
+ resetForm();
+ formData.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
+ dialogVisible.value = true;
+ };
+
+ const handleEdit = row => {
+ dialogType.value = "edit";
+ Object.assign(formData, row);
+ dialogVisible.value = true;
+ };
+
+ const handleDelete = async row => {
+ try {
+ await ElMessageBox.confirm("纭畾瑕佸垹闄よ繖涓噰璐鍒掑悧锛�", "鎻愮ず", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ });
+ let ids = [row.id];
+ del(ids).then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ loadData();
+ }
+ });
+ } catch {
+ // 鐢ㄦ埛鍙栨秷鍒犻櫎
}
- })
-}
+ };
-const handleProductSelectionChange = (selection) => {
- selectedProducts.value = selection
-}
+ const handleSubmit = async () => {
+ try {
+ // 琛ㄥ崟楠岃瘉
+ if (!formData.planName || !formData.formula) {
+ ElMessage.error("璇峰~鍐欏繀濉」");
+ return;
+ }
-const handleConfirmProductSelection = () => {
- if (selectedProducts.value.length === 0) {
- ElMessage.warning('璇烽�夋嫨瑕佽绠楃殑浜у搧')
- return
- }
-
- ElMessage.success(`姝e湪璁$畻 ${currentPlan.value.planName} 鐨勯噰璐渶姹�...`)
- productSelectDialogVisible.value = false
-
- // 鏍规嵁閫夋嫨鐨勪骇鍝佸拰璁$畻鍏紡杩涜璁$畻
- calculateWithSelectedProducts()
-}
+ submitLoading.value = true;
-const calculateWithSelectedProducts = () => {
- // 妯℃嫙璁$畻杩囩▼
- // 鏍规嵁閫夋嫨鐨勪骇鍝佹洿鏂拌绠楃粨鏋�
- const result = selectedProducts.value.map(product => {
- // 杩欓噷搴旇鏍规嵁瀹為檯鐨勮绠楀叕寮忚繘琛岃绠�
- // 绀轰緥锛氶璁″嚭搴撴暟閲� - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺
- const weeklyNetDemand = product.inboundNum - product.inboundNum0 + product.inboundNum - product.inboundNum0
- const suggestedPurchase = Math.max(0, weeklyNetDemand)
-
- return {
- productCategory: product.productCategory,
- specificationModel: product.specificationModel,
- inboundNum0: product.inboundNum0,
- inboundNum: product.inboundNum,
- weeklyNetDemand: weeklyNetDemand,
- suggestedPurchase: suggestedPurchase
+ if (dialogType.value === "add") {
+ add(formData).then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鏂板鎴愬姛");
+ dialogVisible.value = false;
+ loadData();
+ }
+ });
+ } else {
+ // 缂栬緫
+ update(formData).then(res => {
+ if (res.code === 200) {
+ ElMessage.success("缂栬緫鎴愬姛");
+ dialogVisible.value = false;
+ loadData();
+ }
+ });
+ }
+ } catch (error) {
+ ElMessage.error("鎿嶄綔澶辫触");
+ } finally {
+ submitLoading.value = false;
}
- })
+ };
- calculateResult.value = result
- calculateDialogVisible.value = true
-}
+ const resetForm = () => {
+ Object.assign(formData, {
+ code: "",
+ planName: "",
+ description: "",
+ status: "",
+ isSystemPreset: false,
+ formula: "棰勮鍑哄簱鏁伴噺 - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺",
+ // 璁$畻鍙傛暟
+ considerExistingStock: false,
+ warehouseControl: false,
+ calculateTotalDemand: false,
+ considerSafetyStock: false,
+ considerLockedStock: false,
+ notConsiderMaterialAux: false,
+ negativeStockAsDemand: false,
+ // 姹囨�诲悎骞堕�夐」
+ summaryMaterial: false,
+ summaryAuxAttributes: false,
+ summaryDemandDate: false,
+ });
+ activeTab.value = "demand";
+ };
+ const validateFormula = () => {
+ // 绠�鍗曠殑鍏紡楠岃瘉
+ const formula = formData.formula;
+ if (formula && !/^[a-zA-Z\u4e00-\u9fa5\s\*\+\-\/\(\)\d\.]+$/.test(formula)) {
+ ElMessage.warning("鍏紡鏍煎紡鍙兘涓嶆纭紝璇锋鏌�");
+ }
+ };
-const handleCreatePurchaseOrder = () => {
- calculateDialogVisible.value = false
-}
-const { proxy } = getCurrentInstance();
-const handleExport = () => {
- ElMessageBox.confirm("鍐呭灏嗚瀵煎嚭锛屾槸鍚︾‘璁ゅ鍑猴紵", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ const handleCalculate = row => {
+ currentPlan.value = row;
+ productSelectDialogVisible.value = true;
+ loadProductList();
+ };
+
+ const loadProductList = () => {
+ productLoading.value = true;
+ // 妯℃嫙鍔犺浇浜у搧鏁版嵁
+ listPageCopy({ size: -1 }).then(res => {
+ if (res.code === 200) {
+ productList.value = res.data.records;
+ productLoading.value = false;
+ }
+ });
+ };
+
+ const handleProductSelectionChange = selection => {
+ selectedProducts.value = selection;
+ };
+
+ const handleConfirmProductSelection = () => {
+ if (selectedProducts.value.length === 0) {
+ ElMessage.warning("璇烽�夋嫨瑕佽绠楃殑浜у搧");
+ return;
+ }
+
+ ElMessage.success(`姝e湪璁$畻 ${currentPlan.value.planName} 鐨勯噰璐渶姹�...`);
+ productSelectDialogVisible.value = false;
+
+ // 鏍规嵁閫夋嫨鐨勪骇鍝佸拰璁$畻鍏紡杩涜璁$畻
+ calculateWithSelectedProducts();
+ };
+
+ const calculateWithSelectedProducts = () => {
+ // 妯℃嫙璁$畻杩囩▼
+ // 鏍规嵁閫夋嫨鐨勪骇鍝佹洿鏂拌绠楃粨鏋�
+ const result = selectedProducts.value.map(product => {
+ // 杩欓噷搴旇鏍规嵁瀹為檯鐨勮绠楀叕寮忚繘琛岃绠�
+ // 绀轰緥锛氶璁″嚭搴撴暟閲� - 鐜版湁搴撳瓨 + 瀹夊叏搴撳瓨 - 棰勮鍏ュ簱鏁伴噺
+ const weeklyNetDemand =
+ product.inboundNum -
+ product.inboundNum0 +
+ product.inboundNum -
+ product.inboundNum0;
+ const suggestedPurchase = Math.max(0, weeklyNetDemand);
+
+ return {
+ productCategory: product.productCategory,
+ specificationModel: product.specificationModel,
+ inboundNum0: product.inboundNum0,
+ inboundNum: product.inboundNum,
+ weeklyNetDemand: weeklyNetDemand,
+ suggestedPurchase: suggestedPurchase,
+ };
+ });
+
+ calculateResult.value = result;
+ calculateDialogVisible.value = true;
+ };
+
+ const handleCreatePurchaseOrder = () => {
+ calculateDialogVisible.value = false;
+ };
+ const { proxy } = getCurrentInstance();
+ const handleExport = () => {
+ ElMessageBox.confirm("鍐呭灏嗚瀵煎嚭锛屾槸鍚︾‘璁ゅ鍑猴紵", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
proxy.download("/procurementPlan/export", {}, "閲囪喘璁″垝.xlsx");
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-}
+ };
+ const handleSizeChange = size => {
+ pagination.size = size;
+ loadData();
+ };
-const handleSizeChange = (size) => {
- pagination.size = size
- loadData()
-}
+ const handleCurrentChange = current => {
+ pagination.current = current;
+ loadData();
+ };
-const handleCurrentChange = (current) => {
- pagination.current = current
- loadData()
-}
-
-// 鐢熷懡鍛ㄦ湡
-onMounted(() => {
- loadData()
-})
+ // 鐢熷懡鍛ㄦ湡
+ onMounted(() => {
+ loadData();
+ });
</script>
<style scoped>
-.app-container {
- padding: 20px;
-}
+ .app-container {
+ padding: 20px;
+ }
-.page-header {
- margin-bottom: 20px;
-}
+ .page-header {
+ margin-bottom: 20px;
+ }
-.page-header h2 {
- margin: 0 0 8px 0;
- color: #303133;
- font-size: 24px;
- font-weight: 600;
-}
+ .page-header h2 {
+ margin: 0 0 8px 0;
+ color: #303133;
+ font-size: 24px;
+ font-weight: 600;
+ }
-.page-header p {
- margin: 0;
- color: #909399;
- font-size: 14px;
-}
+ .page-header p {
+ margin: 0;
+ color: #909399;
+ font-size: 14px;
+ }
-.search-card {
- margin-bottom: 20px;
-}
+ .search-card {
+ margin-bottom: 20px;
+ }
-.search-form {
- margin-bottom: 0;
-}
+ .search-form {
+ margin-bottom: 0;
+ }
-.table-card {
- margin-bottom: 20px;
-}
+ .table-card {
+ margin-bottom: 20px;
+ }
-.table-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
-}
+ .table-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ }
-.table-title {
- font-size: 16px;
- font-weight: 600;
- color: #303133;
-}
+ .table-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
-.table-actions {
- display: flex;
- gap: 10px;
-}
+ .table-actions {
+ display: flex;
+ gap: 10px;
+ }
-.pagination-container {
- margin-top: 20px;
- display: flex;
- justify-content: end;
-}
+ .pagination-container {
+ margin-top: 20px;
+ display: flex;
+ justify-content: end;
+ }
-.form-container {
- padding: 0 20px;
-}
+ .form-container {
+ padding: 0 20px;
+ }
-.formula-help {
- margin-top: 5px;
-}
+ .formula-help {
+ margin-top: 5px;
+ }
-.calculate-result {
- padding: 20px 0;
-}
+ .calculate-result {
+ padding: 20px 0;
+ }
-.dialog-footer {
- text-align: right;
-}
+ .dialog-footer {
+ text-align: right;
+ }
-:deep(.el-card__body) {
- padding: 20px;
-}
+ :deep(.el-card__body) {
+ padding: 20px;
+ }
-:deep(.el-table) {
- font-size: 14px;
-}
+ :deep(.el-table) {
+ font-size: 14px;
+ }
-:deep(.el-form-item__label) {
- font-weight: 500;
-}
+ :deep(.el-form-item__label) {
+ font-weight: 500;
+ }
-.form-container {
- padding: 0;
-}
+ .form-container {
+ padding: 0;
+ }
-.form-section {
- margin-bottom: 24px;
- border: 1px solid #e4e7ed;
- border-radius: 6px;
- overflow: hidden;
-}
+ .form-section {
+ margin-bottom: 24px;
+ border: 1px solid #e4e7ed;
+ border-radius: 6px;
+ overflow: hidden;
+ }
-.section-title {
- background-color: #f5f7fa;
- padding: 12px 16px;
- font-weight: 600;
- color: #303133;
- border-bottom: 1px solid #e4e7ed;
-}
+ .section-title {
+ background-color: #f5f7fa;
+ padding: 12px 16px;
+ font-weight: 600;
+ color: #303133;
+ border-bottom: 1px solid #e4e7ed;
+ }
-.form-section .el-form {
- padding: 20px;
-}
+ .form-section .el-form {
+ padding: 20px;
+ }
-.param-tabs {
- padding: 20px;
-}
+ .param-tabs {
+ padding: 20px;
+ }
-.param-tabs :deep(.el-tabs__header) {
- margin-bottom: 20px;
-}
+ .param-tabs :deep(.el-tabs__header) {
+ margin-bottom: 20px;
+ }
-.param-tabs :deep(.el-tabs__item.is-active) {
- color: #f56c6c;
- border-bottom-color: #f56c6c;
-}
+ .param-tabs :deep(.el-tabs__item.is-active) {
+ color: #f56c6c;
+ border-bottom-color: #f56c6c;
+ }
-.checkbox-group {
- display: flex;
- flex-wrap: wrap;
- gap: 16px;
-}
+ .checkbox-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ }
-.checkbox-group .el-checkbox {
- margin-right: 0;
- margin-bottom: 8px;
-}
+ .checkbox-group .el-checkbox {
+ margin-right: 0;
+ margin-bottom: 8px;
+ }
-.formula-input-section {
- padding: 20px;
-}
+ .formula-input-section {
+ padding: 20px;
+ }
-.formula-input-section .el-form-item {
- margin-bottom: 12px;
-}
+ .formula-input-section .el-form-item {
+ margin-bottom: 12px;
+ }
-.formula-help {
- text-align: center;
- margin-top: 8px;
-}
+ .formula-help {
+ text-align: center;
+ margin-top: 8px;
+ }
</style>
diff --git a/src/views/procurementManagement/purchaseOrder/index.vue b/src/views/procurementManagement/purchaseOrder/index.vue
index 7e56cb4..4f9812f 100644
--- a/src/views/procurementManagement/purchaseOrder/index.vue
+++ b/src/views/procurementManagement/purchaseOrder/index.vue
@@ -56,6 +56,13 @@
<el-option label="渚涘簲鍟咮" value="渚涘簲鍟咮" />
</el-select>
</el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿">
+ <el-date-picker v-model="formCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%" />
+ </el-form-item>
<el-form-item label="澶囨敞">
<el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" />
</el-form-item>
@@ -66,7 +73,8 @@
<script setup>
import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { ref, reactive } from 'vue'
+import { ref, reactive, computed } from 'vue'
+import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false)
@@ -81,7 +89,14 @@
const formData = reactive({
supplierName: '',
- remark: ''
+ remark: '',
+ createTime: ''
+})
+const formCreateTimeDate = computed({
+ get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''),
+ set: (value) => {
+ formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : ''
+ }
})
const mockData = [
@@ -122,9 +137,9 @@
const openDialog = (type, row = {}) => {
dialogType.value = type
if (type === 'edit' && row.id) {
- Object.assign(formData, { supplierName: row.supplierName, remark: row.remark })
+ Object.assign(formData, { supplierName: row.supplierName, remark: row.remark, createTime: row.createTime || '' })
} else {
- Object.assign(formData, { supplierName: '', remark: '' })
+ Object.assign(formData, { supplierName: '', remark: '', createTime: dayjs().format('YYYY-MM-DD HH:mm:ss') })
}
dialogVisible.value = true
}
@@ -133,11 +148,11 @@
if (dialogType.value === 'add') {
const newOrder = {
id: Date.now(),
- orderNo: `PO${Date.now()}`,
+ orderNo: '',
supplierName: formData.supplierName,
status: 'draft',
totalAmount: 0,
- createTime: new Date().toLocaleString(),
+ createTime: formData.createTime,
remark: formData.remark
}
tableData.value.unshift(newOrder)
diff --git a/src/views/procurementManagement/qualityInspection/index.vue b/src/views/procurementManagement/qualityInspection/index.vue
index 7628839..aee1d99 100644
--- a/src/views/procurementManagement/qualityInspection/index.vue
+++ b/src/views/procurementManagement/qualityInspection/index.vue
@@ -116,6 +116,18 @@
<el-input v-model="formData.inspector" placeholder="璇疯緭鍏ヨ川妫�鍛樺鍚�" />
</el-form-item>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿">
+ <el-date-picker v-model="formCreateTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
<el-form-item label="澶囨敞">
<el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�" />
</el-form-item>
@@ -126,7 +138,8 @@
<script setup>
import FormDialog from '@/components/Dialog/FormDialog.vue';
-import { ref, reactive } from 'vue'
+import { ref, reactive, computed } from 'vue'
+import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false)
@@ -144,7 +157,14 @@
supplierName: '',
products: [],
inspector: '',
- remark: ''
+ remark: '',
+ createTime: ''
+})
+const formCreateTimeDate = computed({
+ get: () => (formData.createTime ? String(formData.createTime).split(' ')[0] : ''),
+ set: (value) => {
+ formData.createTime = value ? `${value} ${dayjs().format('HH:mm:ss')}` : ''
+ }
})
const mockData = [
@@ -190,15 +210,17 @@
arrivalNo: row.arrivalNo,
supplierName: row.supplierName,
inspector: row.inspector,
- remark: row.remark
+ remark: row.remark,
+ createTime: row.createTime || ''
})
} else {
- Object.assign(formData, {
- arrivalNo: '',
- supplierName: '',
+ Object.assign(formData, {
+ arrivalNo: '',
+ supplierName: '',
products: [],
- inspector: '',
- remark: ''
+ inspector: '',
+ remark: '',
+ createTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
})
}
dialogVisible.value = true
@@ -228,13 +250,13 @@
if (dialogType.value === 'add') {
const newInspection = {
id: Date.now(),
- inspectionNo: `QI${Date.now()}`,
+ inspectionNo: '',
arrivalNo: formData.arrivalNo,
supplierName: formData.supplierName,
status: 'pending',
qualifiedQuantity: totalQualified,
unqualifiedQuantity: totalUnqualified,
- inspectionTime: new Date().toLocaleString(),
+ inspectionTime: formData.createTime,
inspector: formData.inspector,
remark: formData.remark
}
diff --git a/src/views/productManagement/productIdentifier/index.vue b/src/views/productManagement/productIdentifier/index.vue
index 94359e4..d638e7a 100644
--- a/src/views/productManagement/productIdentifier/index.vue
+++ b/src/views/productManagement/productIdentifier/index.vue
@@ -239,6 +239,13 @@
<el-form-item label="鏍囪瘑绫诲瀷">
<span>{{ currentProduct.identifierType }}</span>
</el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿">
+ <el-date-picker v-model="createTimeDate"
+ type="date"
+ placeholder="閫夋嫨鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ style="width: 100%"></el-date-picker>
+ </el-form-item>
<el-form-item label="鐢熸垚鏁伴噺"
prop="generateQuantity">
<el-input-number v-model="generateQuantity"
@@ -356,6 +363,7 @@
<script setup>
import { ref, reactive, computed } from "vue";
+ import dayjs from "dayjs";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, Search, Loading, Download } from "@element-plus/icons-vue";
import Pagination from "@/components/PIMTable/Pagination.vue";
@@ -442,6 +450,13 @@
const generateQuantity = ref(1);
const codeRule = ref("");
const customPrefix = ref("");
+ const createTime = ref(dayjs().format("YYYY-MM-DD HH:mm:ss"));
+ const createTimeDate = computed({
+ get: () => (createTime.value ? String(createTime.value).split(" ")[0] : ""),
+ set: (value) => {
+ createTime.value = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
+ });
const newBatchNo = ref("");
const reassignReason = ref("");
const formRef = ref();
@@ -659,9 +674,9 @@
currentProduct.value.batchNo
}_${String(i).padStart(3, "0")}`;
} else if (codeRule.value === "鏃堕棿鎴�+闅忔満鏁�") {
- identifierCode = `TS_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
+ identifierCode = "";
} else if (codeRule.value === "鑷畾涔夎鍒�") {
- identifierCode = `${customPrefix.value || "CUSTOM"}_${Date.now()}_${i}`;
+ identifierCode = "";
}
newIdentifiers.push({
@@ -672,7 +687,7 @@
identifierType: currentProduct.value.identifierType,
identifierCode: identifierCode,
status: "宸茬敓鎴�",
- generateTime: new Date().toLocaleString(),
+ generateTime: createTime.value,
remark: "鎵归噺鐢熸垚",
});
}
diff --git a/src/views/productionManagement/productionTraceability/index.vue b/src/views/productionManagement/productionTraceability/index.vue
index d8b8f98..aa65286 100644
--- a/src/views/productionManagement/productionTraceability/index.vue
+++ b/src/views/productionManagement/productionTraceability/index.vue
@@ -35,7 +35,7 @@
border>
<el-descriptions-item label="鐢熶骇璁㈠崟鍙�">{{ rowData.productionOrderDto?.npsNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="浜у搧鍚嶇О">{{ rowData.productionOrderDto?.productName || '-' }}</el-descriptions-item>
- <el-descriptions-item label="浜у搧瑙勬牸">{{ rowData.productionOrderDto?.model || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="瑙勬牸鍨嬪彿">{{ rowData.productionOrderDto?.model || '-' }}</el-descriptions-item>
<!-- <el-descriptions-item label="鐗╂枡缂栫爜">{{ rowData.productionOrderDto?.materialCode || '-' }}</el-descriptions-item> -->
<el-descriptions-item label="璁″垝鏁伴噺">{{ rowData.productionOrderDto?.quantity || 0 }} <span class="unit">{{ rowData.productionOrderDto?.unit || '-' }}</span></el-descriptions-item>
<el-descriptions-item label="褰撳墠鐘舵��">
diff --git a/src/views/productionManagement/workOrder/index.vue b/src/views/productionManagement/workOrder/index.vue
index 1e4810a..8c76b2e 100644
--- a/src/views/productionManagement/workOrder/index.vue
+++ b/src/views/productionManagement/workOrder/index.vue
@@ -93,7 +93,7 @@
<span class="info-value">{{ transferCardRowData.productName }}</span>
</div>
<div class="info-item">
- <span class="info-label">浜у搧瑙勬牸</span>
+ <span class="info-label">瑙勬牸鍨嬪彿</span>
<span class="info-value">{{ transferCardRowData.model }}</span>
</div>
<!-- <div class="info-item">
diff --git a/src/views/productionManagement/workOrderManagement/index.vue b/src/views/productionManagement/workOrderManagement/index.vue
index 60fe511..8bc6dc2 100644
--- a/src/views/productionManagement/workOrderManagement/index.vue
+++ b/src/views/productionManagement/workOrderManagement/index.vue
@@ -57,7 +57,7 @@
<span class="info-value">{{ transferCardRowData.productName }}</span>
</div>
<div class="info-item">
- <span class="info-label">浜у搧瑙勬牸</span>
+ <span class="info-label">瑙勬牸鍨嬪彿</span>
<span class="info-value">{{ transferCardRowData.model }}</span>
</div>
<div class="info-item">
diff --git a/src/views/productionPlan/productionPlan/index.vue b/src/views/productionPlan/productionPlan/index.vue
index 4251daa..e5bc1f8 100644
--- a/src/views/productionPlan/productionPlan/index.vue
+++ b/src/views/productionPlan/productionPlan/index.vue
@@ -56,7 +56,7 @@
style="width: 160px;"
@keyup.enter="handleQuery" />
</el-form-item>
- <el-form-item label="浜у搧瑙勬牸:"
+ <el-form-item label="瑙勬牸鍨嬪彿:"
prop="model">
<el-input v-model="searchForm.model"
placeholder="璇疯緭鍏�"
@@ -121,7 +121,7 @@
</el-row>
<el-row :gutter="20">
<el-col>
- <el-form-item label="浜у搧瑙勬牸">
+ <el-form-item label="瑙勬牸鍨嬪彿">
<div class="info-display">{{ mergeForm.model || '-' }}</div>
</el-form-item>
</el-col>
@@ -138,6 +138,12 @@
:max="sumAssignedQuantity"
@change="onBlur"
style="width: 100%" />
+ </el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿">
+ <el-date-picker v-model="mergeCreateTimeDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ style="width: 100%" />
</el-form-item>
</el-form>
<template #footer>
@@ -173,7 +179,7 @@
prop="mpsNo">
<el-input v-model="form.mpsNo"
disabled
- placeholder="鏂板鍚庤嚜鍔ㄧ敓鎴�" />
+ placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" />
</el-form-item>
<el-form-item label="浜у搧鍚嶇О"
prop="productId">
@@ -186,7 +192,7 @@
@change="handleProductChange"
style="width: 100%" />
</el-form-item>
- <el-form-item label="浜у搧瑙勬牸"
+ <el-form-item label="瑙勬牸鍨嬪彿"
prop="productModelId">
<el-select v-model="form.productModelId"
@change="handleChangeSpecification"
@@ -226,6 +232,14 @@
value-format="YYYY-MM-DD"
style="width: 100%"
placeholder="璇烽�夋嫨鎵胯鏃ユ湡" />
+ </el-form-item>
+ <el-form-item label="鍒涘缓鏃堕棿"
+ prop="createTime">
+ <el-date-picker v-model="formCreateTimeDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ style="width: 100%"
+ placeholder="璇烽�夋嫨鍒涘缓鏃堕棿" />
</el-form-item>
<el-form-item label="澶囨敞"
prop="remark">
@@ -321,7 +335,7 @@
},
},
{
- label: "浜у搧瑙勬牸",
+ label: "瑙勬牸鍨嬪彿",
prop: "model",
width: "150px",
className: "spec-cell",
@@ -430,6 +444,7 @@
Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
mergeForm.planCompleteTime = row.requiredDate || "";
mergeForm.productId = row.productId || "";
+ mergeForm.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
mergeForm.ids = [row.id];
sumAssignedQuantity.value =
Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
@@ -473,6 +488,13 @@
totalAssignedQuantity: 0,
planCompleteTime: "",
productId: "",
+ createTime: "",
+ });
+ const mergeCreateTimeDate = computed({
+ get: () => (mergeForm.createTime ? String(mergeForm.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ mergeForm.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
// 瀵煎叆鐩稿叧
@@ -503,11 +525,18 @@
requiredDate: "",
promisedDeliveryDate: "",
remark: "",
+ createTime: "",
+ });
+ const formCreateTimeDate = computed({
+ get: () => (form.createTime ? String(form.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ form.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
const rules = reactive({
productId: [{ required: true, message: "璇烽�夋嫨浜у搧", trigger: "change" }],
productModelId: [
- { required: true, message: "璇烽�夋嫨浜у搧瑙勬牸", trigger: "change" },
+ { required: true, message: "璇烽�夋嫨瑙勬牸鍨嬪彿", trigger: "change" },
],
qtyRequired: [{ required: true, message: "璇疯緭鍏ユ暟閲�", trigger: "blur" }],
requiredDate: [
@@ -686,17 +715,17 @@
});
};
- // 閫変腑鐨勪骇鍝佽鏍糏D
+ // 閫変腑鐨勮鏍煎瀷鍙稩D
const selectedProductModelId = ref("");
// 琛ㄦ牸閫夋嫨鏁版嵁
const handleSelectionChange = selection => {
selectedRows.value = selection;
- // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑浜у搧瑙勬牸ID
+ // 濡傛灉鏈夐�変腑鐨勮锛岃褰曠涓�涓�変腑琛岀殑瑙勬牸鍨嬪彿ID
if (selection.length > 0) {
selectedProductModelId.value = selection[0].productModelId;
} else {
- // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌轰骇鍝佽鏍糏D
+ // 濡傛灉娌℃湁閫変腑鐨勮锛屾竻绌鸿鏍煎瀷鍙稩D
selectedProductModelId.value = "";
}
};
@@ -717,7 +746,7 @@
if (!selectedProductModelId.value) {
return true;
}
- // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈変骇鍝佽鏍糏D鐩稿悓鐨勮鎵嶅彲閫夋嫨
+ // 濡傛灉鏈夐�変腑鐨勮锛屽彧鏈夎鏍煎瀷鍙稩D鐩稿悓鐨勮鎵嶅彲閫夋嫨
return row.productModelId === selectedProductModelId.value;
};
// 鎷夊彇鏁版嵁鎸夐挳鎿嶄綔
@@ -889,6 +918,7 @@
requiredDate: "",
promisedDeliveryDate: "",
remark: "",
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
});
dialogVisible.value = true;
fetchProductOptions();
@@ -909,6 +939,7 @@
requiredDate: row.requiredDate || "",
promisedDeliveryDate: row.promisedDeliveryDate || "",
remark: row.remark || "",
+ createTime: row.createTime || "",
});
dialogVisible.value = true;
fetchProductOptions();
diff --git a/src/views/qualityManagement/finalInspection/index.vue b/src/views/qualityManagement/finalInspection/index.vue
index b0e222b..4a59fa4 100644
--- a/src/views/qualityManagement/finalInspection/index.vue
+++ b/src/views/qualityManagement/finalInspection/index.vue
@@ -1,59 +1,111 @@
<template>
<div class="app-container">
<div class="search_form mb20">
- <div>
- <span class="search_title">浜у搧鍚嶇О锛�</span>
- <el-input
- v-model="searchForm.productName"
- style="width: 240px"
- placeholder="璇疯緭鍏ヤ骇鍝佸悕绉版悳绱�"
- @change="handleQuery"
- 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"/>
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储
- </el-button
- >
- </div>
- <div>
- <el-button type="primary" @click="openForm('add')">鏂板</el-button>
+ <el-form ref="searchFormRef"
+ :model="searchForm"
+ class="demo-form-inline">
+ <el-row :gutter="20">
+ <el-col :span="4">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productName">
+ <el-input v-model="searchForm.productName"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ヤ骇鍝佸悕绉版悳绱�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="妫�娴嬫棩鏈�"
+ prop="entryDate">
+ <el-date-picker v-model="searchForm.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="daterange"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="changeDaterange" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="閿�鍞崟鍙�"
+ prop="salesContractNo">
+ <el-input v-model="searchForm.salesContractNo"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ラ攢鍞崟鍙锋悳绱�"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <el-col :span="4">
+ <el-form-item label="鐢熶骇宸ュ崟鍙�"
+ prop="workOrderNo">
+ <el-input v-model="searchForm.workOrderNo"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ョ敓浜у伐鍗曞彿鎼滅储"
+ clearable />
+ </el-form-item>
+ </el-col>
+ <!-- 鎸夐挳 -->
+ <el-col :span="4">
+ <el-form-item>
+ <el-button type="primary"
+ @click="getList">
+ 鎼滅储
+ </el-button>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <div class="actions">
+ <el-button type="primary"
+ @click="openForm('add')">鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</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>
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"></PIMTable>
</div>
- <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="30%"
+ <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="30%"
@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-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 type="primary"
+ @click="submitForm">纭</el-button>
<el-button @click="closeDia">鍙栨秷</el-button>
</div>
</template>
@@ -62,296 +114,320 @@
</template>
<script setup>
-import {Search} from "@element-plus/icons-vue";
-import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
-import InspectionFormDia from "@/views/qualityManagement/finalInspection/components/inspectionFormDia.vue";
-import FormDia from "@/views/qualityManagement/finalInspection/components/formDia.vue";
-import {ElMessageBox} from "element-plus";
-import {
- downloadQualityInspect,
- qualityInspectDel,
- qualityInspectListPage, qualityInspectUpdate,
- submitQualityInspect
-} from "@/api/qualityManagement/rawMaterialInspection.js";
-import FilesDia from "@/views/qualityManagement/finalInspection/components/filesDia.vue";
-import dayjs from "dayjs";
-import {userListNoPage} from "@/api/system/user.js";
-import useUserStore from "@/store/modules/user";
+ import { Search } from "@element-plus/icons-vue";
+ import {
+ onMounted,
+ ref,
+ reactive,
+ toRefs,
+ getCurrentInstance,
+ nextTick,
+ } from "vue";
+ import InspectionFormDia from "@/views/qualityManagement/finalInspection/components/inspectionFormDia.vue";
+ import FormDia from "@/views/qualityManagement/finalInspection/components/formDia.vue";
+ import { ElMessageBox } from "element-plus";
+ import {
+ downloadQualityInspect,
+ qualityInspectDel,
+ qualityInspectListPage,
+ qualityInspectUpdate,
+ submitQualityInspect,
+ } from "@/api/qualityManagement/rawMaterialInspection.js";
+ import FilesDia from "@/views/qualityManagement/finalInspection/components/filesDia.vue";
+ import dayjs from "dayjs";
+ import { userListNoPage } from "@/api/system/user.js";
+ import useUserStore from "@/store/modules/user";
-const data = reactive({
- searchForm: {
- productName: "",
- entryDate: undefined, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- rules: {
- checkName: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
- },
-});
-const {searchForm} = toRefs(data);
-const tableColumn = ref([
- {
- label: "妫�娴嬫棩鏈�",
- prop: "checkTime",
- width: 120
- },
- {
- label: "閿�鍞崟鍙�",
- prop: "salesContractNo",
- width: 120
- },
- {
- label: "鐢熶骇宸ュ崟鍙�",
- prop: "workOrderNo",
- width: 120
- },
- {
- label: "妫�楠屽憳",
- prop: "checkName",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "model",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鎬绘暟閲�",
- prop: "quantity",
- width: 100
- },
- {
- label: "鍚堟牸鏁伴噺",
- prop: "qualifiedQuantity",
- width: 100
- },
- {
- label: "涓嶅悎鏍兼暟閲�",
- prop: "unqualifiedQuantity",
- width: 100
- },
- {
- label: "妫�娴嬪崟浣�",
- prop: "checkCompany",
- width: 120
- },
- {
- label: "鍚堟牸鐜�",
- prop: "passRate",
- width: 100,
- dataType: "tag",
- formatData: (params) => {
- if (params == null || params === '') return '鈥�';
- const n = Number(params);
- if (Number.isNaN(n)) return '鈥�';
- return `${n.toFixed(2)}%`;
+ const data = reactive({
+ searchForm: {
+ productName: "",
+ salesContractNo: "",
+ workOrderNo: "",
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
},
- formatType: (params) => {
- if (params == null || params === '') return 'info';
- const n = Number(params);
- if (Number.isNaN(n)) return 'info';
- if (n === 100) return 'success';
- if (n >= 75) return 'primary';
- if (n >= 50) return 'warning';
- if (n >= 25) return 'danger';
- return 'danger';
+ rules: {
+ checkName: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
- },
- {
- label: "鎻愪氦鐘舵��",
- prop: "inspectState",
- dataType: "tag",
- formatData: (params) => {
- if (params) {
- return "宸叉彁浜�";
- } else {
- return "鏈彁浜�";
- }
+ });
+ const { searchForm } = toRefs(data);
+ const tableColumn = ref([
+ {
+ label: "妫�娴嬫棩鏈�",
+ prop: "checkTime",
+ width: 120,
},
- formatType: (params) => {
- if (params) {
- return "success";
- } else {
- return "info";
- }
+ {
+ label: "閿�鍞崟鍙�",
+ prop: "salesContractNo",
+ width: 120,
},
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openForm("edit", row);
- },
- disabled: (row) => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
+ {
+ label: "鐢熶骇宸ュ崟鍙�",
+ prop: "workOrderNo",
+ width: 120,
+ },
+ {
+ label: "妫�楠屽憳",
+ prop: "checkName",
+ },
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "productName",
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鎬绘暟閲�",
+ prop: "quantity",
+ width: 100,
+ },
+ {
+ label: "鍚堟牸鏁伴噺",
+ prop: "qualifiedQuantity",
+ width: 100,
+ },
+ {
+ label: "涓嶅悎鏍兼暟閲�",
+ prop: "unqualifiedQuantity",
+ width: 100,
+ },
+ {
+ label: "鍚堟牸鐜�",
+ prop: "passRate",
+ width: 100,
+ dataType: "tag",
+ formatType: params => {
+ if (!params) return "";
+ const rate = parseFloat(params);
+ if (rate < 90) {
+ return "danger";
+ } else if (rate === 100) {
+ return "success";
+ } else {
+ return "warning";
}
},
- {
- name: "鏌ョ湅",
- type: "text",
- clickFun: (row) => {
- openForm("view", row);
- },
- },
- {
- name: "闄勪欢",
- type: "text",
- clickFun: (row) => {
- openFilesFormDia(row);
- },
- },
- {
- name: "鎻愪氦",
- type: "text",
- clickFun: (row) => {
- submit(row.id);
- },
- disabled: (row) => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
+ },
+ {
+ label: "妫�娴嬪崟浣�",
+ prop: "checkCompany",
+ width: 120,
+ },
+ {
+ label: "妫�娴嬬粨鏋�",
+ prop: "checkResult",
+ dataType: "tag",
+ formatType: params => {
+ if (params == "涓嶅悎鏍�") {
+ return "danger";
+ } else if (params == "鍚堟牸") {
+ return "success";
+ } else {
+ return "danger";
}
},
- {
- name: "鍒嗛厤妫�楠屽憳",
- type: "text",
- clickFun: (row) => {
- if (!row.checkName) {
- open(row)
- } else {
- proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
- }
- },
- disabled: (row) => {
- return row.inspectState == 1 || row.checkName;
+ },
+ {
+ label: "鎻愪氦鐘舵��",
+ prop: "inspectState",
+ formatData: params => {
+ if (params) {
+ return "宸叉彁浜�";
+ } else {
+ return "鏈彁浜�";
}
},
- {
- name: "涓嬭浇",
- type: "text",
- clickFun: (row) => {
- downLoadFile(row);
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 280,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
+ disabled: row => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ },
},
- },
- ],
- },
-]);
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const currentRow = ref(null)
-const page = reactive({
- current: 1,
- size: 100,
- total: 0
-});
-const formDia = ref()
-const filesDia = ref()
-const inspectionFormDia = ref()
-const {proxy} = getCurrentInstance()
-const userStore = useUserStore()
-const userList = ref([]);
-const form = ref({
- checkName: ""
-});
-const dialogFormVisible = ref(false);
+ {
+ name: "鏌ョ湅",
+ type: "text",
+ clickFun: row => {
+ openForm("view", row);
+ },
+ },
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: row => {
+ openFilesFormDia(row);
+ },
+ },
+ {
+ name: "鎻愪氦",
+ type: "text",
+ clickFun: row => {
+ submit(row.id);
+ },
+ disabled: row => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ },
+ },
+ {
+ name: "鍒嗛厤妫�楠屽憳",
+ type: "text",
+ clickFun: row => {
+ if (!row.checkName) {
+ open(row);
+ } else {
+ proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
+ }
+ },
+ disabled: row => {
+ return row.inspectState == 1 || row.checkName;
+ },
+ },
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: row => {
+ downLoadFile(row);
+ },
+ },
+ ],
+ },
+ ]);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ const currentRow = ref(null);
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ const formDia = ref();
+ const filesDia = ref();
+ const inspectionFormDia = ref();
+ const { proxy } = getCurrentInstance();
+ const userStore = useUserStore();
+ const userList = ref([]);
+ const form = ref({
+ checkName: "",
+ });
+ const dialogFormVisible = ref(false);
-const changeDaterange = (value) => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).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;
- const params = {...searchForm.value, ...page};
- params.entryDate = undefined
- qualityInspectListPage({...params, inspectType: 2}).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 changeDaterange = value => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).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;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined;
+ qualityInspectListPage({ ...params, inspectType: 2 })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records.map(item => {
+ const quantity = parseFloat(item.quantity);
+ const qualifiedQuantity = parseFloat(item.qualifiedQuantity);
+ let passRate = null;
+ if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) {
+ passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%";
+ }
+ return {
+ ...item,
+ passRate: passRate,
+ };
+ });
+ 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 openInspectionForm = (type, row) => {
- nextTick(() => {
- inspectionFormDia.value?.openDialog(type, row)
- })
-};
-// 鎵撳紑闄勪欢寮规
-const openFilesFormDia = (type, row) => {
- nextTick(() => {
- filesDia.value?.openDialog(type, row)
- })
-};
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row);
+ });
+ };
+ // 鎵撳紑鏂板妫�楠屽脊妗�
+ const openInspectionForm = (type, row) => {
+ nextTick(() => {
+ inspectionFormDia.value?.openDialog(type, row);
+ });
+ };
+ // 鎵撳紑闄勪欢寮规
+ const openFilesFormDia = (type, row) => {
+ nextTick(() => {
+ filesDia.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",
- })
+ // 鍒犻櫎
+ 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(() => {
- qualityInspectDel(ids).then((res) => {
+ qualityInspectDel(ids).then(res => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -359,78 +435,88 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ };
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- proxy.download("/quality/qualityInspect/export", {inspectType: 2}, "鍑哄巶妫�楠�.xlsx");
+ proxy.download(
+ "/quality/qualityInspect/export",
+ { inspectType: 2 },
+ "鍑哄巶妫�楠�.xlsx"
+ );
})
.catch(() => {
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 => {
+ // 鎻愪环
+ const submit = async id => {
+ const res = await submitQualityInspect({ id: id });
+ if (res.code === 200) {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
getList();
- })
- }
-};
+ }
+ };
-const open = async (row) => {
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- currentRow.value = row
- dialogFormVisible.value = true
-}
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
-const downLoadFile = (row) => {
- downloadQualityInspect({id: row.id}).then((blobData) => {
- const blob = new Blob([blobData], {
- type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
- })
- const downloadUrl = window.URL.createObjectURL(blob)
+ const submitForm = () => {
+ if (currentRow.value) {
+ const data = {
+ ...form.value,
+ id: currentRow.value.id,
+ };
+ qualityInspectUpdate(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ }
+ };
- const link = document.createElement('a')
- link.href = downloadUrl
- link.download = '鍘熸潗鏂欐楠屾姤鍛�.docx'
- document.body.appendChild(link)
- link.click()
+ const open = async row => {
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ currentRow.value = row;
+ dialogFormVisible.value = true;
+ };
- document.body.removeChild(link)
- window.URL.revokeObjectURL(downloadUrl)
- })
-};
-onMounted(() => {
- getList();
-});
+ const downLoadFile = row => {
+ downloadQualityInspect({ id: row.id }).then(blobData => {
+ const blob = new Blob([blobData], {
+ type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ });
+ const downloadUrl = window.URL.createObjectURL(blob);
+
+ 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();
+ });
</script>
-<style scoped></style>
+<style scoped lang="scss">
+ .actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 10px;
+ }
+</style>
diff --git a/src/views/qualityManagement/nearExpiryReturn/index.vue b/src/views/qualityManagement/nearExpiryReturn/index.vue
index 93e19c2..26dc747 100644
--- a/src/views/qualityManagement/nearExpiryReturn/index.vue
+++ b/src/views/qualityManagement/nearExpiryReturn/index.vue
@@ -1,213 +1,257 @@
<template>
<div class="app-container">
- <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
- <el-form-item label="浜у搧鍚嶇О" prop="productName">
- <el-input
- v-model="queryParams.productName"
- placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
- clearable
- @keyup.enter.native="handleQuery"
- />
+ <el-form :model="queryParams"
+ ref="queryForm"
+ :inline="true"
+ v-show="showSearch"
+ label-width="68px">
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productName">
+ <el-input v-model="queryParams.productName"
+ placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+ clearable
+ @keyup.enter.native="handleQuery" />
</el-form-item>
- <el-form-item label="鎵规鍙�" prop="batchNumber">
- <el-input
- v-model="queryParams.batchNumber"
- placeholder="璇疯緭鍏ユ壒娆″彿"
- clearable
- @keyup.enter.native="handleQuery"
- />
+ <el-form-item label="鎵规鍙�"
+ prop="batchNumber">
+ <el-input v-model="queryParams.batchNumber"
+ placeholder="璇疯緭鍏ユ壒娆″彿"
+ clearable
+ @keyup.enter.native="handleQuery" />
</el-form-item>
- <el-form-item label="閫�鍥炴棩鏈�" prop="returnDate">
- <el-date-picker
- clearable
- v-model="queryParams.returnDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
+ <el-form-item label="閫�鍥炴棩鏈�"
+ prop="returnDate">
+ <el-date-picker clearable
+ v-model="queryParams.returnDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
</el-date-picker>
</el-form-item>
<el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
- <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+ <el-button type="primary"
+ icon="Search"
+ @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh"
+ @click="resetQuery">閲嶇疆</el-button>
</el-form-item>
</el-form>
-
- <el-row :gutter="10" class="mb8">
+ <el-row :gutter="10"
+ class="mb8">
<el-col :span="1.5">
- <el-button
- type="primary"
- plain
- icon="Plus"
- @click="handleAdd"
- >鏂板</el-button>
+ <el-button type="primary"
+ plain
+ icon="Plus"
+ @click="handleAdd">鏂板</el-button>
</el-col>
<el-col :span="1.5">
- <el-button
- type="success"
- plain
- icon="Edit"
- :disabled="single"
- @click="handleUpdate"
- >淇敼</el-button>
+ <el-button type="success"
+ plain
+ icon="Edit"
+ :disabled="single"
+ @click="handleUpdate">淇敼</el-button>
</el-col>
<el-col :span="1.5">
- <el-button
- type="danger"
- plain
- icon="Delete"
- :disabled="multiple"
- @click="handleDelete"
- >鍒犻櫎</el-button>
+ <el-button type="danger"
+ plain
+ icon="Delete"
+ :disabled="multiple"
+ @click="handleDelete">鍒犻櫎</el-button>
</el-col>
<el-col :span="1.5">
- <el-button
- type="warning"
- plain
- icon="Download"
- @click="handleExport"
- >瀵煎嚭</el-button>
+ <el-button type="warning"
+ plain
+ icon="Download"
+ @click="handleExport">瀵煎嚭</el-button>
</el-col>
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+ <right-toolbar v-model:showSearch="showSearch"
+ @queryTable="getList"></right-toolbar>
</el-row>
-
- <el-table v-loading="loading" :data="nearExpiryReturnList" @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="搴忓彿" type="index" width="50" align="center" />
- <el-table-column label="浜у搧鍚嶇О" prop="productName" />
- <el-table-column label="浜у搧瑙勬牸" prop="productSpec" />
- <el-table-column label="鎵规鍙�" prop="batchNumber" />
- <el-table-column label="鐢熶骇鏃ユ湡" prop="productionDate" align="center">
+ <el-table v-loading="loading"
+ :data="nearExpiryReturnList"
+ @selection-change="handleSelectionChange">
+ <el-table-column type="selection"
+ width="55"
+ align="center" />
+ <el-table-column label="搴忓彿"
+ type="index"
+ width="50"
+ align="center" />
+ <el-table-column label="浜у搧鍚嶇О"
+ prop="productName" />
+ <el-table-column label="瑙勬牸鍨嬪彿"
+ prop="productSpec" />
+ <el-table-column label="鎵规鍙�"
+ prop="batchNumber" />
+ <el-table-column label="鐢熶骇鏃ユ湡"
+ prop="productionDate"
+ align="center">
<template #default="scope">
<span>{{ parseTime(scope.row.productionDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
- <el-table-column label="鍒版湡鏃ユ湡" prop="expiryDate" align="center">
+ <el-table-column label="鍒版湡鏃ユ湡"
+ prop="expiryDate"
+ align="center">
<template #default="scope">
<span>{{ parseTime(scope.row.expiryDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
- <el-table-column label="閫�鍥炴暟閲�" prop="returnQuantity" />
- <el-table-column label="閫�鍥炲師鍥�" prop="returnReason" />
- <el-table-column label="閫�鍥炴棩鏈�" prop="returnDate" align="center">
+ <el-table-column label="閫�鍥炴暟閲�"
+ prop="returnQuantity" />
+ <el-table-column label="閫�鍥炲師鍥�"
+ prop="returnReason" />
+ <el-table-column label="閫�鍥炴棩鏈�"
+ prop="returnDate"
+ align="center">
<template #default="scope">
<span>{{ parseTime(scope.row.returnDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
- <el-table-column label="澶勭悊鐘舵��" prop="status" align="center">
+ <el-table-column label="澶勭悊鐘舵��"
+ prop="status"
+ align="center">
<template #default="scope">
- <dict-tag :options="statusOptions" :value="scope.row.status"/>
+ <dict-tag :options="statusOptions"
+ :value="scope.row.status" />
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <el-table-column label="鎿嶄綔"
+ align="center"
+ class-name="small-padding fixed-width">
<template #default="scope">
- <el-button size="mini" type="text" icon="Edit" @click="handleUpdate(scope.row)">淇敼</el-button>
- <el-button size="mini" type="text" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+ <el-button size="mini"
+ type="text"
+ icon="Edit"
+ @click="handleUpdate(scope.row)">淇敼</el-button>
+ <el-button size="mini"
+ type="text"
+ icon="Delete"
+ @click="handleDelete(scope.row)">鍒犻櫎</el-button>
</template>
</el-table-column>
</el-table>
-
- <pagination
- v-show="total>0"
- :total="total"
- v-model:page="queryParams.pageNum"
- v-model:limit="queryParams.pageSize"
- @pagination="getList"
- />
-
+ <pagination v-show="total>0"
+ :total="total"
+ v-model:page="queryParams.pageNum"
+ v-model:limit="queryParams.pageSize"
+ @pagination="getList" />
<!-- 娣诲姞鎴栦慨鏀逛复鏈熼��鍥炲彴璐﹀璇濇 -->
- <el-dialog :title="title" v-model="open" width="800px" append-to-body>
- <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
+ <el-dialog :title="title"
+ v-model="open"
+ width="800px"
+ append-to-body>
+ <el-form ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-width="100px">
<el-row>
<el-col :span="12">
- <el-form-item label="浜у搧鍚嶇О" prop="productName">
- <el-input v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
+ <el-form-item label="浜у搧鍚嶇О"
+ prop="productName">
+ <el-input v-model="form.productName"
+ placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="浜у搧瑙勬牸" prop="productSpec">
- <el-input v-model="form.productSpec" placeholder="璇疯緭鍏ヤ骇鍝佽鏍�" />
+ <el-form-item label="瑙勬牸鍨嬪彿"
+ prop="productSpec">
+ <el-input v-model="form.productSpec"
+ placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
- <el-form-item label="鎵规鍙�" prop="batchNumber">
- <el-input v-model="form.batchNumber" placeholder="璇疯緭鍏ユ壒娆″彿" />
+ <el-form-item label="鎵规鍙�"
+ prop="batchNumber">
+ <el-input v-model="form.batchNumber"
+ placeholder="璇疯緭鍏ユ壒娆″彿" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="閫�鍥炴暟閲�" prop="returnQuantity">
- <el-input-number v-model="form.returnQuantity" controls-position="right" :min="1" />
+ <el-form-item label="閫�鍥炴暟閲�"
+ prop="returnQuantity">
+ <el-input-number v-model="form.returnQuantity"
+ controls-position="right"
+ :min="1" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
- <el-form-item label="鐢熶骇鏃ユ湡" prop="productionDate">
- <el-date-picker
- clearable
- v-model="form.productionDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨鐢熶骇鏃ユ湡">
+ <el-form-item label="鐢熶骇鏃ユ湡"
+ prop="productionDate">
+ <el-date-picker clearable
+ v-model="form.productionDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鐢熶骇鏃ユ湡">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鍒版湡鏃ユ湡" prop="expiryDate">
- <el-date-picker
- clearable
- v-model="form.expiryDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨鍒版湡鏃ユ湡">
+ <el-form-item label="鍒版湡鏃ユ湡"
+ prop="expiryDate">
+ <el-date-picker clearable
+ v-model="form.expiryDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨鍒版湡鏃ユ湡">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
- <el-form-item label="閫�鍥炴棩鏈�" prop="returnDate">
- <el-date-picker
- clearable
- v-model="form.returnDate"
- type="date"
- value-format="YYYY-MM-DD"
- placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
+ <el-form-item label="閫�鍥炴棩鏈�"
+ prop="returnDate">
+ <el-date-picker clearable
+ v-model="form.returnDate"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨閫�鍥炴棩鏈�">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="澶勭悊鐘舵��" prop="status">
- <el-select v-model="form.status" placeholder="璇烽�夋嫨澶勭悊鐘舵��">
- <el-option
- v-for="dict in statusOptions"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- ></el-option>
+ <el-form-item label="澶勭悊鐘舵��"
+ prop="status">
+ <el-select v-model="form.status"
+ placeholder="璇烽�夋嫨澶勭悊鐘舵��">
+ <el-option v-for="dict in statusOptions"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
- <el-form-item label="閫�鍥炲師鍥�" prop="returnReason">
- <el-input v-model="form.returnReason" type="textarea" placeholder="璇疯緭鍏ラ��鍥炲師鍥�" />
+ <el-form-item label="閫�鍥炲師鍥�"
+ prop="returnReason">
+ <el-input v-model="form.returnReason"
+ type="textarea"
+ placeholder="璇疯緭鍏ラ��鍥炲師鍥�" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
- <el-form-item label="澶囨敞" prop="remark">
- <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ娉�" />
+ <el-form-item label="澶囨敞"
+ prop="remark">
+ <el-input v-model="form.remark"
+ type="textarea"
+ placeholder="璇疯緭鍏ュ娉�" />
</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 type="primary"
+ @click="submitForm">纭� 瀹�</el-button>
<el-button @click="cancel">鍙� 娑�</el-button>
</div>
</template>
@@ -216,180 +260,186 @@
</template>
<script setup name="NearExpiryReturn">
-import { ref, reactive, onMounted } from "vue";
-import { ElMessageBox } from "element-plus";
-// API鎺ュ彛宸茬Щ闄わ紝涓嶅啀璋冪敤鍚庣鎺ュ彛
+ import { ref, reactive, onMounted } from "vue";
+ import { ElMessageBox } from "element-plus";
+ // API鎺ュ彛宸茬Щ闄わ紝涓嶅啀璋冪敤鍚庣鎺ュ彛
-const { proxy } = getCurrentInstance();
-const { parseTime } = proxy;
+ const { proxy } = getCurrentInstance();
+ const { parseTime } = proxy;
-const nearExpiryReturnList = ref([]);
-const open = ref(false);
-const loading = ref(true);
-const showSearch = ref(true);
-const ids = ref([]);
-const single = ref(true);
-const multiple = ref(true);
-const total = ref(0);
-const title = ref("");
+ const nearExpiryReturnList = ref([]);
+ const open = ref(false);
+ const loading = ref(true);
+ const showSearch = ref(true);
+ const ids = ref([]);
+ const single = ref(true);
+ const multiple = ref(true);
+ const total = ref(0);
+ const title = ref("");
-// 鐘舵�佸瓧鍏�
-const statusOptions = ref([
- { label: "寰呭鐞�", value: "0" },
- { label: "澶勭悊涓�", value: "1" },
- { label: "宸插畬鎴�", value: "2" }
-]);
+ // 鐘舵�佸瓧鍏�
+ const statusOptions = ref([
+ { label: "寰呭鐞�", value: "0" },
+ { label: "澶勭悊涓�", value: "1" },
+ { label: "宸插畬鎴�", value: "2" },
+ ]);
-const data = reactive({
- form: {},
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- productName: null,
- batchNumber: null,
- returnDate: null
- },
- rules: {
- productName: [
- { required: true, message: "浜у搧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }
- ],
- productSpec: [
- { required: true, message: "浜у搧瑙勬牸涓嶈兘涓虹┖", trigger: "blur" }
- ],
- batchNumber: [
- { required: true, message: "鎵规鍙蜂笉鑳戒负绌�", trigger: "blur" }
- ],
- returnQuantity: [
- { required: true, message: "閫�鍥炴暟閲忎笉鑳戒负绌�", trigger: "blur" }
- ],
- productionDate: [
- { required: true, message: "鐢熶骇鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" }
- ],
- expiryDate: [
- { required: true, message: "鍒版湡鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" }
- ],
- returnDate: [
- { required: true, message: "閫�鍥炴棩鏈熶笉鑳戒负绌�", trigger: "blur" }
- ],
- returnReason: [
- { required: true, message: "閫�鍥炲師鍥犱笉鑳戒负绌�", trigger: "blur" }
- ],
- status: [
- { required: true, message: "澶勭悊鐘舵�佷笉鑳戒负绌�", trigger: "change" }
- ]
- }
-});
-
-const { queryParams, form, rules } = toRefs(data);
-
-/** 鏌ヨ涓存湡閫�鍥炲彴璐﹀垪琛� */
-function getList() {
- loading.value = true;
- // 涓嶈皟鐢ㄦ帴鍙o紝杩斿洖绌烘暟鎹�
- nearExpiryReturnList.value = [];
- total.value = 0;
- loading.value = false;
-}
-
-// 鍙栨秷鎸夐挳
-function cancel() {
- open.value = false;
- reset();
-}
-
-// 琛ㄥ崟閲嶇疆
-function reset() {
- form.value = {
- id: null,
- productName: null,
- productSpec: null,
- batchNumber: null,
- productionDate: null,
- expiryDate: null,
- returnQuantity: null,
- returnReason: null,
- returnDate: null,
- status: null,
- remark: null
- };
- proxy.resetForm("formRef");
-}
-
-/** 鎼滅储鎸夐挳鎿嶄綔 */
-function handleQuery() {
- queryParams.value.pageNum = 1;
- getList();
-}
-
-/** 閲嶇疆鎸夐挳鎿嶄綔 */
-function resetQuery() {
- proxy.resetForm("queryForm");
- handleQuery();
-}
-
-// 澶氶�夋閫変腑鏁版嵁
-function handleSelectionChange(selection) {
- ids.value = selection.map(item => item.id);
- single.value = selection.length !== 1;
- multiple.value = !selection.length;
-}
-
-/** 鏂板鎸夐挳鎿嶄綔 */
-function handleAdd() {
- reset();
- open.value = true;
- title.value = "娣诲姞涓存湡閫�鍥炲彴璐�";
-}
-
-/** 淇敼鎸夐挳鎿嶄綔 */
-function handleUpdate(row) {
- reset();
- // 涓嶈皟鐢ㄦ帴鍙o紝鐩存帴浣跨敤浼犲叆鐨勬暟鎹�
- if (row) {
- form.value = { ...row };
- open.value = true;
- title.value = "淇敼涓存湡閫�鍥炲彴璐�";
- }
-}
-
-/** 鎻愪氦鎸夐挳 */
-function submitForm() {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
- if (form.value.id != null) {
- proxy.$modal.msgSuccess("淇敼鎴愬姛");
- } else {
- proxy.$modal.msgSuccess("鏂板鎴愬姛");
- }
- open.value = false;
- getList();
- }
+ const data = reactive({
+ form: {},
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ productName: null,
+ batchNumber: null,
+ returnDate: null,
+ },
+ rules: {
+ productName: [
+ { required: true, message: "浜у搧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" },
+ ],
+ productSpec: [
+ { required: true, message: "瑙勬牸鍨嬪彿涓嶈兘涓虹┖", trigger: "blur" },
+ ],
+ batchNumber: [
+ { required: true, message: "鎵规鍙蜂笉鑳戒负绌�", trigger: "blur" },
+ ],
+ returnQuantity: [
+ { required: true, message: "閫�鍥炴暟閲忎笉鑳戒负绌�", trigger: "blur" },
+ ],
+ productionDate: [
+ { required: true, message: "鐢熶骇鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" },
+ ],
+ expiryDate: [
+ { required: true, message: "鍒版湡鏃ユ湡涓嶈兘涓虹┖", trigger: "blur" },
+ ],
+ returnDate: [
+ { required: true, message: "閫�鍥炴棩鏈熶笉鑳戒负绌�", trigger: "blur" },
+ ],
+ returnReason: [
+ { required: true, message: "閫�鍥炲師鍥犱笉鑳戒负绌�", trigger: "blur" },
+ ],
+ status: [
+ { required: true, message: "澶勭悊鐘舵�佷笉鑳戒负绌�", trigger: "change" },
+ ],
+ },
});
-}
-/** 鍒犻櫎鎸夐挳鎿嶄綔 */
-function handleDelete(row) {
- const deleteIds = row.id || ids.value;
- ElMessageBox.confirm('鏄惁纭鍒犻櫎涓存湡閫�鍥炲彴璐︾紪鍙蜂负"' + deleteIds + '"鐨勬暟鎹」锛�', "璀﹀憡", {
- confirmButtonText: "纭畾",
- cancelButtonText: "鍙栨秷",
- type: "warning"
- }).then(function() {
- // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ const { queryParams, form, rules } = toRefs(data);
+
+ /** 鏌ヨ涓存湡閫�鍥炲彴璐﹀垪琛� */
+ function getList() {
+ loading.value = true;
+ // 涓嶈皟鐢ㄦ帴鍙o紝杩斿洖绌烘暟鎹�
+ nearExpiryReturnList.value = [];
+ total.value = 0;
+ loading.value = false;
+ }
+
+ // 鍙栨秷鎸夐挳
+ function cancel() {
+ open.value = false;
+ reset();
+ }
+
+ // 琛ㄥ崟閲嶇疆
+ function reset() {
+ form.value = {
+ id: null,
+ productName: null,
+ productSpec: null,
+ batchNumber: null,
+ productionDate: null,
+ expiryDate: null,
+ returnQuantity: null,
+ returnReason: null,
+ returnDate: null,
+ status: null,
+ remark: null,
+ };
+ proxy.resetForm("formRef");
+ }
+
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ function handleQuery() {
+ queryParams.value.pageNum = 1;
getList();
- }).catch(() => {});
-}
+ }
-/** 瀵煎嚭鎸夐挳鎿嶄綔 */
-function handleExport() {
- // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘彁绀�
- proxy.$modal.msgSuccess("瀵煎嚭鍔熻兘鏆傛湭瀹炵幇");
-}
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ function resetQuery() {
+ proxy.resetForm("queryForm");
+ handleQuery();
+ }
-onMounted(() => {
- getList();
-});
+ // 澶氶�夋閫変腑鏁版嵁
+ function handleSelectionChange(selection) {
+ ids.value = selection.map(item => item.id);
+ single.value = selection.length !== 1;
+ multiple.value = !selection.length;
+ }
+
+ /** 鏂板鎸夐挳鎿嶄綔 */
+ function handleAdd() {
+ reset();
+ open.value = true;
+ title.value = "娣诲姞涓存湡閫�鍥炲彴璐�";
+ }
+
+ /** 淇敼鎸夐挳鎿嶄綔 */
+ function handleUpdate(row) {
+ reset();
+ // 涓嶈皟鐢ㄦ帴鍙o紝鐩存帴浣跨敤浼犲叆鐨勬暟鎹�
+ if (row) {
+ form.value = { ...row };
+ open.value = true;
+ title.value = "淇敼涓存湡閫�鍥炲彴璐�";
+ }
+ }
+
+ /** 鎻愪氦鎸夐挳 */
+ function submitForm() {
+ proxy.$refs["formRef"].validate(valid => {
+ if (valid) {
+ // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
+ if (form.value.id != null) {
+ proxy.$modal.msgSuccess("淇敼鎴愬姛");
+ } else {
+ proxy.$modal.msgSuccess("鏂板鎴愬姛");
+ }
+ open.value = false;
+ getList();
+ }
+ });
+ }
+
+ /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+ function handleDelete(row) {
+ const deleteIds = row.id || ids.value;
+ ElMessageBox.confirm(
+ '鏄惁纭鍒犻櫎涓存湡閫�鍥炲彴璐︾紪鍙蜂负"' + deleteIds + '"鐨勬暟鎹」锛�',
+ "璀﹀憡",
+ {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }
+ )
+ .then(function () {
+ // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘垚鍔熸彁绀�
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .catch(() => {});
+ }
+
+ /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+ function handleExport() {
+ // 涓嶈皟鐢ㄦ帴鍙o紝鍙樉绀烘彁绀�
+ proxy.$modal.msgSuccess("瀵煎嚭鍔熻兘鏆傛湭瀹炵幇");
+ }
+
+ onMounted(() => {
+ getList();
+ });
</script>
diff --git a/src/views/qualityManagement/processInspection/index.vue b/src/views/qualityManagement/processInspection/index.vue
index eaa437c..58d1a3a 100644
--- a/src/views/qualityManagement/processInspection/index.vue
+++ b/src/views/qualityManagement/processInspection/index.vue
@@ -3,385 +3,436 @@
<div class="search_form mb20">
<div>
<span class="search_title">宸ュ簭锛�</span>
- <el-input
- v-model="searchForm.process"
- style="width: 240px"
- placeholder="璇疯緭鍏ュ伐搴忔悳绱�"
- @change="handleQuery"
- 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" />
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储</el-button
- >
+ <el-input v-model="searchForm.process"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ュ伐搴忔悳绱�"
+ @change="handleQuery"
+ 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-input v-model="searchForm.workOrderNo"
+ 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="primary"
+ @click="openForm('add')">鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</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>
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"></PIMTable>
</div>
- <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="30%"
- @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>
+ <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="30%"
+ @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 {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
-import InspectionFormDia from "@/views/qualityManagement/processInspection/components/inspectionFormDia.vue";
-import FormDia from "@/views/qualityManagement/processInspection/components/formDia.vue";
-import {ElMessageBox} from "element-plus";
-import {
- downloadQualityInspect,
- qualityInspectDel,
- qualityInspectListPage, qualityInspectUpdate,
- submitQualityInspect
-} from "@/api/qualityManagement/rawMaterialInspection.js";
-import FilesDia from "@/views/qualityManagement/processInspection/components/filesDia.vue";
-import dayjs from "dayjs";
-import {userListNoPage} from "@/api/system/user.js";
-import useUserStore from "@/store/modules/user";
+ import { Search } from "@element-plus/icons-vue";
+ import {
+ onMounted,
+ ref,
+ reactive,
+ toRefs,
+ getCurrentInstance,
+ nextTick,
+ } from "vue";
+ import InspectionFormDia from "@/views/qualityManagement/processInspection/components/inspectionFormDia.vue";
+ import FormDia from "@/views/qualityManagement/processInspection/components/formDia.vue";
+ import { ElMessageBox } from "element-plus";
+ import {
+ downloadQualityInspect,
+ qualityInspectDel,
+ qualityInspectListPage,
+ qualityInspectUpdate,
+ submitQualityInspect,
+ } from "@/api/qualityManagement/rawMaterialInspection.js";
+ import FilesDia from "@/views/qualityManagement/processInspection/components/filesDia.vue";
+ import dayjs from "dayjs";
+ import { userListNoPage } from "@/api/system/user.js";
+ import useUserStore from "@/store/modules/user";
-const data = reactive({
- searchForm: {
- process: "",
- entryDate: undefined, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- rules: {
- checkName: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
- },
-});
-const { searchForm } = toRefs(data);
-const tableColumn = ref([
- {
- label: "妫�娴嬫棩鏈�",
- prop: "checkTime",
- width: 120
- },
- {
- label: "鐢熶骇宸ュ崟鍙�",
- prop: "workOrderNo",
- width: 120
- },
- {
- label: "宸ュ簭",
- prop: "process",
- width: 230
- },
- {
- label: "妫�楠屽憳",
- prop: "checkName",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "model",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鎬绘暟閲�",
- prop: "quantity",
- width: 100
- },
- {
- label: "鍚堟牸鏁伴噺",
- prop: "qualifiedQuantity",
- width: 100
- },
- {
- label: "涓嶅悎鏍兼暟閲�",
- prop: "unqualifiedQuantity",
- width: 100
- },
- {
- label: "妫�娴嬪崟浣�",
- prop: "checkCompany",
- width: 120
- },
- {
- label: "鍚堟牸鐜�",
- prop: "passRate",
- width: 100,
- dataType: "tag",
- formatData: (params) => {
- if (params == null || params === '') return '鈥�';
- const n = Number(params);
- if (Number.isNaN(n)) return '鈥�';
- return `${n.toFixed(2)}%`;
+ const data = reactive({
+ searchForm: {
+ process: "",
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ workOrderNo: "",
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
},
- formatType: (params) => {
- if (params == null || params === '') return 'info';
- const n = Number(params);
- if (Number.isNaN(n)) return 'info';
- if (n === 100) return 'success';
- if (n >= 75) return 'primary';
- if (n >= 50) return 'warning';
- if (n >= 25) return 'danger';
- return 'danger';
+ rules: {
+ checkName: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
- },
- {
- label: "鎻愪氦鐘舵��",
- prop: "inspectState",
- dataType: "tag",
- formatData: (params) => {
- if (params) {
- return "宸叉彁浜�";
- } else {
- return "鏈彁浜�";
- }
- },
- formatType: (params) => {
- if (params) {
- return "success";
- } else {
- return "info";
- }
- },
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openForm("edit", row);
- },
- disabled: (row) => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- }
+ });
+ const { searchForm } = toRefs(data);
+ const tableColumn = ref([
+ {
+ label: "妫�娴嬫棩鏈�",
+ prop: "checkTime",
+ width: 120,
+ },
+ {
+ label: "鐢熶骇宸ュ崟鍙�",
+ prop: "workOrderNo",
+ width: 120,
+ },
+ {
+ label: "宸ュ簭",
+ prop: "process",
+ width: 230,
+ },
+ {
+ label: "妫�楠屽憳",
+ prop: "checkName",
+ },
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "productName",
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鎬绘暟閲�",
+ prop: "quantity",
+ width: 100,
+ },
+ {
+ label: "鍚堟牸鏁伴噺",
+ prop: "qualifiedQuantity",
+ width: 100,
+ },
+ {
+ label: "涓嶅悎鏍兼暟閲�",
+ prop: "unqualifiedQuantity",
+ width: 100,
+ },
+ {
+ label: "鍚堟牸鐜�",
+ prop: "passRate",
+ width: 100,
+ dataType: "tag",
+ formatType: params => {
+ if (!params) return "";
+ const rate = parseFloat(params);
+ if (rate < 90) {
+ return "danger";
+ } else if (rate === 100) {
+ return "success";
+ } else {
+ return "warning";
+ }
},
- {
- name: "鏌ョ湅",
- type: "text",
- clickFun: (row) => {
- openForm("view", row);
- },
+ },
+ {
+ label: "妫�娴嬪崟浣�",
+ prop: "checkCompany",
+ width: 120,
+ },
+ {
+ label: "妫�娴嬬粨鏋�",
+ prop: "checkResult",
+ dataType: "tag",
+ formatType: params => {
+ if (params == "涓嶅悎鏍�") {
+ return "danger";
+ } else if (params == "鍚堟牸") {
+ return "success";
+ } else {
+ return "danger";
+ }
},
- {
- name: "闄勪欢",
- type: "text",
- clickFun: (row) => {
- openFilesFormDia(row);
- },
+ },
+ {
+ label: "鎻愪氦鐘舵��",
+ prop: "inspectState",
+ formatData: params => {
+ if (params) {
+ return "宸叉彁浜�";
+ } else {
+ return "鏈彁浜�";
+ }
},
- {
- name: "鎻愪氦",
- type: "text",
- clickFun: (row) => {
- submit(row.id);
- },
- disabled: (row) => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- }
- },
- {
- name: "鍒嗛厤妫�楠屽憳",
- type: "text",
- clickFun: (row) => {
- if (!row.checkName) {
- open(row)
- } else {
- proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
- }
- },
- disabled: (row) => {
- return row.inspectState == 1 || row.checkName;
- }
- },
- {
- name: "涓嬭浇",
- type: "text",
- clickFun: (row) => {
- downLoadFile(row);
- },
- },
- ],
- },
-]);
-const userList = ref([]);
-const currentRow = ref(null)
-const tableData = ref([]);
-const selectedRows = ref([]);
-const tableLoading = ref(false);
-const dialogFormVisible = ref(false);
-const form = ref({
- checkName: ""
-});
-const page = reactive({
- current: 1,
- size: 100,
- total: 0
-});
-const formDia = ref()
-const filesDia = ref()
-const inspectionFormDia = ref()
-const { proxy } = getCurrentInstance()
-const userStore = useUserStore()
-const changeDaterange = (value) => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).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;
- const params = { ...searchForm.value, ...page };
- params.entryDate = undefined
- qualityInspectListPage({...params, inspectType: 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;
-};
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 280,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
+ disabled: row => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ },
+ },
+ {
+ name: "鏌ョ湅",
+ type: "text",
+ clickFun: row => {
+ openForm("view", row);
+ },
+ },
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: row => {
+ openFilesFormDia(row);
+ },
+ },
+ {
+ name: "鎻愪氦",
+ type: "text",
+ clickFun: row => {
+ submit(row.id);
+ },
+ disabled: row => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ },
+ },
+ {
+ name: "鍒嗛厤妫�楠屽憳",
+ type: "text",
+ clickFun: row => {
+ if (!row.checkName) {
+ open(row);
+ } else {
+ proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
+ }
+ },
+ disabled: row => {
+ return row.inspectState == 1 || row.checkName;
+ },
+ },
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: row => {
+ downLoadFile(row);
+ },
+ },
+ ],
+ },
+ ]);
+ const userList = ref([]);
+ const currentRow = ref(null);
+ const tableData = ref([]);
+ const selectedRows = ref([]);
+ const tableLoading = ref(false);
+ const dialogFormVisible = ref(false);
+ const form = ref({
+ checkName: "",
+ });
+ const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+ });
+ const formDia = ref();
+ const filesDia = ref();
+ const inspectionFormDia = ref();
+ const { proxy } = getCurrentInstance();
+ const userStore = useUserStore();
+ const changeDaterange = value => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).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;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined;
+ qualityInspectListPage({ ...params, inspectType: 1 })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records.map(item => {
+ const quantity = parseFloat(item.quantity);
+ const qualifiedQuantity = parseFloat(item.qualifiedQuantity);
+ let passRate = null;
+ if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) {
+ passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%";
+ }
+ return {
+ ...item,
+ passRate: passRate,
+ };
+ });
+ 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 openInspectionForm = (type, row) => {
- nextTick(() => {
- inspectionFormDia.value?.openDialog(type, row)
- })
-};
-// 鎵撳紑闄勪欢寮规
-const openFilesFormDia = (type, row) => {
- nextTick(() => {
- filesDia.value?.openDialog(type, row)
- })
-};
-// 鎻愪环
-const submit = async (id) => {
- const res = await submitQualityInspect({id: id})
- if (res.code === 200) {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- getList();
- }
-}
-const open = async (row) => {
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- currentRow.value = row
- dialogFormVisible.value = true
-}
-// 鍏抽棴寮规
-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 openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row);
+ });
+ };
+ // 鎵撳紑鏂板妫�楠屽脊妗�
+ const openInspectionForm = (type, row) => {
+ nextTick(() => {
+ inspectionFormDia.value?.openDialog(type, row);
+ });
+ };
+ // 鎵撳紑闄勪欢寮规
+ const openFilesFormDia = (type, row) => {
+ nextTick(() => {
+ filesDia.value?.openDialog(type, row);
+ });
+ };
+ // 鎻愪环
+ const submit = async id => {
+ const res = await submitQualityInspect({ id: id });
+ if (res.code === 200) {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ getList();
+ }
+ };
+ const open = async row => {
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ currentRow.value = row;
+ dialogFormVisible.value = true;
+ };
+ // 鍏抽棴寮规
+ 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 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",
- })
+ // 鍒犻櫎
+ 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(() => {
- qualityInspectDel(ids).then((res) => {
+ qualityInspectDel(ids).then(res => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -389,41 +440,45 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
-const downLoadFile = (row) => {
- downloadQualityInspect({ id: row.id }).then((blobData) => {
- const blob = new Blob([blobData], {
- type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
- })
- const downloadUrl = window.URL.createObjectURL(blob)
+ };
+ const downLoadFile = row => {
+ downloadQualityInspect({ id: row.id }).then(blobData => {
+ const blob = new Blob([blobData], {
+ type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ });
+ const downloadUrl = window.URL.createObjectURL(blob);
- const link = document.createElement('a')
- link.href = downloadUrl
- link.download = '杩囩▼妫�楠屾姤鍛�.docx'
- document.body.appendChild(link)
- link.click()
+ 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)
- })
-};
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ document.body.removeChild(link);
+ window.URL.revokeObjectURL(downloadUrl);
+ });
+ };
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- proxy.download("/quality/qualityInspect/export", {inspectType: 1}, "杩囩▼妫�楠�.xlsx");
+ proxy.download(
+ "/quality/qualityInspect/export",
+ { inspectType: 1 },
+ "杩囩▼妫�楠�.xlsx"
+ );
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
-onMounted(() => {
- getList();
-});
+ };
+ onMounted(() => {
+ getList();
+ });
</script>
<style scoped></style>
diff --git a/src/views/qualityManagement/rawMaterialInspection/index.vue b/src/views/qualityManagement/rawMaterialInspection/index.vue
index 7ed40eb..6d2acd5 100644
--- a/src/views/qualityManagement/rawMaterialInspection/index.vue
+++ b/src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -3,349 +3,404 @@
<div class="search_form mb20">
<div>
<span class="search_title">渚涘簲鍟嗭細</span>
- <el-input
- v-model="searchForm.supplier"
- style="width: 240px"
- placeholder="璇疯緭鍏ヤ緵搴斿晢鎼滅储"
- @change="handleQuery"
- 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"/>
- <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
- >鎼滅储
- </el-button
- >
+ <el-input v-model="searchForm.supplier"
+ style="width: 240px"
+ placeholder="璇疯緭鍏ヤ緵搴斿晢鎼滅储"
+ @change="handleQuery"
+ 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-input v-model="searchForm.purchaseContractNo"
+ 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="primary"
+ @click="openForm('add')">鏂板</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</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>
+ <PIMTable rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"></PIMTable>
</div>
- <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="30%"
+ <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="30%"
@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-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 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 {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} 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 {
- 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";
-import useUserStore from "@/store/modules/user";
+ import { Search } from "@element-plus/icons-vue";
+ import {
+ onMounted,
+ ref,
+ reactive,
+ toRefs,
+ getCurrentInstance,
+ nextTick,
+ } 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 {
+ 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";
+ import useUserStore from "@/store/modules/user";
-const data = reactive({
- searchForm: {
- supplier: "",
- entryDate: undefined, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- rules: {
- checkName: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
- },
-});
-const {searchForm, rules} = toRefs(data);
-const tableColumn = ref([
- {
- label: "妫�娴嬫棩鏈�",
- prop: "checkTime",
- width: 120
- },
- {
- label: "閲囪喘璁㈠崟鍙�",
- prop: "purchaseContractNo",
- width: 120
- },
- {
- label: "渚涘簲鍟�",
- prop: "supplier",
- width: 230
- },
- {
- label: "妫�楠屽憳",
- prop: "checkName",
- },
- {
- label: "浜у搧鍚嶇О",
- prop: "productName",
- },
- {
- label: "瑙勬牸鍨嬪彿",
- prop: "model",
- },
- {
- label: "鍗曚綅",
- prop: "unit",
- },
- {
- label: "鎬绘暟閲�",
- prop: "quantity",
- width: 100
- },
- {
- label: "鍚堟牸鏁伴噺",
- prop: "qualifiedQuantity",
- width: 100
- },
- {
- label: "涓嶅悎鏍兼暟閲�",
- prop: "unqualifiedQuantity",
- width: 100
- },
- {
- label: "妫�娴嬪崟浣�",
- prop: "checkCompany",
- width: 120
- },
- {
- label: "鍚堟牸鐜�",
- prop: "passRate",
- width: 100,
- dataType: "tag",
- formatData: (params) => {
- if (params == null || params === '') return '鈥�';
- const n = Number(params);
- if (Number.isNaN(n)) return '鈥�';
- return `${n.toFixed(2)}%`;
+ const data = reactive({
+ searchForm: {
+ supplier: "",
+ entryDate: undefined, // 褰曞叆鏃ユ湡
+ purchaseContractNo: "",
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
},
- formatType: (params) => {
- if (params == null || params === '') return 'info';
- const n = Number(params);
- if (Number.isNaN(n)) return 'info';
- if (n === 100) return 'success';
- if (n >= 75) return 'primary';
- if (n >= 50) return 'warning';
- if (n >= 25) return 'danger';
- return 'danger';
+ rules: {
+ checkName: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
},
- },
- {
- label: "鎻愪氦鐘舵��",
- prop: "inspectState",
- dataType: "tag",
- formatData: (params) => {
- if (params) {
- return "宸叉彁浜�";
- } else {
- return "鏈彁浜�";
- }
+ });
+ const { searchForm, rules } = toRefs(data);
+ const tableColumn = ref([
+ {
+ label: "妫�娴嬫棩鏈�",
+ prop: "checkTime",
+ width: 120,
},
- formatType: (params) => {
- if (params) {
- return "success";
- } else {
- return "info";
- }
+ {
+ label: "閲囪喘璁㈠崟鍙�",
+ prop: "purchaseContractNo",
+ width: 120,
},
- },
- {
- dataType: "action",
- label: "鎿嶄綔",
- align: "center",
- fixed: "right",
- width: 280,
- operation: [
- {
- name: "缂栬緫",
- type: "text",
- clickFun: (row) => {
- openForm("edit", row);
- },
- disabled: (row) => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- }
+ {
+ label: "渚涘簲鍟�",
+ prop: "supplier",
+ width: 230,
+ },
+ {
+ label: "妫�楠屽憳",
+ prop: "checkName",
+ },
+ {
+ label: "浜у搧鍚嶇О",
+ prop: "productName",
+ },
+ {
+ label: "瑙勬牸鍨嬪彿",
+ prop: "model",
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ },
+ {
+ label: "鎬绘暟閲�",
+ prop: "quantity",
+ width: 100,
+ },
+ {
+ label: "鍚堟牸鏁伴噺",
+ prop: "qualifiedQuantity",
+ width: 100,
+ },
+ {
+ label: "涓嶅悎鏍兼暟閲�",
+ prop: "unqualifiedQuantity",
+ width: 100,
+ },
+ {
+ label: "鍚堟牸鐜�",
+ prop: "passRate",
+ width: 100,
+ dataType: "tag",
+ formatType: params => {
+ if (!params) return "";
+ const rate = parseFloat(params);
+ if (rate < 90) {
+ return "danger";
+ } else if (rate === 100) {
+ return "success";
+ } else {
+ return "warning";
+ }
},
- {
- name: "鏌ョ湅",
- type: "text",
- clickFun: (row) => {
- openForm("view", row);
- },
+ },
+ {
+ label: "妫�娴嬪崟浣�",
+ prop: "checkCompany",
+ width: 120,
+ },
+ {
+ label: "妫�娴嬪崟浣�",
+ prop: "checkCompany",
+ width: 120,
+ },
+ {
+ label: "妫�娴嬬粨鏋�",
+ prop: "checkResult",
+ dataType: "tag",
+ formatType: params => {
+ if (params === "涓嶅悎鏍�") {
+ return "danger";
+ } else if (params === "鍚堟牸") {
+ return "success";
+ } else {
+ return "danger";
+ }
},
- {
- name: "闄勪欢",
- type: "text",
- clickFun: (row) => {
- openFilesFormDia(row);
- },
+ },
+ {
+ label: "鎻愪氦鐘舵��",
+ prop: "inspectState",
+ formatData: params => {
+ if (params) {
+ return "宸叉彁浜�";
+ } else {
+ return "鏈彁浜�";
+ }
},
- {
- name: "鎻愪氦",
- type: "text",
- clickFun: (row) => {
- submit(row.id);
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 280,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: row => {
+ openForm("edit", row);
+ },
+ disabled: row => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳界紪杈�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ },
},
- disabled: (row) => {
- // 宸叉彁浜ゅ垯绂佺敤
- if (row.inspectState == 1) return true;
- // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
- if (row.checkName) {
- return row.checkName !== userStore.nickName;
- }
- return false;
- }
- },
- {
- name: "鍒嗛厤妫�楠屽憳",
- type: "text",
- clickFun: (row) => {
- if (!row.checkName) {
- open(row)
- } else {
- proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
+ {
+ name: "鏌ョ湅",
+ type: "text",
+ clickFun: row => {
+ openForm("view", row);
+ },
+ },
+ {
+ name: "闄勪欢",
+ type: "text",
+ clickFun: row => {
+ openFilesFormDia(row);
+ },
+ },
+ {
+ name: "鎻愪氦",
+ type: "text",
+ clickFun: row => {
+ submit(row.id);
+ },
+ disabled: row => {
+ // 宸叉彁浜ゅ垯绂佺敤
+ if (row.inspectState == 1) return true;
+ // 濡傛灉妫�楠屽憳鏈夊�硷紝鍙湁褰撳墠鐧诲綍鐢ㄦ埛鑳芥彁浜�
+ if (row.checkName) {
+ return row.checkName !== userStore.nickName;
+ }
+ return false;
+ },
+ },
+ {
+ name: "鍒嗛厤妫�楠屽憳",
+ type: "text",
+ clickFun: row => {
+ if (!row.checkName) {
+ open(row);
+ } else {
+ proxy.$modal.msgError("妫�楠屽憳宸插瓨鍦�");
+ }
+ },
+ disabled: row => {
+ return row.inspectState == 1 || row.checkName;
+ },
+ },
+ {
+ name: "涓嬭浇",
+ type: "text",
+ clickFun: row => {
+ downLoadFile(row);
+ },
+ },
+ ],
+ },
+ ]);
+ 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 userStore = useUserStore();
+ const changeDaterange = value => {
+ searchForm.value.entryDateStart = undefined;
+ searchForm.value.entryDateEnd = undefined;
+ if (value) {
+ searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.value.entryDateEnd = dayjs(value[1]).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;
+ const params = { ...searchForm.value, ...page };
+ params.entryDate = undefined;
+ qualityInspectListPage({ ...params, inspectType: 0 })
+ .then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records.map(item => {
+ const quantity = parseFloat(item.quantity);
+ const qualifiedQuantity = parseFloat(item.qualifiedQuantity);
+ let passRate = null;
+ if (!isNaN(quantity) && !isNaN(qualifiedQuantity) && quantity > 0) {
+ passRate = ((qualifiedQuantity / quantity) * 100).toFixed(2) + "%";
}
- },
- disabled: (row) => {
- return row.inspectState == 1 || row.checkName;
- }
- },
- {
- name: "涓嬭浇",
- type: "text",
- clickFun: (row) => {
- downLoadFile(row);
- },
- },
- ],
- },
-]);
-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 userStore = useUserStore()
-const changeDaterange = (value) => {
- searchForm.value.entryDateStart = undefined;
- searchForm.value.entryDateEnd = undefined;
- if (value) {
- searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.value.entryDateEnd = dayjs(value[1]).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;
- const params = {...searchForm.value, ...page};
- params.entryDate = undefined
- qualityInspectListPage({...params, inspectType: 0}).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;
-};
+ return {
+ ...item,
+ passRate: passRate,
+ };
+ });
+ 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 openFilesFormDia = (type, row) => {
- nextTick(() => {
- filesDia.value?.openDialog(type, row)
- })
-};
+ // 鎵撳紑寮规
+ const openForm = (type, row) => {
+ nextTick(() => {
+ formDia.value?.openDialog(type, row);
+ });
+ };
+ // 鎵撳紑闄勪欢寮规
+ const openFilesFormDia = (type, row) => {
+ nextTick(() => {
+ filesDia.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",
- })
+ // 鍒犻櫎
+ 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(() => {
- qualityInspectDel(ids).then((res) => {
+ qualityInspectDel(ids).then(res => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
getList();
});
@@ -353,79 +408,83 @@
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
-};
-// 瀵煎嚭
-const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
+ };
+ // 瀵煎嚭
+ const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
.then(() => {
- proxy.download("/quality/qualityInspect/export", {inspectType: 0}, "鍘熸潗鏂欐楠�.xlsx");
+ proxy.download(
+ "/quality/qualityInspect/export",
+ { inspectType: 0 },
+ "鍘熸潗鏂欐楠�.xlsx"
+ );
})
.catch(() => {
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 => {
+ // 鎻愪环
+ const submit = async id => {
+ const res = await submitQualityInspect({ id: id });
+ if (res.code === 200) {
proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
getList();
- })
- }
-};
+ }
+ };
-const open = async (row) => {
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- currentRow.value = row
- dialogFormVisible.value = true
-}
+ // 鍏抽棴寮规
+ const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+ };
-const downLoadFile = (row) => {
- downloadQualityInspect({ id: row.id }).then((blobData) => {
- const blob = new Blob([blobData], {
- type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
- })
- const downloadUrl = window.URL.createObjectURL(blob)
+ const submitForm = () => {
+ if (currentRow.value) {
+ const data = {
+ ...form.value,
+ id: currentRow.value.id,
+ };
+ qualityInspectUpdate(data).then(res => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+ }
+ };
- const link = document.createElement('a')
- link.href = downloadUrl
- link.download = '鍘熸潗鏂欐楠屾姤鍛�.docx'
- document.body.appendChild(link)
- link.click()
+ const open = async row => {
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ currentRow.value = row;
+ dialogFormVisible.value = true;
+ };
- document.body.removeChild(link)
- window.URL.revokeObjectURL(downloadUrl)
- })
-};
+ const downLoadFile = row => {
+ downloadQualityInspect({ id: row.id }).then(blobData => {
+ const blob = new Blob([blobData], {
+ type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ });
+ const downloadUrl = window.URL.createObjectURL(blob);
-onMounted(() => {
- getList();
-});
+ 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();
+ });
</script>
<style scoped></style>
diff --git a/src/views/safeProduction/dangerInvestigation/index.vue b/src/views/safeProduction/dangerInvestigation/index.vue
index cb09e52..a278058 100644
--- a/src/views/safeProduction/dangerInvestigation/index.vue
+++ b/src/views/safeProduction/dangerInvestigation/index.vue
@@ -160,7 +160,7 @@
<el-form-item label="闅愭偅缂栧彿锛�"
prop="hiddenCode">
<el-input v-model="form.hiddenCode"
- placeholder="鑷姩鐢熸垚"
+ placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�"
disabled
clearable />
</el-form-item>
diff --git a/src/views/safeProduction/safetyTrainingAssessment/index.vue b/src/views/safeProduction/safetyTrainingAssessment/index.vue
index 2c98308..38c2172 100644
--- a/src/views/safeProduction/safetyTrainingAssessment/index.vue
+++ b/src/views/safeProduction/safetyTrainingAssessment/index.vue
@@ -76,7 +76,21 @@
prop="courseCode">
<el-input v-model="form.courseCode"
disabled
- placeholder="鑷姩鐢熸垚" />
+ placeholder="淇濆瓨鍚庤嚜鍔ㄧ敓鎴�" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍒涘缓鏃堕棿"
+ prop="createTime">
+ <el-date-picker style="width: 100%"
+ v-model="formCreateTimeDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable />
</el-form-item>
</el-col>
</el-row>
@@ -445,12 +459,19 @@
trainingMode: "", // 鍩硅鏂瑰紡
placeTraining: "", // 鍩硅鍦扮偣
classHour: "", // 璇炬椂
+ createTime: "", // 鍒涘缓鏃堕棿
},
dialogVisible: false,
dialogTitle: "",
dialogType: "add",
viewDialogVisible: false,
currentKnowledge: {},
+ });
+ const formCreateTimeDate = computed({
+ get: () => (form.value.createTime ? String(form.value.createTime).split(" ")[0] : ""),
+ set: (value) => {
+ form.value.createTime = value ? `${value} ${dayjs().format("HH:mm:ss")}` : "";
+ },
});
const {
@@ -1025,6 +1046,7 @@
trainingMode: "", // 鍩硅鏂瑰紡
placeTraining: "", // 鍩硅鍦扮偣
classHour: "", // 璇炬椂
+ createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 鍒涘缓鏃堕棿
});
} else if (type === "edit" && row) {
dialogTitle.value = "缂栬緫鍩硅";
@@ -1042,6 +1064,7 @@
trainingMode: row.trainingMode, // 鍩硅鏂瑰紡
placeTraining: row.placeTraining, // 鍩硅鍦扮偣
classHour: row.classHour, // 璇炬椂
+ createTime: row.createTime || "", // 鍒涘缓鏃堕棿
});
}
dialogVisible.value = true;
diff --git a/src/views/salesManagement/receiptPaymentLedger/index.vue b/src/views/salesManagement/receiptPaymentLedger/index.vue
index 8852a32..82d426d 100644
--- a/src/views/salesManagement/receiptPaymentLedger/index.vue
+++ b/src/views/salesManagement/receiptPaymentLedger/index.vue
@@ -46,13 +46,13 @@
show-overflow-tooltip
:formatter="formattedNumber"
width="200" />
- <el-table-column label="鏈嚭搴撻噾棰�(鍏�)"
- prop="unshippedAmount"
+ <el-table-column label="搴旀敹閲戦(鍏�)"
+ prop="receiptableAmount"
show-overflow-tooltip
width="200">
<template #default="{ row, column }">
<el-text type="danger">
- {{ formattedNumber(row, column, row.unshippedAmount) }}
+ {{ formattedNumber(row, column, row.receiptableAmount) }}
</el-text>
</template>
</el-table-column>
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 56f9fd2..604ba82 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -1,42 +1,47 @@
<template>
<div class="app-container">
<div class="search_form">
- <el-form :model="searchForm"
- :inline="true">
+ <el-form :model="searchForm" :inline="true">
<el-form-item label="瀹㈡埛鍚嶇О锛�">
- <el-input v-model="searchForm.customerName"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery" />
+ <el-input
+ v-model="searchForm.customerName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery"
+ />
</el-form-item>
<el-form-item label="閿�鍞悎鍚屽彿锛�">
- <el-input v-model="searchForm.salesContractNo"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery" />
+ <el-input
+ v-model="searchForm.salesContractNo"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery"
+ />
</el-form-item>
<el-form-item label="椤圭洰鍚嶇О锛�">
- <el-input v-model="searchForm.projectName"
- placeholder="璇疯緭鍏�"
- clearable
- prefix-icon="Search"
- @change="handleQuery" />
+ <el-input
+ v-model="searchForm.projectName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ prefix-icon="Search"
+ @change="handleQuery"
+ />
</el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
- <el-date-picker v-model="searchForm.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="daterange"
- placeholder="璇烽�夋嫨"
- clearable
- @change="changeDaterange" />
+ <el-date-picker
+ v-model="searchForm.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="daterange"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="changeDaterange"
+ />
</el-form-item>
<el-form-item>
- <el-button type="primary"
- @click="handleQuery"> 鎼滅储
- </el-button>
+ <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
</el-form-item>
</el-form>
</div>
@@ -44,139 +49,131 @@
<div class="actions">
<div></div>
<div>
- <el-button type="primary"
- @click="openForm('add')">
+ <el-button type="primary" @click="openForm('add')">
鏂板鍙拌处
</el-button>
- <el-button type="primary"
- plain
- @click="handleImport">瀵煎叆
+ <el-button type="primary" plain @click="handleImport"
+ >瀵煎叆
</el-button>
<el-button @click="handleOut">瀵煎嚭</el-button>
- <el-button type="danger"
- plain
- @click="handleDelete">鍒犻櫎
- </el-button>
- <el-button type="primary"
- plain
- @click="handlePrint">鎵撳嵃
- </el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎 </el-button>
+ <el-button type="primary" plain @click="handlePrint">鎵撳嵃 </el-button>
</div>
</div>
- <el-table :data="tableData"
- border
- v-loading="tableLoading"
- @selection-change="handleSelectionChange"
- :expand-row-keys="expandedRowKeys"
- :row-key="(row) => row.id"
- :row-class-name="tableRowClassName"
- show-summary
- style="width: 100%"
- :summary-method="summarizeMainTable"
- @expand-change="expandChange"
- height="calc(100vh - 18.5em)">
- <el-table-column align="center"
- type="selection"
- width="55"
- fixed="left" />
- <el-table-column type="expand"
- width="60"
- fixed="left">
+ <el-table
+ :data="tableData"
+ border
+ v-loading="tableLoading"
+ @selection-change="handleSelectionChange"
+ :expand-row-keys="expandedRowKeys"
+ :row-key="(row) => row.id"
+ :row-class-name="tableRowClassName"
+ show-summary
+ style="width: 100%"
+ :summary-method="summarizeMainTable"
+ @expand-change="expandChange"
+ height="calc(100vh - 18.5em)"
+ >
+ <el-table-column
+ align="center"
+ type="selection"
+ width="55"
+ fixed="left"
+ />
+ <el-table-column type="expand" width="60" fixed="left">
<template #default="props">
- <el-table :data="props.row.children"
- border
- show-summary
- :summary-method="(param) => summarizeChildrenTable(param, props.row)">
- <el-table-column align="center"
- label="搴忓彿"
- type="index" />
- <el-table-column label="浜у搧澶х被"
- prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel" />
- <el-table-column label="鍗曚綅"
- prop="unit" />
- <el-table-column label="浜у搧鐘舵��"
- width="100px"
- align="center">
+ <el-table
+ :data="props.row.children"
+ border
+ show-summary
+ :summary-method="
+ (param) => summarizeChildrenTable(param, props.row)
+ "
+ >
+ <el-table-column align="center" label="搴忓彿" type="index" />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="浜у搧鐘舵��" width="100px" align="center">
<template #default="scope">
- <el-tag v-if="scope.row.approveStatus === 1 "
- type="success">鍏呰冻
+ <el-tag v-if="scope.row.approveStatus === 1" type="success"
+ >鍏呰冻
</el-tag>
- <el-tag v-else-if="scope.row.approveStatus === 0 && scope.row.noQuantity === 0"
- type="success">宸插嚭搴�
+ <el-tag
+ v-else-if="
+ scope.row.approveStatus === 0 &&
+ scope.row.noQuantity === 0
+ "
+ type="success"
+ >宸插嚭搴�
</el-tag>
- <el-tag v-else
- type="danger">涓嶈冻
- </el-tag>
+ <el-tag v-else type="danger">涓嶈冻 </el-tag>
</template>
</el-table-column>
- <el-table-column label="鍙戣揣鐘舵��"
- width="140"
- align="center">
+ <el-table-column label="鍙戣揣鐘舵��" width="140" align="center">
<template #default="scope">
- <el-tag :type="getShippingStatusType(scope.row)"
- size="small">
+ <el-tag :type="getShippingStatusType(scope.row)" size="small">
{{ getShippingStatusText(scope.row) }}
</el-tag>
</template>
</el-table-column>
- <el-table-column label="蹇�掑叕鍙�"
- prop="expressCompany"
- show-overflow-tooltip />
- <el-table-column label="蹇�掑崟鍙�"
- prop="expressNumber"
- show-overflow-tooltip />
- <el-table-column label="鍙戣揣杞︾墝"
- minWidth="100px"
- align="center">
+ <el-table-column
+ label="蹇�掑叕鍙�"
+ prop="expressCompany"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="蹇�掑崟鍙�"
+ prop="expressNumber"
+ show-overflow-tooltip
+ />
+ <el-table-column label="鍙戣揣杞︾墝" minWidth="100px" align="center">
<template #default="scope">
<div>
- <el-tag type="success"
- v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}
+ <el-tag type="success" v-if="scope.row.shippingCarNumber"
+ >{{ scope.row.shippingCarNumber }}
</el-tag>
- <el-tag v-else
- type="info">-
- </el-tag>
+ <el-tag v-else type="info">- </el-tag>
</div>
</template>
</el-table-column>
- <el-table-column label="鍙戣揣鏃ユ湡"
- minWidth="100px"
- align="center">
+ <el-table-column label="鍙戣揣鏃ユ湡" minWidth="100px" align="center">
<template #default="scope">
<div>
- <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
- <el-tag v-else
- type="info">-
- </el-tag>
+ <div v-if="scope.row.shippingDate">
+ {{ scope.row.shippingDate }}
+ </div>
+ <el-tag v-else type="info">- </el-tag>
</div>
</template>
</el-table-column>
- <el-table-column label="鏁伴噺"
- prop="quantity" />
- <el-table-column label="寰呭彂璐ф暟閲�"
- prop="noQuantity" />
- <el-table-column label="绋庣巼(%)"
- prop="taxRate" />
- <el-table-column label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="sensitiveAmountFormatter" />
- <el-table-column label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="sensitiveAmountFormatter" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="sensitiveAmountFormatter" />
+ <el-table-column label="鏁伴噺" prop="quantity" />
+ <el-table-column label="寰呭彂璐ф暟閲�" prop="noQuantity" />
+ <el-table-column label="绋庣巼(%)" prop="taxRate" />
+ <el-table-column
+ label="鍚◣鍗曚环(鍏�)"
+ prop="taxInclusiveUnitPrice"
+ :formatter="sensitiveAmountFormatter"
+ />
+ <el-table-column
+ label="鍚◣鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ :formatter="sensitiveAmountFormatter"
+ />
+ <el-table-column
+ label="涓嶅惈绋庢�讳环(鍏�)"
+ prop="taxExclusiveTotalPrice"
+ :formatter="sensitiveAmountFormatter"
+ />
<!--鎿嶄綔-->
- <el-table-column Width="60px"
- label="鎿嶄綔"
- align="center">
+ <el-table-column Width="60px" label="鎿嶄綔" align="center">
<template #default="scope">
- <el-button link
- type="primary"
- :disabled="!canShip(scope.row)"
- @click="openDeliveryForm(scope.row)">
+ <el-button
+ link
+ type="primary"
+ :disabled="!canShip(scope.row)"
+ @click="openDeliveryForm(scope.row)"
+ >
鍙戣揣
</el-button>
</template>
@@ -184,150 +181,198 @@
</el-table>
</template>
</el-table-column>
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column label="閿�鍞悎鍚屽彿"
- prop="salesContractNo"
- width="180"
- show-overflow-tooltip />
- <el-table-column label="瀹㈡埛鍚嶇О"
- prop="customerName"
- width="300"
- show-overflow-tooltip />
- <el-table-column label="涓氬姟鍛�"
- prop="salesman"
- width="100"
- show-overflow-tooltip />
- <el-table-column label="椤圭洰鍚嶇О"
- prop="projectName"
- width="180"
- show-overflow-tooltip />
- <el-table-column label="浠樻鏂瑰紡"
- prop="paymentMethod"
- show-overflow-tooltip />
- <el-table-column label="鍚堝悓閲戦(鍏�)"
- prop="contractAmount"
- width="220"
- show-overflow-tooltip
- :formatter="formattedNumber" />
- <el-table-column label="褰曞叆浜�"
- prop="entryPersonName"
- width="100"
- show-overflow-tooltip />
- <el-table-column label="褰曞叆鏃ユ湡"
- prop="entryDate"
- width="120"
- show-overflow-tooltip />
- <el-table-column label="绛捐鏃ユ湡"
- prop="executionDate"
- width="120"
- show-overflow-tooltip />
- <el-table-column label="浜や粯鏃ユ湡"
- prop="deliveryDate"
- width="120"
- show-overflow-tooltip />
- <el-table-column label="澶囨敞"
- prop="remarks"
- width="200"
- show-overflow-tooltip />
- <el-table-column fixed="right"
- label="鎿嶄綔"
- width="220"
- align="center">
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column
+ label="閿�鍞悎鍚屽彿"
+ prop="salesContractNo"
+ width="180"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="瀹㈡埛鍚嶇О"
+ prop="customerName"
+ width="300"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="涓氬姟鍛�"
+ prop="salesman"
+ width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="椤圭洰鍚嶇О"
+ prop="projectName"
+ width="180"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="浠樻鏂瑰紡"
+ prop="paymentMethod"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="鍚堝悓閲戦(鍏�)"
+ prop="contractAmount"
+ width="220"
+ show-overflow-tooltip
+ :formatter="formattedNumber"
+ />
+ <el-table-column
+ label="褰曞叆浜�"
+ prop="entryPersonName"
+ width="100"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="褰曞叆鏃ユ湡"
+ prop="entryDate"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="绛捐鏃ユ湡"
+ prop="executionDate"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="浜や粯鏃ユ湡"
+ prop="deliveryDate"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ label="澶囨敞"
+ prop="remarks"
+ width="200"
+ show-overflow-tooltip
+ />
+ <el-table-column fixed="right" label="鎿嶄綔" width="220" align="center">
<template #default="scope">
- <el-button link
- type="primary"
- @click="openForm('view', scope.row)">璇︽儏
+ <el-button link type="primary" @click="openForm('view', scope.row)"
+ >璇︽儏
</el-button>
- <el-button link
- type="primary"
- @click="openForm('edit', scope.row)"
- :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">缂栬緫
+ <el-button
+ link
+ type="primary"
+ @click="openForm('edit', scope.row)"
+ :disabled="
+ !scope.row.isEdit ||
+ scope.row.hasProductionRecord ||
+ !canEditLedger(scope.row)
+ "
+ >缂栬緫
</el-button>
- <el-button link
- type="primary"
- @click="openFileDialog(scope.row)">闄勪欢
+ <el-button link type="primary" @click="openFileDialog(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" />
+ <pagination
+ v-show="total > 0"
+ :total="total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationChange"
+ />
</div>
- <FormDialog v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : (operationType === 'edit' ? '缂栬緫閿�鍞彴璐﹂〉闈�' : '閿�鍞彴璐﹁鎯�')"
- :width="'70%'"
- :operation-type="operationType"
- @close="closeDia"
- @confirm="submitForm"
- @cancel="closeDia">
- <el-form :model="form"
- label-width="140px"
- label-position="top"
- :rules="rules"
- ref="formRef">
+ <FormDialog
+ v-model="dialogFormVisible"
+ :title="
+ operationType === 'add'
+ ? '鏂板閿�鍞彴璐﹂〉闈�'
+ : operationType === 'edit'
+ ? '缂栬緫閿�鍞彴璐﹂〉闈�'
+ : '閿�鍞彴璐﹁鎯�'
+ "
+ :width="'70%'"
+ :operation-type="operationType"
+ @close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
<!-- 鎶ヤ环鍗曞鍏ュ叆鍙o細鏀惧湪琛ㄥ崟椤堕儴锛岄�夋嫨鍚庡弽鏄惧鎴�/涓氬姟鍛樼瓑 -->
- <el-row v-if="operationType === 'add'"
- style="margin-bottom: 10px;">
- <el-col :span="24"
- style="text-align: right;">
- <el-button type="primary"
- plain
- @click="openQuotationDialog">
+ <el-row v-if="operationType === 'add'" style="margin-bottom: 10px">
+ <el-col :span="24" style="text-align: right">
+ <el-button type="primary" plain @click="openQuotationDialog">
浠庨攢鍞姤浠峰鍏�
</el-button>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="閿�鍞悎鍚屽彿锛�"
- prop="salesContractNo">
- <div style="display: flex; align-items: center; gap: 12px;width: 100%;">
- <el-checkbox v-model="form.autoGenerateContractNo"
- v-if="operationType === 'add'">鑷姩鐢熸垚
+ <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
+ <div
+ style="
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ width: 100%;
+ "
+ >
+ <el-checkbox
+ v-model="form.autoGenerateContractNo"
+ v-if="operationType === 'add'"
+ >鑷姩鐢熸垚
</el-checkbox>
- <el-input v-model="form.salesContractNo"
- :placeholder="form.autoGenerateContractNo ? '鑷姩鐢熸垚' : '璇疯緭鍏�'"
- clearable
- :disabled="form.autoGenerateContractNo || operationType === 'view'" />
+ <el-input
+ v-model="form.salesContractNo"
+ :placeholder="
+ form.autoGenerateContractNo ? '淇濆瓨鍚庤嚜鍔ㄧ敓鎴�' : '璇疯緭鍏�'
+ "
+ clearable
+ :disabled="
+ form.autoGenerateContractNo || operationType === 'view'
+ "
+ />
</div>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="涓氬姟鍛橈細"
- prop="salesman">
- <el-select v-model="form.salesman"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- filterable>
- <el-option v-for="item in userList"
- :key="item.nickName"
- :label="item.nickName"
- :value="item.nickName" />
+ <el-form-item label="涓氬姟鍛橈細" prop="salesman">
+ <el-select
+ v-model="form.salesman"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ filterable
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="瀹㈡埛鍚嶇О锛�"
- prop="customerId">
- <el-select v-model="form.customerId"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- filterable>
- <el-option v-for="item in customerOption"
- :key="item.id"
- :label="item.customerName"
- :value="item.id">
+ <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerId">
+ <el-select
+ v-model="form.customerId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ filterable
+ >
+ <el-option
+ v-for="item in customerOption"
+ :key="item.id"
+ :label="item.customerName"
+ :value="item.id"
+ >
{{
item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
}}
@@ -336,400 +381,453 @@
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="椤圭洰鍚嶇О锛�"
- prop="projectName">
- <el-input v-model="form.projectName"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="operationType === 'view'" />
+ <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
+ <el-input
+ v-model="form.projectName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="operationType === 'view'"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="绛捐鏃ユ湡锛�"
- prop="executionDate">
- <el-date-picker style="width: 100%"
- v-model="form.executionDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'" />
+ <el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.executionDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="浠樻鏂瑰紡">
- <el-input v-model="form.paymentMethod"
- placeholder="璇疯緭鍏�"
- clearable
- :disabled="operationType === 'view'" />
+ <el-input
+ v-model="form.paymentMethod"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :disabled="operationType === 'view'"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="褰曞叆浜猴細"
- prop="entryPerson">
- <el-select v-model="form.entryPerson"
- filterable
- default-first-option
- :reserve-keyword="false"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'"
- @change="changs">
- <el-option v-for="item in userList"
- :key="item.userId"
- :label="item.nickName"
- :value="item.userId" />
+ <el-form-item label="褰曞叆浜猴細" prop="entryPerson">
+ <el-select
+ v-model="form.entryPerson"
+ filterable
+ default-first-option
+ :reserve-keyword="false"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ @change="changs"
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.userId"
+ :label="item.nickName"
+ :value="item.userId"
+ />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="褰曞叆鏃ユ湡锛�"
- prop="entryDate">
- <el-date-picker style="width: 100%"
- v-model="form.entryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'" />
+ <el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.entryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="浜よ揣鏃ユ湡锛�"
- prop="entryDate">
- <el-date-picker style="width: 100%"
- v-model="form.deliveryDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨"
- clearable
- :disabled="operationType === 'view'" />
+ <el-form-item label="浜よ揣鏃ユ湡锛�" prop="entryDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.deliveryDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ :disabled="operationType === 'view'"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row>
- <el-form-item label="浜у搧淇℃伅锛�"
- prop="entryDate">
- <el-button v-if="operationType !== 'view'"
- type="primary"
- @click="openProductForm('add')">娣诲姞
+ <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
+ <el-button
+ v-if="operationType !== 'view'"
+ type="primary"
+ @click="openProductForm('add')"
+ >娣诲姞
</el-button>
- <el-button v-if="operationType !== 'view'"
- plain
- type="danger"
- @click="deleteProduct">鍒犻櫎
+ <el-button
+ v-if="operationType !== 'view'"
+ plain
+ type="danger"
+ @click="deleteProduct"
+ >鍒犻櫎
</el-button>
</el-form-item>
</el-row>
- <el-table :data="productData"
- border
- @selection-change="productSelected"
- show-summary
- :summary-method="summarizeMainTable">
- <el-table-column align="center"
- type="selection"
- width="55"
- v-if="operationType !== 'view'"
- :selectable="(row) => !isProductShipped(row)" />
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column label="浜у搧澶х被"
- prop="productCategory" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="specificationModel" />
- <el-table-column label="鍗曚綅"
- prop="unit" />
- <el-table-column label="鏁伴噺"
- prop="quantity" />
- <el-table-column label="绋庣巼(%)"
- prop="taxRate" />
- <el-table-column label="鍚◣鍗曚环(鍏�)"
- prop="taxInclusiveUnitPrice"
- :formatter="formattedNumber" />
- <el-table-column label="鍚◣鎬讳环(鍏�)"
- prop="taxInclusiveTotalPrice"
- :formatter="formattedNumber" />
- <el-table-column label="涓嶅惈绋庢�讳环(鍏�)"
- prop="taxExclusiveTotalPrice"
- :formatter="formattedNumber" />
- <el-table-column label="鏄惁鐢熶骇"
- prop="isProduction"
- width="150">
+ <el-table
+ :data="productData"
+ border
+ @selection-change="productSelected"
+ show-summary
+ :summary-method="summarizeMainTable"
+ >
+ <el-table-column
+ align="center"
+ type="selection"
+ width="55"
+ v-if="operationType !== 'view'"
+ :selectable="(row) => !isProductShipped(row)"
+ />
+ <el-table-column
+ align="center"
+ label="搴忓彿"
+ type="index"
+ width="60"
+ />
+ <el-table-column label="浜у搧澶х被" prop="productCategory" />
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+ <el-table-column label="鍗曚綅" prop="unit" />
+ <el-table-column label="鏁伴噺" prop="quantity" />
+ <el-table-column label="绋庣巼(%)" prop="taxRate" />
+ <el-table-column
+ label="鍚◣鍗曚环(鍏�)"
+ prop="taxInclusiveUnitPrice"
+ :formatter="formattedNumber"
+ />
+ <el-table-column
+ label="鍚◣鎬讳环(鍏�)"
+ prop="taxInclusiveTotalPrice"
+ :formatter="formattedNumber"
+ />
+ <el-table-column
+ label="涓嶅惈绋庢�讳环(鍏�)"
+ prop="taxExclusiveTotalPrice"
+ :formatter="formattedNumber"
+ />
+ <el-table-column label="鏄惁鐢熶骇" prop="isProduction" width="150">
<template #default="scope">
<el-tag :type="scope.row.isProduction ? 'success' : 'info'">
- {{ scope.row.isProduction ? '鏄�' : '鍚�' }}
+ {{ scope.row.isProduction ? "鏄�" : "鍚�" }}
</el-tag>
</template>
</el-table-column>
- <el-table-column fixed="right"
- label="鎿嶄綔"
- min-width="60"
- align="center"
- v-if="operationType !== 'view'">
+ <el-table-column
+ fixed="right"
+ label="鎿嶄綔"
+ min-width="60"
+ align="center"
+ v-if="operationType !== 'view'"
+ >
<template #default="scope">
- <el-button link
- type="primary"
- size="small"
- :disabled="isProductShipped(scope.row)"
- @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫
+ <el-button
+ link
+ type="primary"
+ size="small"
+ :disabled="isProductShipped(scope.row)"
+ @click="openProductForm('edit', scope.row, scope.$index)"
+ >缂栬緫
</el-button>
</template>
</el-table-column>
</el-table>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="澶囨敞锛�"
- prop="remarks">
- <el-input v-model="form.remarks"
- placeholder="璇疯緭鍏�"
- clearable
- type="textarea"
- :rows="2"
- :disabled="operationType === 'view'" />
+ <el-form-item label="澶囨敞锛�" prop="remarks">
+ <el-input
+ v-model="form.remarks"
+ placeholder="璇疯緭鍏�"
+ clearable
+ type="textarea"
+ :rows="2"
+ :disabled="operationType === 'view'"
+ />
</el-form-item>
</el-col>
</el-row>
- <el-row v-if="operationType !== 'view'"
- :gutter="30">
+ <el-row v-if="operationType !== 'view'" :gutter="30">
<el-col :span="24">
- <el-form-item label="闄勪欢鏉愭枡锛�"
- prop="salesLedgerFiles">
- <FileUpload v-model:file-list="fileList"
- :disabled="operationType === 'view'" />
+ <el-form-item label="闄勪欢鏉愭枡锛�" prop="salesLedgerFiles">
+ <FileUpload
+ v-model:file-list="fileList"
+ :disabled="operationType === 'view'"
+ />
</el-form-item>
</el-col>
</el-row>
</el-form>
</FormDialog>
<!-- 浠庢姤浠峰崟瀵煎叆锛堜粎瀹℃壒閫氳繃锛� -->
- <el-dialog v-model="quotationDialogVisible"
- title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
- width="80%"
- :close-on-click-modal="false">
- <div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
- <el-input v-model="quotationSearchForm.quotationNo"
- placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
- clearable
- style="max-width: 260px;"
- @change="fetchQuotationList" />
- <el-input v-model="quotationSearchForm.customer"
- placeholder="璇疯緭鍏ュ鎴峰悕绉�"
- clearable
- style="max-width: 260px;"
- @change="fetchQuotationList" />
- <el-button type="primary"
- @click="fetchQuotationList">鎼滅储
- </el-button>
+ <el-dialog
+ v-model="quotationDialogVisible"
+ title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
+ width="80%"
+ :close-on-click-modal="false"
+ >
+ <div
+ style="
+ margin-bottom: 12px;
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ "
+ >
+ <el-input
+ v-model="quotationSearchForm.quotationNo"
+ placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
+ clearable
+ style="max-width: 260px"
+ @change="fetchQuotationList"
+ />
+ <el-input
+ v-model="quotationSearchForm.customer"
+ placeholder="璇疯緭鍏ュ鎴峰悕绉�"
+ clearable
+ style="max-width: 260px"
+ @change="fetchQuotationList"
+ />
+ <el-button type="primary" @click="fetchQuotationList">鎼滅储 </el-button>
<el-button @click="resetQuotationSearch">閲嶇疆</el-button>
</div>
- <el-table :data="quotationList"
- border
- stripe
- v-loading="quotationLoading"
- height="420px">
- <el-table-column align="center"
- label="搴忓彿"
- type="index"
- width="60" />
- <el-table-column prop="quotationNo"
- label="鎶ヤ环鍗曞彿"
- width="180"
- show-overflow-tooltip />
- <el-table-column prop="customer"
- label="瀹㈡埛鍚嶇О"
- min-width="220"
- show-overflow-tooltip />
- <el-table-column prop="salesperson"
- label="涓氬姟鍛�"
- width="120"
- show-overflow-tooltip />
- <el-table-column prop="quotationDate"
- label="鎶ヤ环鏃ユ湡"
- width="140" />
- <el-table-column prop="status"
- label="瀹℃壒鐘舵��"
- width="120"
- align="center" />
- <el-table-column prop="totalAmount"
- label="鎶ヤ环閲戦(鍏�)"
- width="160"
- align="right">
+ <el-table
+ :data="quotationList"
+ border
+ stripe
+ v-loading="quotationLoading"
+ height="420px"
+ >
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+ <el-table-column
+ prop="quotationNo"
+ label="鎶ヤ环鍗曞彿"
+ width="180"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="customer"
+ label="瀹㈡埛鍚嶇О"
+ min-width="220"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ prop="salesperson"
+ label="涓氬姟鍛�"
+ width="120"
+ show-overflow-tooltip
+ />
+ <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="140" />
+ <el-table-column
+ prop="status"
+ label="瀹℃壒鐘舵��"
+ width="120"
+ align="center"
+ />
+ <el-table-column
+ prop="totalAmount"
+ label="鎶ヤ环閲戦(鍏�)"
+ width="160"
+ align="right"
+ >
<template #default="scope">
{{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
</template>
</el-table-column>
- <el-table-column fixed="right"
- label="鎿嶄綔"
- width="120"
- align="center">
+ <el-table-column fixed="right" label="鎿嶄綔" width="120" align="center">
<template #default="scope">
- <el-button type="primary"
- link
- @click="applyQuotation(scope.row)">閫夋嫨
+ <el-button type="primary" link @click="applyQuotation(scope.row)"
+ >閫夋嫨
</el-button>
</template>
</el-table-column>
</el-table>
- <pagination v-show="quotationPage.total > 0"
- :total="quotationPage.total"
- layout="total, sizes, prev, pager, next, jumper"
- :page="quotationPage.current"
- :limit="quotationPage.size"
- @pagination="quotationPaginationChange" />
+ <pagination
+ v-show="quotationPage.total > 0"
+ :total="quotationPage.total"
+ layout="total, sizes, prev, pager, next, jumper"
+ :page="quotationPage.current"
+ :limit="quotationPage.size"
+ @pagination="quotationPaginationChange"
+ />
<template #footer>
<el-button @click="quotationDialogVisible = false">鍏抽棴</el-button>
</template>
</el-dialog>
- <FormDialog v-model="productFormVisible"
- :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
- :width="'40%'"
- :operation-type="productOperationType"
- @close="closeProductDia"
- @confirm="submitProduct"
- @cancel="closeProductDia">
- <el-form :model="productForm"
- label-width="140px"
- label-position="top"
- :rules="productRules"
- ref="productFormRef">
+ <FormDialog
+ v-model="productFormVisible"
+ :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
+ :width="'40%'"
+ :operation-type="productOperationType"
+ @close="closeProductDia"
+ @confirm="submitProduct"
+ @cancel="closeProductDia"
+ >
+ <el-form
+ :model="productForm"
+ label-width="140px"
+ label-position="top"
+ :rules="productRules"
+ ref="productFormRef"
+ >
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="浜у搧澶х被锛�"
- prop="productCategory">
- <el-tree-select v-model="productForm.productCategory"
- placeholder="璇烽�夋嫨"
- clearable
- filterable
- check-strictly
- @change="getModels"
- :data="productOptions"
- :render-after-expand="false"
- style="width: 100%" />
+ <el-form-item label="浜у搧澶х被锛�" prop="productCategory">
+ <el-tree-select
+ v-model="productForm.productCategory"
+ placeholder="璇烽�夋嫨"
+ clearable
+ filterable
+ check-strictly
+ @change="getModels"
+ :data="productOptions"
+ :render-after-expand="false"
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="瑙勬牸鍨嬪彿锛�"
- prop="productModelId">
- <el-select v-model="productForm.productModelId"
- placeholder="璇烽�夋嫨"
- clearable
- @change="getProductModel"
- filterable>
- <el-option v-for="item in modelOptions"
- :key="item.id"
- :label="item.model"
- :value="item.id" />
+ <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+ <el-select
+ v-model="productForm.productModelId"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="getProductModel"
+ filterable
+ >
+ <el-option
+ v-for="item in modelOptions"
+ :key="item.id"
+ :label="item.model"
+ :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="unit">
- <el-input v-model="productForm.unit"
- placeholder="璇疯緭鍏�"
- clearable />
+ <el-form-item label="鍗曚綅锛�" prop="unit">
+ <el-input
+ v-model="productForm.unit"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="绋庣巼(%)锛�"
- prop="taxRate">
- <el-select v-model="productForm.taxRate"
- placeholder="璇烽�夋嫨"
- clearable
- @change="calculateFromTaxRate">
- <el-option v-for="dict in tax_rate"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value" />
+ <el-form-item label="绋庣巼(%)锛�" prop="taxRate">
+ <el-select
+ v-model="productForm.taxRate"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="calculateFromTaxRate"
+ >
+ <el-option
+ v-for="dict in tax_rate"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍚◣鍗曚环(鍏�)锛�"
- prop="taxInclusiveUnitPrice">
- <el-input-number :step="0.01"
- :min="0"
- v-model="productForm.taxInclusiveUnitPrice"
- style="width: 100%"
- :precision="2"
- placeholder="璇疯緭鍏�"
- clearable
- @change="calculateFromUnitPrice" />
+ <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
+ <el-input-number
+ :step="0.01"
+ :min="0"
+ v-model="productForm.taxInclusiveUnitPrice"
+ style="width: 100%"
+ :precision="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromUnitPrice"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏁伴噺锛�"
- prop="quantity">
- <el-input-number :step="0.1"
- :min="0"
- v-model="productForm.quantity"
- placeholder="璇疯緭鍏�"
- clearable
- :precision="2"
- @change="calculateFromQuantity"
- style="width: 100%" />
+ <el-form-item label="鏁伴噺锛�" prop="quantity">
+ <el-input-number
+ :step="0.1"
+ :min="0"
+ v-model="productForm.quantity"
+ placeholder="璇疯緭鍏�"
+ clearable
+ :precision="2"
+ @change="calculateFromQuantity"
+ style="width: 100%"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍚◣鎬讳环(鍏�)锛�"
- prop="taxInclusiveTotalPrice">
- <el-input v-model="productForm.taxInclusiveTotalPrice"
- placeholder="璇疯緭鍏�"
- clearable
- @change="calculateFromTotalPrice" />
+ <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
+ <el-input
+ v-model="productForm.taxInclusiveTotalPrice"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromTotalPrice"
+ />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�"
- prop="taxExclusiveTotalPrice">
- <el-input v-model="productForm.taxExclusiveTotalPrice"
- placeholder="璇疯緭鍏�"
- clearable
- @change="calculateFromExclusiveTotalPrice" />
+ <el-form-item
+ label="涓嶅惈绋庢�讳环(鍏�)锛�"
+ prop="taxExclusiveTotalPrice"
+ >
+ <el-input
+ v-model="productForm.taxExclusiveTotalPrice"
+ placeholder="璇疯緭鍏�"
+ clearable
+ @change="calculateFromExclusiveTotalPrice"
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="12">
- <el-form-item label="鍙戠エ绫诲瀷锛�"
- prop="invoiceType">
- <el-select v-model="productForm.invoiceType"
- placeholder="璇烽�夋嫨"
- clearable>
- <el-option label="澧炴櫘绁�"
- value="澧炴櫘绁�" />
- <el-option label="澧炰笓绁�"
- value="澧炰笓绁�" />
+ <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
+ <el-select
+ v-model="productForm.invoiceType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ >
+ <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
+ <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鏄惁鐢熶骇锛�"
- prop="isProduction">
+ <el-form-item label="鏄惁鐢熶骇锛�" prop="isProduction">
<el-radio-group v-model="productForm.isProduction">
- <el-radio label="鏄�"
- :value="true" />
- <el-radio label="鍚�"
- :value="false" />
+ <el-radio label="鏄�" :value="true" />
+ <el-radio label="鍚�" :value="false" />
</el-radio-group>
</el-form-item>
</el-col>
@@ -737,34 +835,35 @@
</el-form>
</FormDialog>
<!-- 瀵煎叆寮圭獥 -->
- <FormDialog v-model="importUpload.open"
- :title="importUpload.title"
- :width="'600px'"
- @close="importUpload.open = false"
- @confirm="submitImportFile"
- @cancel="importUpload.open = false">
- <el-upload ref="importUploadRef"
- :limit="1"
- accept=".xlsx,.xls"
- :action="importUpload.url"
- :headers="importUpload.headers"
- :before-upload="importUpload.beforeUpload"
- :on-success="importUpload.onSuccess"
- :on-error="importUpload.onError"
- :on-progress="importUpload.onProgress"
- :on-change="importUpload.onChange"
- :auto-upload="false"
- drag>
+ <FormDialog
+ v-model="importUpload.open"
+ :title="importUpload.title"
+ :width="'600px'"
+ @close="importUpload.open = false"
+ @confirm="submitImportFile"
+ @cancel="importUpload.open = false"
+ >
+ <el-upload
+ ref="importUploadRef"
+ :limit="1"
+ accept=".xlsx,.xls"
+ :action="importUpload.url"
+ :headers="importUpload.headers"
+ :before-upload="importUpload.beforeUpload"
+ :on-success="importUpload.onSuccess"
+ :on-error="importUpload.onError"
+ :on-progress="importUpload.onProgress"
+ :on-change="importUpload.onChange"
+ :auto-upload="false"
+ drag
+ >
<i class="el-icon-upload"></i>
- <div class="el-upload__text">
- 灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em>
- </div>
+ <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
<template #tip>
<div class="el-upload__tip">
浠呮敮鎸� xls/xlsx锛屽ぇ灏忎笉瓒呰繃 10MB銆�
- <el-button link
- type="primary"
- @click="downloadTemplate">涓嬭浇瀵煎叆妯℃澘
+ <el-button link type="primary" @click="downloadTemplate"
+ >涓嬭浇瀵煎叆妯℃澘
</el-button>
</div>
</template>
@@ -772,35 +871,50 @@
</FormDialog>
<!-- // todo 闄勪欢棰勮鐩稿叧 -->
<!-- 闄勪欢鍒楄〃寮圭獥 -->
- <FileList v-if="fileDialogVisible"
- v-model:visible="fileDialogVisible"
- record-type="sales_ledger"
- :record-id="recordId" />
+ <FileList
+ v-if="fileDialogVisible"
+ v-model:visible="fileDialogVisible"
+ record-type="sales_ledger"
+ :record-id="recordId"
+ />
<!-- 鎵撳嵃棰勮寮圭獥 -->
- <el-dialog v-model="printPreviewVisible"
- title="鎵撳嵃棰勮"
- width="90%"
- :close-on-click-modal="false"
- class="print-preview-dialog">
+ <el-dialog
+ v-model="printPreviewVisible"
+ title="鎵撳嵃棰勮"
+ width="90%"
+ :close-on-click-modal="false"
+ class="print-preview-dialog"
+ >
<div class="print-preview-container">
<div class="print-preview-header">
- <el-button type="primary"
- @click="executePrint">鎵ц鎵撳嵃
- </el-button>
+ <el-button type="primary" @click="executePrint">鎵ц鎵撳嵃 </el-button>
<el-button @click="printPreviewVisible = false">鍏抽棴棰勮</el-button>
</div>
<div class="print-preview-content">
- <div v-if="printData.length === 0"
- style="text-align: center; padding: 50px; color: #999;">
+ <div
+ v-if="printData.length === 0"
+ style="text-align: center; padding: 50px; color: #999"
+ >
鏆傛棤鎵撳嵃鏁版嵁
</div>
- <div v-else
- style="text-align: center; padding: 10px; color: #666; font-size: 14px; background: #e8f4fd; margin-bottom: 10px;">
+ <div
+ v-else
+ style="
+ text-align: center;
+ padding: 10px;
+ color: #666;
+ font-size: 14px;
+ background: #e8f4fd;
+ margin-bottom: 10px;
+ "
+ >
鍏� {{ printData.length }} 鏉℃暟鎹緟鎵撳嵃
</div>
- <div v-for="(item, index) in printData"
- :key="index"
- class="print-page">
+ <div
+ v-for="(item, index) in printData"
+ :key="index"
+ class="print-page"
+ >
<div class="delivery-note">
<div class="header">
<div class="document-title">闆跺敭鍙戣揣鍗�</div>
@@ -838,18 +952,17 @@
</tr>
</thead>
<tbody>
- <tr v-for="product in item.products"
- :key="product.id">
- <td>{{ product.productCategory || '' }}</td>
- <td>{{ product.specificationModel || '' }}</td>
- <td>{{ product.unit || '' }}</td>
- <td>{{ product.taxInclusiveUnitPrice || '0' }}</td>
- <td>{{ product.quantity || '0' }}</td>
- <td>{{ product.taxInclusiveTotalPrice || '0' }}</td>
+ <tr v-for="product in item.products" :key="product.id">
+ <td>{{ product.productCategory || "" }}</td>
+ <td>{{ product.specificationModel || "" }}</td>
+ <td>{{ product.unit || "" }}</td>
+ <td>{{ product.taxInclusiveUnitPrice || "0" }}</td>
+ <td>{{ product.quantity || "0" }}</td>
+ <td>{{ product.taxInclusiveTotalPrice || "0" }}</td>
</tr>
<tr v-if="!item.products || item.products.length === 0">
- <td colspan="6"
- style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁
+ <td colspan="6" style="text-align: center; color: #999">
+ 鏆傛棤浜у搧鏁版嵁
</td>
</tr>
</tbody>
@@ -859,8 +972,12 @@
<td class="total-value"></td>
<td class="total-value"></td>
<td class="total-value"></td>
- <td class="total-value">{{ getTotalQuantity(item.products) }}</td>
- <td class="total-value">{{ getTotalAmount(item.products) }}</td>
+ <td class="total-value">
+ {{ getTotalQuantity(item.products) }}
+ </td>
+ <td class="total-value">
+ {{ getTotalAmount(item.products) }}
+ </td>
</tr>
</tfoot>
</table>
@@ -883,7 +1000,9 @@
<div class="footer-row">
<div class="footer-item">
<span class="label">鎿嶄綔鍛橈細</span>
- <span class="value">{{ userStore.nickName || '鎾曞紑鍓�' }}</span>
+ <span class="value">{{
+ userStore.nickName || "鎾曞紑鍓�"
+ }}</span>
</div>
<div class="footer-item">
<span class="label">鎵撳嵃鏃ユ湡锛�</span>
@@ -897,116 +1016,127 @@
</div>
</el-dialog>
<!-- 鍙戣揣寮规 -->
- <el-dialog v-model="deliveryFormVisible"
- title="鍙戣揣淇℃伅"
- width="40%"
- @close="closeDeliveryDia">
- <el-form :model="deliveryForm"
- label-width="120px"
- label-position="top"
- :rules="deliveryRules"
- ref="deliveryFormRef">
+ <el-dialog
+ v-model="deliveryFormVisible"
+ title="鍙戣揣淇℃伅"
+ width="40%"
+ @close="closeDeliveryDia"
+ >
+ <el-form
+ :model="deliveryForm"
+ label-width="120px"
+ label-position="top"
+ :rules="deliveryRules"
+ ref="deliveryFormRef"
+ >
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="鍙戣揣绫诲瀷锛�"
- prop="type">
- <el-select v-model="deliveryForm.type"
- placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
- style="width: 100%"
- @change="handleDeliveryTypeChange">
- <el-option label="璐ц溅"
- value="璐ц溅" />
- <el-option label="蹇��"
- value="蹇��" />
+ <el-form-item label="鍙戣揣绫诲瀷锛�" prop="type">
+ <el-select
+ v-model="deliveryForm.type"
+ placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
+ style="width: 100%"
+ @change="handleDeliveryTypeChange"
+ >
+ <el-option label="璐ц溅" value="璐ц溅" />
+ <el-option label="蹇��" value="蹇��" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="寰呭彂璐ф暟閲忥細">
- <el-input :model-value="currentDeliveryRow?.noQuantity"
- disabled />
+ <el-input
+ :model-value="currentDeliveryRow?.noQuantity"
+ disabled
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
- <el-col :span="24"
- v-if="deliveryForm.type === '璐ц溅'">
- <el-form-item label="鍙戣揣杞︾墝鍙凤細"
- prop="shippingCarNumber">
- <el-input v-model="deliveryForm.shippingCarNumber"
- placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
- clearable />
+ <el-col :span="24" v-if="deliveryForm.type === '璐ц溅'">
+ <el-form-item label="鍙戣揣杞︾墝鍙凤細" prop="shippingCarNumber">
+ <el-input
+ v-model="deliveryForm.shippingCarNumber"
+ placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
+ clearable
+ />
</el-form-item>
</el-col>
- <el-col :span="24"
- v-else>
- <el-form-item label="蹇�掑叕鍙革細"
- prop="expressCompany">
- <el-input v-model="deliveryForm.expressCompany"
- placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
- clearable />
+ <el-col :span="24" v-else>
+ <el-form-item label="蹇�掑叕鍙革細" prop="expressCompany">
+ <el-input
+ v-model="deliveryForm.expressCompany"
+ placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
+ clearable
+ />
</el-form-item>
</el-col>
</el-row>
- <el-row :gutter="30"
- v-if="deliveryForm.type === '蹇��'">
+ <el-row :gutter="30" v-if="deliveryForm.type === '蹇��'">
<el-col :span="24">
- <el-form-item label="蹇�掑崟鍙凤細"
- prop="expressNumber">
- <el-input v-model="deliveryForm.expressNumber"
- placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
- clearable />
+ <el-form-item label="蹇�掑崟鍙凤細" prop="expressNumber">
+ <el-input
+ v-model="deliveryForm.expressNumber"
+ placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
+ clearable
+ />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
<el-form-item label="鍙戣揣鍥剧墖锛�">
- <ImageUpload v-model:file-list="deliveryFileList"
- :limit="9" />
+ <ImageUpload v-model:file-list="deliveryFileList" :limit="9" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="30">
<el-col :span="24">
- <el-form-item label="搴撳瓨锛�"
- prop="batchNo">
- <el-table :data="deliveryForm.batchNoList"
- border
- size="small"
- max-height="260"
- style="width: 100%;">
- <el-table-column label="鎵瑰彿"
- prop="batchNo"
- min-width="180" />
- <el-table-column label="浜у搧澶х被"
- prop="productName"
- min-width="100" />
- <el-table-column label="瑙勬牸鍨嬪彿"
- prop="model"
- min-width="100" />
- <el-table-column label="鍗曚綅"
- prop="unit"
- min-width="100" />
- <el-table-column label="搴撳瓨鏁伴噺"
- min-width="120"
- align="center">
+ <el-form-item label="搴撳瓨锛�" prop="batchNo">
+ <el-table
+ :data="deliveryForm.batchNoList"
+ border
+ size="small"
+ max-height="260"
+ style="width: 100%"
+ >
+ <el-table-column label="鎵瑰彿" prop="batchNo" min-width="180" />
+ <el-table-column
+ label="浜у搧澶х被"
+ prop="productName"
+ min-width="100"
+ />
+ <el-table-column
+ label="瑙勬牸鍨嬪彿"
+ prop="model"
+ min-width="100"
+ />
+ <el-table-column label="鍗曚綅" prop="unit" min-width="100" />
+ <el-table-column
+ label="搴撳瓨鏁伴噺"
+ min-width="120"
+ align="center"
+ >
<template #default="scope">
{{ getDeliveryBatchQuantity(scope.row) }}
</template>
</el-table-column>
- <el-table-column label="鍙戣揣鏁伴噺"
- min-width="160"
- align="center">
+ <el-table-column
+ label="鍙戣揣鏁伴噺"
+ min-width="160"
+ align="center"
+ >
<template #default="scope">
- <el-input-number v-model="scope.row.deliveryQuantity"
- :min="0"
- :max="getDeliveryBatchDeliveryMax(scope.row)"
- :precision="2"
- :step="0.01"
- controls-position="right"
- @change="handleDeliveryBatchQuantityChange(scope.row)"
- style="width: 100%;" />
+ <el-input-number
+ v-model="scope.row.deliveryQuantity"
+ :min="0"
+ :max="getDeliveryBatchDeliveryMax(scope.row)"
+ :precision="2"
+ :step="0.01"
+ controls-position="right"
+ @change="handleDeliveryBatchQuantityChange(scope.row)"
+ style="width: 100%"
+ />
</template>
</el-table-column>
</el-table>
@@ -1016,8 +1146,8 @@
</el-form>
<template #footer>
<div class="dialog-footer">
- <el-button type="primary"
- @click="submitDelivery">纭鍙戣揣
+ <el-button type="primary" @click="submitDelivery"
+ >纭鍙戣揣
</el-button>
<el-button @click="closeDeliveryDia">鍙栨秷</el-button>
</div>
@@ -1027,1059 +1157,1062 @@
</template>
<script setup>
- import { getToken } from "@/utils/auth";
- import pagination from "@/components/PIMTable/Pagination.vue";
- import { onMounted, ref, getCurrentInstance } from "vue";
- import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
- import { ElMessageBox, ElMessage } from "element-plus";
- import useUserStore from "@/store/modules/user";
- import { userListNoPage } from "@/api/system/user.js";
- import FormDialog from "@/components/Dialog/FormDialog.vue";
- import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
- import {
- ledgerListPage,
- productList,
- customerList,
- addOrUpdateSalesLedger,
- getSalesLedgerWithProducts,
- delLedger,
- addOrUpdateSalesLedgerProduct,
- delProduct,
- delLedgerFile,
- getProductInventory,
- } from "@/api/salesManagement/salesLedger.js";
- import { getStockInventoryByModelId } from "@/api/inventoryManagement/stockInventory.js";
- import { modelList, productTreeList } from "@/api/basicData/product.js";
- import useFormData from "@/hooks/useFormData.js";
- import dayjs from "dayjs";
- import FileUpload from "@/components/AttachmentUpload/file/index.vue";
- import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
- import { getCurrentDate } from "@/utils/index.js";
- import { listCustomer } from "@/api/basicData/customer.js";
+import { getToken } from "@/utils/auth";
+import pagination from "@/components/PIMTable/Pagination.vue";
+import { onMounted, ref, getCurrentInstance } from "vue";
+import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
+import { ElMessageBox, ElMessage } from "element-plus";
+import useUserStore from "@/store/modules/user";
+import { userListNoPage } from "@/api/system/user.js";
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
+import {
+ ledgerListPage,
+ productList,
+ customerList,
+ addOrUpdateSalesLedger,
+ getSalesLedgerWithProducts,
+ delLedger,
+ addOrUpdateSalesLedgerProduct,
+ delProduct,
+ delLedgerFile,
+ getProductInventory,
+} from "@/api/salesManagement/salesLedger.js";
+import { getStockInventoryByModelId } from "@/api/inventoryManagement/stockInventory.js";
+import { modelList, productTreeList } from "@/api/basicData/product.js";
+import useFormData from "@/hooks/useFormData.js";
+import dayjs from "dayjs";
+import FileUpload from "@/components/AttachmentUpload/file/index.vue";
+import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
+import { getCurrentDate } from "@/utils/index.js";
+import { listCustomer } from "@/api/basicData/customer.js";
- const FileList = defineAsyncComponent(() =>
- import("@/components/Dialog/FileList.vue")
+const FileList = defineAsyncComponent(() =>
+ import("@/components/Dialog/FileList.vue")
+);
+
+const router = useRouter();
+const route = useRoute();
+const userStore = useUserStore();
+const { proxy } = getCurrentInstance();
+const { tax_rate } = proxy.useDict("tax_rate");
+const tableData = ref([]);
+const productData = ref([]);
+const selectedRows = ref([]);
+const productSelectedRows = ref([]);
+const userList = ref([]);
+const customerOption = ref([]);
+const productOptions = ref([]);
+const modelOptions = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+});
+const total = ref(0);
+const fileList = ref([]);
+const deliveryFileList = ref([]);
+
+// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ customerName: "", // 瀹㈡埛鍚嶇О
+ salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+ entryDate: null, // 褰曞叆鏃ユ湡
+ entryDateStart: undefined,
+ entryDateEnd: undefined,
+ },
+ form: {
+ salesContractNo: "",
+ autoGenerateContractNo: true,
+ salesman: "",
+ customerId: "",
+ entryPerson: "",
+ entryDate: "",
+ deliveryDate: "",
+ maintenanceTime: "",
+ productData: [],
+ executionDate: "",
+ hasProductionRecord: false,
+ createTime: "",
+ },
+ rules: {
+ salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+});
+const { form, rules } = toRefs(data);
+const { form: searchForm } = useFormData(data.searchForm);
+// 浜у搧琛ㄥ崟寮规鏁版嵁
+const productFormVisible = ref(false);
+const productOperationType = ref("");
+const currentId = ref("");
+const productFormData = reactive({
+ productForm: {
+ productCategory: "",
+ specificationModel: "",
+ unit: "",
+ quantity: "",
+ taxInclusiveUnitPrice: "",
+ taxRate: "",
+ taxInclusiveTotalPrice: "",
+ taxExclusiveTotalPrice: "",
+ invoiceType: "",
+ isProduction: false,
+ },
+ productRules: {
+ productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ specificationModel: [
+ { required: true, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ taxInclusiveUnitPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ taxInclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ taxExclusiveTotalPrice: [
+ { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+ ],
+ invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ isProduction: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ },
+});
+const { productForm, productRules } = toRefs(productFormData);
+// 闃叉寰幆璁$畻鐨勬爣蹇�
+const isCalculating = ref(false);
+// 鎵撳嵃鐩稿叧
+const printPreviewVisible = ref(false);
+const printData = ref([]);
+
+// 鎶ヤ环鍗曞鍏ョ浉鍏�
+const quotationDialogVisible = ref(false);
+const quotationLoading = ref(false);
+const quotationList = ref([]);
+const quotationSearchForm = reactive({
+ quotationNo: "",
+ customer: "",
+});
+// 鎶ヤ环鍗曞脊妗嗗垎椤�
+const quotationPage = reactive({
+ current: 1,
+ size: 10,
+ total: 0,
+});
+const selectedQuotation = ref(null);
+
+// 鍙戣揣鐩稿叧
+const deliveryFormVisible = ref(false);
+const currentDeliveryRow = ref(null);
+const getDeliveryBatchQuantity = (item) => {
+ const quantity =
+ item?.qualitity ??
+ item?.quantity ??
+ item?.unLockedQuantity ??
+ item?.qualifiedUnLockedQuantity ??
+ item?.qualifiedQuantity ??
+ item?.stockQuantity;
+ return quantity ?? 0;
+};
+const getCurrentDeliveryRowQuantity = () => {
+ return Number(currentDeliveryRow.value?.noQuantity || 0);
+};
+const getDeliveryBatchDeliveryMax = (row) => {
+ const productQuantity = getCurrentDeliveryRowQuantity();
+ const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
+ const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
+ (sum, item) => {
+ if (item?.id === row?.id) return sum;
+ return sum + Number(item?.deliveryQuantity || 0);
+ },
+ 0
);
+ const remainingProductQuantity = Math.max(
+ 0,
+ productQuantity - otherBatchTotal
+ );
+ return Math.max(0, Math.min(batchQuantity, remainingProductQuantity));
+};
+const handleDeliveryBatchQuantityChange = (row) => {
+ const productQuantity = getCurrentDeliveryRowQuantity();
+ const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
+ const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
+ (sum, item) => {
+ if (item?.id === row?.id) return sum;
+ return sum + Number(item?.deliveryQuantity || 0);
+ },
+ 0
+ );
+ const remainingProductQuantity = Math.max(
+ 0,
+ productQuantity - otherBatchTotal
+ );
+ const currentValue = Number(row?.deliveryQuantity || 0);
- const router = useRouter();
- const route = useRoute();
- const userStore = useUserStore();
- const { proxy } = getCurrentInstance();
- const { tax_rate } = proxy.useDict("tax_rate");
- const tableData = ref([]);
- const productData = ref([]);
- const selectedRows = ref([]);
- const productSelectedRows = ref([]);
- const userList = ref([]);
- const customerOption = ref([]);
- const productOptions = ref([]);
- const modelOptions = ref([]);
- const tableLoading = ref(false);
- const page = reactive({
- current: 1,
- size: 100,
- });
- const total = ref(0);
- const fileList = ref([]);
- const deliveryFileList = ref([]);
-
- // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
- const operationType = ref("");
- const dialogFormVisible = ref(false);
- const data = reactive({
- searchForm: {
- customerName: "", // 瀹㈡埛鍚嶇О
- salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
- entryDate: null, // 褰曞叆鏃ユ湡
- entryDateStart: undefined,
- entryDateEnd: undefined,
- },
- form: {
- salesContractNo: "",
- autoGenerateContractNo: true,
- salesman: "",
- customerId: "",
- entryPerson: "",
- entryDate: "",
- deliveryDate: "",
- maintenanceTime: "",
- productData: [],
- executionDate: "",
- hasProductionRecord: false,
- },
- rules: {
- salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
- });
- const { form, rules } = toRefs(data);
- const { form: searchForm } = useFormData(data.searchForm);
- // 浜у搧琛ㄥ崟寮规鏁版嵁
- const productFormVisible = ref(false);
- const productOperationType = ref("");
- const currentId = ref("");
- const productFormData = reactive({
- productForm: {
- productCategory: "",
- specificationModel: "",
- unit: "",
- quantity: "",
- taxInclusiveUnitPrice: "",
- taxRate: "",
- taxInclusiveTotalPrice: "",
- taxExclusiveTotalPrice: "",
- invoiceType: "",
- isProduction: false,
- },
- productRules: {
- productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- specificationModel: [
- { required: true, message: "璇烽�夋嫨", trigger: "change" },
- ],
- unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
- taxInclusiveUnitPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- taxInclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- taxExclusiveTotalPrice: [
- { required: true, message: "璇疯緭鍏�", trigger: "blur" },
- ],
- invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- isProduction: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
- },
- });
- const { productForm, productRules } = toRefs(productFormData);
- // 闃叉寰幆璁$畻鐨勬爣蹇�
- const isCalculating = ref(false);
- // 鎵撳嵃鐩稿叧
- const printPreviewVisible = ref(false);
- const printData = ref([]);
-
- // 鎶ヤ环鍗曞鍏ョ浉鍏�
- const quotationDialogVisible = ref(false);
- const quotationLoading = ref(false);
- const quotationList = ref([]);
- const quotationSearchForm = reactive({
- quotationNo: "",
- customer: "",
- });
- // 鎶ヤ环鍗曞脊妗嗗垎椤�
- const quotationPage = reactive({
- current: 1,
- size: 10,
- total: 0,
- });
- const selectedQuotation = ref(null);
-
- // 鍙戣揣鐩稿叧
- const deliveryFormVisible = ref(false);
- const currentDeliveryRow = ref(null);
- const getDeliveryBatchQuantity = item => {
- const quantity =
- item?.qualitity ??
- item?.quantity ??
- item?.unLockedQuantity ??
- item?.qualifiedUnLockedQuantity ??
- item?.qualifiedQuantity ??
- item?.stockQuantity;
- return quantity ?? 0;
- };
- const getCurrentDeliveryRowQuantity = () => {
- return Number(currentDeliveryRow.value?.noQuantity || 0);
- };
- const getDeliveryBatchDeliveryMax = row => {
- const productQuantity = getCurrentDeliveryRowQuantity();
- const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
- const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
- (sum, item) => {
- if (item?.id === row?.id) return sum;
- return sum + Number(item?.deliveryQuantity || 0);
- },
- 0
- );
- const remainingProductQuantity = Math.max(
- 0,
- productQuantity - otherBatchTotal
- );
- return Math.max(0, Math.min(batchQuantity, remainingProductQuantity));
- };
- const handleDeliveryBatchQuantityChange = row => {
- const productQuantity = getCurrentDeliveryRowQuantity();
- const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
- const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
- (sum, item) => {
- if (item?.id === row?.id) return sum;
- return sum + Number(item?.deliveryQuantity || 0);
- },
- 0
- );
- const remainingProductQuantity = Math.max(
- 0,
- productQuantity - otherBatchTotal
- );
- const currentValue = Number(row?.deliveryQuantity || 0);
-
- if (currentValue > batchQuantity) {
- row.deliveryQuantity = batchQuantity;
- proxy.$modal.msgWarning("鍙戣揣鏁伴噺涓嶈兘澶т簬搴撳瓨鏁伴噺");
- } else if (currentValue > remainingProductQuantity) {
- row.deliveryQuantity = remainingProductQuantity;
- proxy.$modal.msgWarning("鎵�鏈夋壒娆″彂璐ф暟閲忎箣鍜屼笉鑳藉ぇ浜庡緟鍙戣揣鏁伴噺");
- }
- };
- const getSelectedDeliveryBatchRows = () => {
- return (deliveryForm.value.batchNoList || []).filter(
- item => Number(item?.deliveryQuantity || 0) > 0
- );
- };
- const getDeliveryBatchNoList = async productModelId => {
- if (!productModelId) return [];
- const res = await getStockInventoryByModelId(productModelId);
- const rawList = Array.isArray(res?.data)
- ? res.data
- : res?.data?.records || res?.data?.rows || [];
- const seenIds = new Set();
- return rawList
- .filter(item => {
- if (!item?.id || !item?.batchNo || seenIds.has(item.id)) {
- return false;
- }
- seenIds.add(item.id);
- return true;
- })
- .map(item => ({
- ...item,
- deliveryQuantity: 0,
- }));
- };
- const validateDeliveryShippingCarNumber = (_rule, value, callback) => {
- if (deliveryForm.value.type === "璐ц溅" && !value) {
- return callback(new Error("璇疯緭鍏ュ彂璐ц溅鐗屽彿"));
- }
- callback();
- };
- const validateDeliveryExpressCompany = (_rule, value, callback) => {
- if (deliveryForm.value.type === "蹇��" && !value) {
- return callback(new Error("璇疯緭鍏ュ揩閫掑叕鍙�"));
- }
- callback();
- };
- const deliveryFormData = reactive({
- deliveryForm: {
- shippingCarNumber: "",
- expressCompany: "",
- expressNumber: "",
- type: "璐ц溅", // 璐ц溅, 蹇��
- },
- deliveryRules: {
- shippingCarNumber: [
- { validator: validateDeliveryShippingCarNumber, trigger: "blur" },
- ],
- expressCompany: [
- { validator: validateDeliveryExpressCompany, trigger: "blur" },
- ],
- type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
- },
- });
- const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
-
- // 瀵煎叆鐩稿叧
- const importUploadRef = ref(null);
- const importUpload = reactive({
- title: "瀵煎叆閿�鍞彴璐�",
- open: false,
- url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
- headers: { Authorization: "Bearer " + getToken() },
- isUploading: false,
- beforeUpload: file => {
- const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
- const isLt10M = file.size / 1024 / 1024 < 10;
- if (!isExcel) {
- proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
+ if (currentValue > batchQuantity) {
+ row.deliveryQuantity = batchQuantity;
+ proxy.$modal.msgWarning("鍙戣揣鏁伴噺涓嶈兘澶т簬搴撳瓨鏁伴噺");
+ } else if (currentValue > remainingProductQuantity) {
+ row.deliveryQuantity = remainingProductQuantity;
+ proxy.$modal.msgWarning("鎵�鏈夋壒娆″彂璐ф暟閲忎箣鍜屼笉鑳藉ぇ浜庡緟鍙戣揣鏁伴噺");
+ }
+};
+const getSelectedDeliveryBatchRows = () => {
+ return (deliveryForm.value.batchNoList || []).filter(
+ (item) => Number(item?.deliveryQuantity || 0) > 0
+ );
+};
+const getDeliveryBatchNoList = async (productModelId) => {
+ if (!productModelId) return [];
+ const res = await getStockInventoryByModelId(productModelId);
+ const rawList = Array.isArray(res?.data)
+ ? res.data
+ : res?.data?.records || res?.data?.rows || [];
+ const seenIds = new Set();
+ return rawList
+ .filter((item) => {
+ if (!item?.id || !item?.batchNo || seenIds.has(item.id)) {
return false;
}
- if (!isLt10M) {
- proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
- return false;
- }
+ seenIds.add(item.id);
return true;
- },
- onChange: (file, fileList) => {
- console.log("鏂囦欢鐘舵�佹敼鍙�", file, fileList);
- },
- onProgress: (event, file, fileList) => {
- console.log("涓婁紶涓�...", event.percent);
- },
- onSuccess: (response, file, fileList) => {
- console.log("涓婁紶鎴愬姛", response, file, fileList);
- importUpload.isUploading = false;
- if (response.code === 200) {
- proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
- importUpload.open = false;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
- getList();
- } else {
- proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
- }
- },
- onError: (error, file, fileList) => {
- console.error("涓婁紶澶辫触", error, file, fileList);
- importUpload.isUploading = false;
- proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
- },
- });
+ })
+ .map((item) => ({
+ ...item,
+ deliveryQuantity: 0,
+ }));
+};
+const validateDeliveryShippingCarNumber = (_rule, value, callback) => {
+ if (deliveryForm.value.type === "璐ц溅" && !value) {
+ return callback(new Error("璇疯緭鍏ュ彂璐ц溅鐗屽彿"));
+ }
+ callback();
+};
+const validateDeliveryExpressCompany = (_rule, value, callback) => {
+ if (deliveryForm.value.type === "蹇��" && !value) {
+ return callback(new Error("璇疯緭鍏ュ揩閫掑叕鍙�"));
+ }
+ callback();
+};
+const deliveryFormData = reactive({
+ deliveryForm: {
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "",
+ type: "璐ц溅", // 璐ц溅, 蹇��
+ },
+ deliveryRules: {
+ shippingCarNumber: [
+ { validator: validateDeliveryShippingCarNumber, trigger: "blur" },
+ ],
+ expressCompany: [
+ { validator: validateDeliveryExpressCompany, trigger: "blur" },
+ ],
+ type: [{ required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }],
+ },
+});
+const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
- const changeDaterange = value => {
- if (value) {
- searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
- searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
- } else {
- searchForm.entryDateStart = undefined;
- searchForm.entryDateEnd = undefined;
+// 瀵煎叆鐩稿叧
+const importUploadRef = ref(null);
+const importUpload = reactive({
+ title: "瀵煎叆閿�鍞彴璐�",
+ open: false,
+ url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
+ headers: { Authorization: "Bearer " + getToken() },
+ isUploading: false,
+ beforeUpload: (file) => {
+ const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls");
+ const isLt10M = file.size / 1024 / 1024 < 10;
+ if (!isExcel) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
+ return false;
}
- handleQuery();
- };
-
- // 鏌ヨ鍒楄〃
- /** 鎼滅储鎸夐挳鎿嶄綔 */
- const handleQuery = () => {
- // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
- // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
- if (arguments.length === 0) {
- page.current = 1;
- }
- expandedRowKeys.value = [];
- getList();
- };
- const paginationChange = obj => {
- page.current = obj.page;
- page.size = obj.limit;
- getList();
- };
- const getList = () => {
- tableLoading.value = true;
- const { entryDate, ...rest } = searchForm;
- // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
- const params = { ...rest, ...page };
- // 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
- delete params.entryDate;
- return ledgerListPage(params)
- .then(res => {
- tableLoading.value = false;
- tableData.value = res.records;
- tableData.value.map(item => {
- item.children = [];
- });
- total.value = res.total;
- return res;
- })
- .catch(() => {
- tableLoading.value = false;
- });
- };
- // 鑾峰彇浜у搧澶х被tree鏁版嵁
- const getProductOptions = () => {
- // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
- return productTreeList().then(res => {
- productOptions.value = convertIdToValue(res);
- return productOptions.value;
- });
- };
- const formattedNumber = (row, column, cellValue) => {
- if (cellValue === undefined || cellValue === null || cellValue === "") {
- return "0.00";
- }
- return parseFloat(cellValue).toFixed(2);
- };
- const findLedgerRecordByRow = row => {
- if (!row) return null;
- if (
- row.maintainer !== undefined ||
- row.maintainerName !== undefined ||
- row.entryPerson !== undefined ||
- row.entryPersonName !== undefined
- ) {
- return row;
- }
- if (row.salesLedgerId !== undefined && row.salesLedgerId !== null) {
- return (
- tableData.value.find(
- item => String(item.id) === String(row.salesLedgerId)
- ) || null
- );
- }
- return null;
- };
- const isCurrentUserMaintainer = row => {
- const ledgerRecord = findLedgerRecordByRow(row);
- if (!ledgerRecord) return true;
- const currentUserId = String(userStore.id ?? "");
- const currentNickName = String(userStore.nickName ?? "").trim();
- const maintainerId = ledgerRecord.maintainerId ?? ledgerRecord.entryPerson;
- const maintainerName =
- ledgerRecord.maintainerName ??
- ledgerRecord.maintainer ??
- ledgerRecord.entryPersonName;
- if (
- maintainerId !== undefined &&
- maintainerId !== null &&
- String(maintainerId) !== ""
- ) {
- return String(maintainerId) === currentUserId;
- }
- if (
- maintainerName !== undefined &&
- maintainerName !== null &&
- String(maintainerName).trim() !== ""
- ) {
- return String(maintainerName).trim() === currentNickName;
+ if (!isLt10M) {
+ proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+ return false;
}
return true;
- };
- const canEditLedger = row => isCurrentUserMaintainer(row);
- const canDeleteLedger = row => isCurrentUserMaintainer(row);
- const sensitiveAmountFormatter = (row, column, cellValue) => {
- if (!isCurrentUserMaintainer(row)) {
- return "*****";
- }
- return formattedNumber(row, column, cellValue);
- };
- // 鑾峰彇tree瀛愭暟鎹�
- const getModels = value => {
- productForm.value.productCategory = findNodeById(productOptions.value, value);
- modelList({ id: value }).then(res => {
- modelOptions.value = res;
- });
- };
- const getProductModel = value => {
- const index = modelOptions.value.findIndex(item => item.id === value);
- if (index !== -1) {
- productForm.value.specificationModel = modelOptions.value[index].model;
- productForm.value.unit = modelOptions.value[index].unit;
+ },
+ onChange: (file, fileList) => {
+ console.log("鏂囦欢鐘舵�佹敼鍙�", file, fileList);
+ },
+ onProgress: (event, file, fileList) => {
+ console.log("涓婁紶涓�...", event.percent);
+ },
+ onSuccess: (response, file, fileList) => {
+ console.log("涓婁紶鎴愬姛", response, file, fileList);
+ importUpload.isUploading = false;
+ if (response.code === 200) {
+ proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
+ importUpload.open = false;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles();
+ }
+ getList();
} else {
- productForm.value.specificationModel = null;
- productForm.value.unit = null;
+ proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
}
- };
- const findNodeById = (nodes, productId) => {
- for (let i = 0; i < nodes.length; i++) {
- if (nodes[i].value === productId) {
- return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
- }
- if (nodes[i].children && nodes[i].children.length > 0) {
- const foundNode = findNodeById(nodes[i].children, productId);
- if (foundNode) {
- return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
- }
- }
- }
- return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
- };
+ },
+ onError: (error, file, fileList) => {
+ console.error("涓婁紶澶辫触", error, file, fileList);
+ importUpload.isUploading = false;
+ proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
+ },
+});
- function convertIdToValue(data) {
- return data.map(item => {
- const { id, children, ...rest } = item;
- const newItem = {
- ...rest,
- value: id, // 灏� id 鏀逛负 value
- };
- if (children && children.length > 0) {
- newItem.children = convertIdToValue(children);
- }
-
- return newItem;
- });
+const changeDaterange = (value) => {
+ if (value) {
+ searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+ searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+ } else {
+ searchForm.entryDateStart = undefined;
+ searchForm.entryDateEnd = undefined;
}
+ handleQuery();
+};
- // 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
- function findNodeIdByLabel(nodes, label) {
- if (!label) return null;
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if (node.label === label) return node.value;
- if (node.children && node.children.length > 0) {
- const found = findNodeIdByLabel(node.children, label);
- if (found !== null && found !== undefined) return found;
- }
- }
- return null;
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ // 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
+ // 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
+ if (arguments.length === 0) {
+ page.current = 1;
}
-
- // 琛ㄦ牸閫夋嫨鏁版嵁
- const handleSelectionChange = selection => {
- // 杩囨护鎺夊瓙鏁版嵁
- selectedRows.value = selection.filter(item => item.children !== undefined);
- console.log("selection", selectedRows.value);
- };
- const productSelected = selectedRows => {
- productSelectedRows.value = selectedRows;
- };
- const expandedRowKeys = ref([]);
- // 灞曞紑琛�
- const expandChange = (row, expandedRows) => {
- if (expandedRows.length > 0) {
- expandedRowKeys.value = [];
- try {
- productList({ salesLedgerId: row.id, type: 1 }).then(res => {
- const index = tableData.value.findIndex(item => item.id === row.id);
- if (index > -1) {
- tableData.value[index].children = res.data;
- }
- expandedRowKeys.value.push(row.id);
- });
- } catch (error) {
- console.log(error);
- }
- } else {
- expandedRowKeys.value = [];
- }
- };
-
- // 娣诲姞琛ㄨ绫诲悕鏂规硶
- const tableRowClassName = ({ row }) => {
- if (!row.deliveryDate) return "";
- if (row.isFh) return "";
-
- const diff = row.deliveryDaysDiff;
- if (diff === 15) {
- return "yellow";
- } else if (diff === 10) {
- return "pink";
- } else if (diff === 2) {
- return "purple";
- } else if (diff < 2) {
- return "red";
- }
- };
- // 涓昏〃鍚堣鏂规硶
- const summarizeMainTable = param => {
- return proxy.summarizeTable(param, [
- "contractAmount",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
- };
- // 瀛愯〃鍚堣鏂规硶
- const summarizeChildrenTable = (param, parentRow) => {
- if (!isCurrentUserMaintainer(parentRow)) {
- const { columns } = param;
- return columns.map((column, index) => {
- if (index === 0) {
- return "鍚堣";
- }
- if (
- [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ].includes(column.property)
- ) {
- return "*****";
- }
- return "";
+ expandedRowKeys.value = [];
+ getList();
+};
+const paginationChange = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ const { entryDate, ...rest } = searchForm;
+ // 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
+ const params = { ...rest, ...page };
+ // 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
+ delete params.entryDate;
+ return ledgerListPage(params)
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.records;
+ tableData.value.map((item) => {
+ item.children = [];
});
- }
- return proxy.summarizeTable(param, [
- "taxInclusiveUnitPrice",
- "taxInclusiveTotalPrice",
- "taxExclusiveTotalPrice",
- ]);
- };
- // 鎵撳紑寮规
- const openForm = async (type, row) => {
- if (type === "edit" && row && !canEditLedger(row)) {
- proxy.$modal.msgWarning("褰撳墠绯荤粺鐧诲綍浜轰笉鏄淮鎶や汉锛屼笉鑳界紪杈戞暟鎹�");
- return;
- }
- operationType.value = type;
- form.value = {};
- productData.value = [];
- selectedQuotation.value = null;
- let userLists = await userListNoPage();
- userList.value = userLists.data;
- listCustomer({ current: -1, size: -1, type: 0 }).then(res => {
- customerOption.value = res.data.records;
- });
- form.value.entryPerson = userStore.id;
- if (type === "add") {
- // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
- form.value.entryDate = getCurrentDate();
- // 绛捐鏃ユ湡榛樿涓哄綋澶�
- form.value.executionDate = getCurrentDate();
- // 榛樿鑷姩鐢熸垚閿�鍞悎鍚屽彿
- form.value.autoGenerateContractNo = true;
- } else {
- currentId.value = row.id;
- getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
- form.value = { ...res };
- form.value.entryPerson = Number(res.entryPerson);
- productData.value = form.value.productData;
- fileList.value = form.value.storageBlobVOs;
- // 缂栬緫鏃惰缃嚜鍔ㄧ敓鎴愪负false锛屽厑璁告墜鍔ㄤ慨鏀�
- form.value.autoGenerateContractNo = false;
- });
- }
- // let userAll = await userStore.getInfo()
- // userList.value.forEach(element => {
- // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
- // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
- // }
- // });
- form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
- dialogFormVisible.value = true;
- };
-
- // 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
- const openQuotationDialog = async () => {
- if (operationType.value === "view") return;
- quotationDialogVisible.value = true;
- // 鎵撳紑寮圭獥鏃堕噸缃垎椤靛埌绗竴椤�
- quotationPage.current = 1;
- // 鍏堢‘淇濆鎴峰垪琛ㄥ凡鍔犺浇锛屼究浜庡悗缁洖濉� customerId
- if (!customerOption.value || customerOption.value.length === 0) {
- try {
- listCustomer({ current: -1, size: -1 }).then(res => {
- customerOption.value = res.data.records;
- });
- } catch (e) {
- // ignore锛屽厑璁哥敤鎴峰悗缁墜鍔ㄩ�夋嫨瀹㈡埛
- }
- }
- await fetchQuotationList();
- };
-
- const fetchQuotationList = async () => {
- quotationLoading.value = true;
- try {
- const params = {
- // 鍚庣鍒嗛〉瀛楁锛歝urrent / size
- current: quotationPage.current,
- size: quotationPage.size,
- ...quotationSearchForm,
- status: "閫氳繃",
- };
- const res = await getQuotationList(params);
- quotationList.value = res?.data?.records || [];
- quotationPage.total = res?.data?.total || 0;
- } finally {
- quotationLoading.value = false;
- }
- };
-
- const resetQuotationSearch = async () => {
- quotationSearchForm.quotationNo = "";
- quotationSearchForm.customer = "";
- quotationPage.current = 1;
- await fetchQuotationList();
- };
-
- // 鎶ヤ环鍗曞脊妗嗗垎椤靛垏鎹�
- const quotationPaginationChange = obj => {
- quotationPage.current = obj.page;
- quotationPage.size = obj.limit;
- fetchQuotationList();
- };
-
- // 閫変腑鎶ヤ环鍗曞悗鍥炲~鍒板彴璐﹁〃鍗�
- const applyQuotation = row => {
- if (!row) return;
- selectedQuotation.value = row;
-
- // 涓氬姟鍛�
- form.value.salesman = (row.salesperson || "").trim();
-
- // 瀹㈡埛鍚嶇О -> customerId
- const qCustomerName = String(row.customer || "").trim();
- const customer = (customerOption.value || []).find(c => {
- const name = String(c.customerName || "").trim();
- return (
- name === qCustomerName ||
- name.includes(qCustomerName) ||
- qCustomerName.includes(name)
- );
- });
- if (customer?.id) {
- form.value.customerId = customer.id;
- } else {
- // 濡傛灉鎵句笉鍒帮紝淇濈暀鍘熷�硷紙鍏佽鐢ㄦ埛鎵嬪姩閫夋嫨/涓嶆墦鏂凡鏈夎緭鍏ワ級
- form.value.customerId = form.value.customerId || "";
- }
-
- // 浜у搧淇℃伅鏄犲皠锛氭姤浠� products -> 鍙拌处 productData
- const products = Array.isArray(row.products) ? row.products : [];
- productData.value = products.map(p => {
- const quantity = Number(p.quantity ?? 0) || 0;
- const unitPrice = Number(p.unitPrice ?? 0) || 0;
- const taxRate = "13"; // 榛樿 13%锛屼究浜庣洿鎺ユ彁浜わ紙濡傞渶鍙湪浜у搧涓嚜琛屼慨鏀癸級
- const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
- const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(
- taxInclusiveTotalPrice,
- taxRate
- );
- return {
- // 鍙拌处瀛楁
- productCategory: p.product || p.productName || "",
- specificationModel: p.specification || "",
- unit: p.unit || "",
- quantity: quantity,
- taxRate: taxRate,
- taxInclusiveUnitPrice: unitPrice.toFixed(2),
- taxInclusiveTotalPrice: taxInclusiveTotalPrice,
- taxExclusiveTotalPrice: taxExclusiveTotalPrice,
- invoiceType: "澧炴櫘绁�",
- isProduction: true,
- productId: p.productId,
- productModelId: p.productModelId,
- };
- });
-
- quotationDialogVisible.value = false;
- };
-
- function changs(val) {
- console.log(val);
- }
-
- // 鎻愪氦琛ㄥ崟
- const submitForm = () => {
- proxy.$refs["formRef"].validate(valid => {
- if (valid) {
- console.log("productData.value--", productData.value);
- if (productData.value !== null && productData.value.length > 0) {
- form.value.productData = proxy.HaveJson(productData.value);
- } else {
- proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
- return;
- }
- form.value.storageBlobDTOs = fileList;
- form.value.type = 1;
- if (form.value.autoGenerateContractNo) {
- form.value.salesContractNo = "";
- }
- addOrUpdateSalesLedger(form.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeDia();
- expandedRowKeys.value = [];
- getList();
- });
- }
- });
- };
- // 鍏抽棴寮规
- const closeDia = () => {
- proxy.resetForm("formRef");
- dialogFormVisible.value = false;
- };
-
- const productIndex = ref(0);
- // 鎵撳紑浜у搧寮规
- const openProductForm = async (type, row, index) => {
- // 缂栬緫鏃舵鏌ヤ骇鍝佹槸鍚﹀凡鍙戣揣鎴栧鏍搁�氳繃
- if (type === "edit" && isProductShipped(row)) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳界紪杈�");
- return;
- }
-
- productOperationType.value = type;
- productForm.value = {};
- if (type === "add") {
- productForm.value.isProduction = true;
- }
- proxy.resetForm("productFormRef");
- if (type === "edit") {
- productForm.value = { ...row };
- productIndex.value = index;
- // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
- try {
- const options =
- productOptions.value && productOptions.value.length > 0
- ? productOptions.value
- : await getProductOptions();
- const categoryId = findNodeIdByLabel(
- options,
- productForm.value.productCategory
- );
- if (categoryId) {
- const models = await modelList({ id: categoryId });
- modelOptions.value = models || [];
- // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
- const currentModel = (modelOptions.value || []).find(
- m => m.model === productForm.value.specificationModel
- );
- if (currentModel) {
- productForm.value.productModelId = currentModel.id;
- }
- }
- } catch (e) {
- // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
- console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
- }
- } else {
- getProductOptions();
- }
- productFormVisible.value = true;
- };
- // 鎻愪氦浜у搧琛ㄥ崟
- const submitProduct = () => {
- proxy.$refs["productFormRef"].validate(valid => {
- if (valid) {
- if (operationType.value === "edit") {
- submitProductEdit();
- } else {
- if (productOperationType.value === "add") {
- productData.value.push({ ...productForm.value });
- } else {
- productData.value[productIndex.value] = { ...productForm.value };
- }
- closeProductDia();
- }
- }
- });
- };
- const submitProductEdit = () => {
- productForm.value.salesLedgerId = currentId.value;
- productForm.value.type = 1;
- addOrUpdateSalesLedgerProduct(productForm.value).then(res => {
- proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(res => {
- productData.value = res.productData;
- });
- });
- };
- // 鍒犻櫎浜у搧
- const deleteProduct = () => {
- if (productSelectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
-
- // 妫�鏌ユ槸鍚︽湁宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝�
- const shippedProducts = productSelectedRows.value.filter(row =>
- isProductShipped(row)
- );
- if (shippedProducts.length > 0) {
- proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳藉垹闄�");
- return;
- }
-
- if (operationType.value === "add") {
- productData.value = productData.value.filter(
- item => !productSelectedRows.value.includes(item)
- );
- productSelectedRows.value = [];
- } else {
- let ids = [];
- if (productSelectedRows.value.length > 0) {
- ids = productSelectedRows.value.map(item => item.id);
- }
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
- })
- .then(() => {
- delProduct(ids).then(res => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- closeProductDia();
- getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
- res => {
- productData.value = res.productData;
- }
- );
- });
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- }
- };
- // 鍏抽棴浜у搧寮规
- const closeProductDia = () => {
- proxy.resetForm("productFormRef");
- productFormVisible.value = false;
- };
- // 瀵煎叆
- const handleImport = () => {
- importUpload.title = "瀵煎叆閿�鍞彴璐�";
- importUpload.open = true;
- if (importUploadRef.value) {
- importUploadRef.value.clearFiles();
- }
- };
-
- // 涓嬭浇瀵煎叆妯℃澘
- const downloadTemplate = () => {
- proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
- };
-
- // 鎻愪氦瀵煎叆鏂囦欢
- const submitImportFile = () => {
- importUpload.isUploading = true;
- proxy.$refs["importUploadRef"].submit();
- };
-
- // 瀵煎嚭
- const handleOut = () => {
- ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
- confirmButtonText: "纭",
- cancelButtonText: "鍙栨秷",
- type: "warning",
+ total.value = res.total;
+ return res;
})
- .then(() => {
- proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
- };
- /** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
- const isProductShipped = product => {
- if (!product) return false;
- const status = String(product.shippingStatus || "").trim();
- // 濡傛灉鍙戣揣鐘舵�佹槸"宸插彂璐�"鎴�"瀹℃牳閫氳繃"锛屽垯涓嶅彲缂栬緫鍜屽垹闄�
- return status === "宸插彂璐�" || status === "瀹℃牳閫氳繃";
- };
-
- /** 鍒ゆ柇閿�鍞鍗曚笅鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝侊紙涓嶅彲鍒犻櫎锛� */
- const hasShippedProducts = products => {
- if (!products || !products.length) return false;
- return products.some(p => {
- const status = String(p.shippingStatus || "").trim();
- // 鏈夊彂璐ф棩鏈熸垨杞︾墝鍙疯涓哄凡鍙戣揣
- if (p.shippingDate || p.shippingCarNumber) return true;
- // 宸茶繘琛屽彂璐с�佸彂璐у畬鎴愩�佸凡鍙戣揣 鍧囦笉鍙垹闄�
- return (
- status === "宸茶繘琛屽彂璐�" || status === "鍙戣揣瀹屾垚" || status === "宸插彂璐�"
- );
+ .catch(() => {
+ tableLoading.value = false;
});
- };
-
- // 鍒犻櫎
- const handleDelete = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
- return;
- }
- const unauthorizedRows = selectedRows.value.filter(
- row => !canDeleteLedger(row)
+};
+// 鑾峰彇浜у搧澶х被tree鏁版嵁
+const getProductOptions = () => {
+ // 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
+ return productTreeList().then((res) => {
+ productOptions.value = convertIdToValue(res);
+ return productOptions.value;
+ });
+};
+const formattedNumber = (row, column, cellValue) => {
+ if (cellValue === undefined || cellValue === null || cellValue === "") {
+ return "0.00";
+ }
+ return parseFloat(cellValue).toFixed(2);
+};
+const findLedgerRecordByRow = (row) => {
+ if (!row) return null;
+ if (
+ row.maintainer !== undefined ||
+ row.maintainerName !== undefined ||
+ row.entryPerson !== undefined ||
+ row.entryPersonName !== undefined
+ ) {
+ return row;
+ }
+ if (row.salesLedgerId !== undefined && row.salesLedgerId !== null) {
+ return (
+ tableData.value.find(
+ (item) => String(item.id) === String(row.salesLedgerId)
+ ) || null
);
- if (unauthorizedRows.length > 0) {
- proxy.$modal.msgWarning("褰撳墠鐧诲綍鐢ㄦ埛涓嶆槸褰曞叆浜猴紝涓嶈兘鍒犻櫎璇ユ暟鎹�");
- return;
+ }
+ return null;
+};
+const isCurrentUserMaintainer = (row) => {
+ const ledgerRecord = findLedgerRecordByRow(row);
+ if (!ledgerRecord) return true;
+ const currentUserId = String(userStore.id ?? "");
+ const currentNickName = String(userStore.nickName ?? "").trim();
+ const maintainerId = ledgerRecord.maintainerId ?? ledgerRecord.entryPerson;
+ const maintainerName =
+ ledgerRecord.maintainerName ??
+ ledgerRecord.maintainer ??
+ ledgerRecord.entryPersonName;
+ if (
+ maintainerId !== undefined &&
+ maintainerId !== null &&
+ String(maintainerId) !== ""
+ ) {
+ return String(maintainerId) === currentUserId;
+ }
+ if (
+ maintainerName !== undefined &&
+ maintainerName !== null &&
+ String(maintainerName).trim() !== ""
+ ) {
+ return String(maintainerName).trim() === currentNickName;
+ }
+ return true;
+};
+const canEditLedger = (row) => isCurrentUserMaintainer(row);
+const canDeleteLedger = (row) => isCurrentUserMaintainer(row);
+const sensitiveAmountFormatter = (row, column, cellValue) => {
+ if (!isCurrentUserMaintainer(row)) {
+ return "*****";
+ }
+ return formattedNumber(row, column, cellValue);
+};
+// 鑾峰彇tree瀛愭暟鎹�
+const getModels = (value) => {
+ productForm.value.productCategory = findNodeById(productOptions.value, value);
+ modelList({ id: value }).then((res) => {
+ modelOptions.value = res;
+ });
+};
+const getProductModel = (value) => {
+ const index = modelOptions.value.findIndex((item) => item.id === value);
+ if (index !== -1) {
+ productForm.value.specificationModel = modelOptions.value[index].model;
+ productForm.value.unit = modelOptions.value[index].unit;
+ } else {
+ productForm.value.specificationModel = null;
+ productForm.value.unit = null;
+ }
+};
+const findNodeById = (nodes, productId) => {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].value === productId) {
+ return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
}
- const ids = selectedRows.value.map(item => item.id);
+ if (nodes[i].children && nodes[i].children.length > 0) {
+ const foundNode = findNodeById(nodes[i].children, productId);
+ if (foundNode) {
+ return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+ }
+ }
+ }
+ return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+};
- // 妫�鏌ユ槸鍚︽湁宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曪紝鑻ユ湁鍒欎笉鍏佽鍒犻櫎
- const cannotDeleteNames = [];
- for (const row of selectedRows.value) {
- let products =
- row.children && row.children.length > 0 ? row.children : null;
- if (!products) {
- try {
- const res = await productList({ salesLedgerId: row.id, type: 1 });
- products = res.data || [];
- } catch {
- products = [];
+function convertIdToValue(data) {
+ return data.map((item) => {
+ const { id, children, ...rest } = item;
+ const newItem = {
+ ...rest,
+ value: id, // 灏� id 鏀逛负 value
+ };
+ if (children && children.length > 0) {
+ newItem.children = convertIdToValue(children);
+ }
+
+ return newItem;
+ });
+}
+
+// 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
+function findNodeIdByLabel(nodes, label) {
+ if (!label) return null;
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ if (node.label === label) return node.value;
+ if (node.children && node.children.length > 0) {
+ const found = findNodeIdByLabel(node.children, label);
+ if (found !== null && found !== undefined) return found;
+ }
+ }
+ return null;
+}
+
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ // 杩囨护鎺夊瓙鏁版嵁
+ selectedRows.value = selection.filter((item) => item.children !== undefined);
+ console.log("selection", selectedRows.value);
+};
+const productSelected = (selectedRows) => {
+ productSelectedRows.value = selectedRows;
+};
+const expandedRowKeys = ref([]);
+// 灞曞紑琛�
+const expandChange = (row, expandedRows) => {
+ if (expandedRows.length > 0) {
+ expandedRowKeys.value = [];
+ try {
+ productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
+ const index = tableData.value.findIndex((item) => item.id === row.id);
+ if (index > -1) {
+ tableData.value[index].children = res.data;
+ }
+ expandedRowKeys.value.push(row.id);
+ });
+ } catch (error) {
+ console.log(error);
+ }
+ } else {
+ expandedRowKeys.value = [];
+ }
+};
+
+// 娣诲姞琛ㄨ绫诲悕鏂规硶
+const tableRowClassName = ({ row }) => {
+ if (!row.deliveryDate) return "";
+ if (row.isFh) return "";
+
+ const diff = row.deliveryDaysDiff;
+ if (diff === 15) {
+ return "yellow";
+ } else if (diff === 10) {
+ return "pink";
+ } else if (diff === 2) {
+ return "purple";
+ } else if (diff < 2) {
+ return "red";
+ }
+};
+// 涓昏〃鍚堣鏂规硶
+const summarizeMainTable = (param) => {
+ return proxy.summarizeTable(param, [
+ "contractAmount",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
+};
+// 瀛愯〃鍚堣鏂规硶
+const summarizeChildrenTable = (param, parentRow) => {
+ if (!isCurrentUserMaintainer(parentRow)) {
+ const { columns } = param;
+ return columns.map((column, index) => {
+ if (index === 0) {
+ return "鍚堣";
+ }
+ if (
+ [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ].includes(column.property)
+ ) {
+ return "*****";
+ }
+ return "";
+ });
+ }
+ return proxy.summarizeTable(param, [
+ "taxInclusiveUnitPrice",
+ "taxInclusiveTotalPrice",
+ "taxExclusiveTotalPrice",
+ ]);
+};
+// 鎵撳紑寮规
+const openForm = async (type, row) => {
+ if (type === "edit" && row && !canEditLedger(row)) {
+ proxy.$modal.msgWarning("褰撳墠绯荤粺鐧诲綍浜轰笉鏄淮鎶や汉锛屼笉鑳界紪杈戞暟鎹�");
+ return;
+ }
+ operationType.value = type;
+ form.value = {};
+ productData.value = [];
+ selectedQuotation.value = null;
+ let userLists = await userListNoPage();
+ userList.value = userLists.data;
+ listCustomer({ current: -1, size: -1, type: 0 }).then((res) => {
+ customerOption.value = res.data.records;
+ });
+ form.value.entryPerson = userStore.id;
+ if (type === "add") {
+ // 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
+ form.value.entryDate = getCurrentDate();
+ // 绛捐鏃ユ湡榛樿涓哄綋澶�
+ form.value.executionDate = getCurrentDate();
+ // 鍒涘缓鏃堕棿榛樿涓哄綋澶�
+ form.value.createTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
+ // 榛樿鑷姩鐢熸垚閿�鍞悎鍚屽彿
+ form.value.autoGenerateContractNo = true;
+ } else {
+ currentId.value = row.id;
+ getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
+ form.value = { ...res };
+ form.value.entryPerson = Number(res.entryPerson);
+ productData.value = form.value.productData;
+ fileList.value = form.value.storageBlobVOs;
+ // 缂栬緫鏃惰缃嚜鍔ㄧ敓鎴愪负false锛屽厑璁告墜鍔ㄤ慨鏀�
+ form.value.autoGenerateContractNo = false;
+ });
+ }
+ // let userAll = await userStore.getInfo()
+ // userList.value.forEach(element => {
+ // if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
+ // form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
+ // }
+ // });
+ form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
+ dialogFormVisible.value = true;
+};
+
+// 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
+const openQuotationDialog = async () => {
+ if (operationType.value === "view") return;
+ quotationDialogVisible.value = true;
+ // 鎵撳紑寮圭獥鏃堕噸缃垎椤靛埌绗竴椤�
+ quotationPage.current = 1;
+ // 鍏堢‘淇濆鎴峰垪琛ㄥ凡鍔犺浇锛屼究浜庡悗缁洖濉� customerId
+ if (!customerOption.value || customerOption.value.length === 0) {
+ try {
+ listCustomer({ current: -1, size: -1 }).then((res) => {
+ customerOption.value = res.data.records;
+ });
+ } catch (e) {
+ // ignore锛屽厑璁哥敤鎴峰悗缁墜鍔ㄩ�夋嫨瀹㈡埛
+ }
+ }
+ await fetchQuotationList();
+};
+
+const fetchQuotationList = async () => {
+ quotationLoading.value = true;
+ try {
+ const params = {
+ // 鍚庣鍒嗛〉瀛楁锛歝urrent / size
+ current: quotationPage.current,
+ size: quotationPage.size,
+ ...quotationSearchForm,
+ status: "閫氳繃",
+ };
+ const res = await getQuotationList(params);
+ quotationList.value = res?.data?.records || [];
+ quotationPage.total = res?.data?.total || 0;
+ } finally {
+ quotationLoading.value = false;
+ }
+};
+
+const resetQuotationSearch = async () => {
+ quotationSearchForm.quotationNo = "";
+ quotationSearchForm.customer = "";
+ quotationPage.current = 1;
+ await fetchQuotationList();
+};
+
+// 鎶ヤ环鍗曞脊妗嗗垎椤靛垏鎹�
+const quotationPaginationChange = (obj) => {
+ quotationPage.current = obj.page;
+ quotationPage.size = obj.limit;
+ fetchQuotationList();
+};
+
+// 閫変腑鎶ヤ环鍗曞悗鍥炲~鍒板彴璐﹁〃鍗�
+const applyQuotation = (row) => {
+ if (!row) return;
+ selectedQuotation.value = row;
+
+ // 涓氬姟鍛�
+ form.value.salesman = (row.salesperson || "").trim();
+
+ // 瀹㈡埛鍚嶇О -> customerId
+ const qCustomerName = String(row.customer || "").trim();
+ const customer = (customerOption.value || []).find((c) => {
+ const name = String(c.customerName || "").trim();
+ return (
+ name === qCustomerName ||
+ name.includes(qCustomerName) ||
+ qCustomerName.includes(name)
+ );
+ });
+ if (customer?.id) {
+ form.value.customerId = customer.id;
+ } else {
+ // 濡傛灉鎵句笉鍒帮紝淇濈暀鍘熷�硷紙鍏佽鐢ㄦ埛鎵嬪姩閫夋嫨/涓嶆墦鏂凡鏈夎緭鍏ワ級
+ form.value.customerId = form.value.customerId || "";
+ }
+
+ // 浜у搧淇℃伅鏄犲皠锛氭姤浠� products -> 鍙拌处 productData
+ const products = Array.isArray(row.products) ? row.products : [];
+ productData.value = products.map((p) => {
+ const quantity = Number(p.quantity ?? 0) || 0;
+ const unitPrice = Number(p.unitPrice ?? 0) || 0;
+ const taxRate = "13"; // 榛樿 13%锛屼究浜庣洿鎺ユ彁浜わ紙濡傞渶鍙湪浜у搧涓嚜琛屼慨鏀癸級
+ const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+ const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(
+ taxInclusiveTotalPrice,
+ taxRate
+ );
+ return {
+ // 鍙拌处瀛楁
+ productCategory: p.product || p.productName || "",
+ specificationModel: p.specification || "",
+ unit: p.unit || "",
+ quantity: quantity,
+ taxRate: taxRate,
+ taxInclusiveUnitPrice: unitPrice.toFixed(2),
+ taxInclusiveTotalPrice: taxInclusiveTotalPrice,
+ taxExclusiveTotalPrice: taxExclusiveTotalPrice,
+ invoiceType: "澧炴櫘绁�",
+ isProduction: true,
+ productId: p.productId,
+ productModelId: p.productModelId,
+ };
+ });
+
+ quotationDialogVisible.value = false;
+};
+
+function changs(val) {
+ console.log(val);
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ console.log("productData.value--", productData.value);
+ if (productData.value !== null && productData.value.length > 0) {
+ form.value.productData = proxy.HaveJson(productData.value);
+ } else {
+ proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+ return;
+ }
+ form.value.storageBlobDTOs = fileList;
+ form.value.type = 1;
+ if (form.value.autoGenerateContractNo) {
+ form.value.salesContractNo = "";
+ }
+ addOrUpdateSalesLedger(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ expandedRowKeys.value = [];
+ getList();
+ });
+ }
+ });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+
+const productIndex = ref(0);
+// 鎵撳紑浜у搧寮规
+const openProductForm = async (type, row, index) => {
+ // 缂栬緫鏃舵鏌ヤ骇鍝佹槸鍚﹀凡鍙戣揣鎴栧鏍搁�氳繃
+ if (type === "edit" && isProductShipped(row)) {
+ proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳界紪杈�");
+ return;
+ }
+
+ productOperationType.value = type;
+ productForm.value = {};
+ if (type === "add") {
+ productForm.value.isProduction = true;
+ }
+ proxy.resetForm("productFormRef");
+ if (type === "edit") {
+ productForm.value = { ...row };
+ productIndex.value = index;
+ // 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
+ try {
+ const options =
+ productOptions.value && productOptions.value.length > 0
+ ? productOptions.value
+ : await getProductOptions();
+ const categoryId = findNodeIdByLabel(
+ options,
+ productForm.value.productCategory
+ );
+ if (categoryId) {
+ const models = await modelList({ id: categoryId });
+ modelOptions.value = models || [];
+ // 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
+ const currentModel = (modelOptions.value || []).find(
+ (m) => m.model === productForm.value.specificationModel
+ );
+ if (currentModel) {
+ productForm.value.productModelId = currentModel.id;
}
}
- if (hasShippedProducts(products)) {
- cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
+ } catch (e) {
+ // 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
+ console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
+ }
+ } else {
+ getProductOptions();
+ }
+ productFormVisible.value = true;
+};
+// 鎻愪氦浜у搧琛ㄥ崟
+const submitProduct = () => {
+ proxy.$refs["productFormRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitProductEdit();
+ } else {
+ if (productOperationType.value === "add") {
+ productData.value.push({ ...productForm.value });
+ } else {
+ productData.value[productIndex.value] = { ...productForm.value };
+ }
+ closeProductDia();
}
}
- if (cannotDeleteNames.length > 0) {
- proxy.$modal.msgWarning(
- "宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄わ細" + cannotDeleteNames.join("銆�")
- );
- return;
- }
+ });
+};
+const submitProductEdit = () => {
+ productForm.value.salesLedgerId = currentId.value;
+ productForm.value.type = 1;
+ addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
+ productData.value = res.productData;
+ });
+ });
+};
+// 鍒犻櫎浜у搧
+const deleteProduct = () => {
+ if (productSelectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ // 妫�鏌ユ槸鍚︽湁宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝�
+ const shippedProducts = productSelectedRows.value.filter((row) =>
+ isProductShipped(row)
+ );
+ if (shippedProducts.length > 0) {
+ proxy.$modal.msgWarning("宸插彂璐ф垨瀹℃牳閫氳繃鐨勪骇鍝佷笉鑳藉垹闄�");
+ return;
+ }
+
+ if (operationType.value === "add") {
+ productData.value = productData.value.filter(
+ (item) => !productSelectedRows.value.includes(item)
+ );
+ productSelectedRows.value = [];
+ } else {
+ let ids = [];
+ if (productSelectedRows.value.length > 0) {
+ ids = productSelectedRows.value.map((item) => item.id);
+ }
ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
})
.then(() => {
- delLedger(ids).then(res => {
+ delProduct(ids).then((res) => {
proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
+ closeProductDia();
+ getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
+ (res) => {
+ productData.value = res.productData;
+ }
+ );
});
})
.catch(() => {
proxy.$modal.msg("宸插彇娑�");
});
- };
+ }
+};
+// 鍏抽棴浜у搧寮规
+const closeProductDia = () => {
+ proxy.resetForm("productFormRef");
+ productFormVisible.value = false;
+};
+// 瀵煎叆
+const handleImport = () => {
+ importUpload.title = "瀵煎叆閿�鍞彴璐�";
+ importUpload.open = true;
+ if (importUploadRef.value) {
+ importUploadRef.value.clearFiles();
+ }
+};
- // 鎵撳嵃鍔熻兘
- const handlePrint = async () => {
- if (selectedRows.value.length === 0) {
- proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
- return;
- }
+// 涓嬭浇瀵煎叆妯℃澘
+const downloadTemplate = () => {
+ proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
+};
- // 鏄剧ず鍔犺浇鐘舵��
- proxy.$modal.loading("姝e湪鑾峰彇浜у搧鏁版嵁锛岃绋嶅��...");
+// 鎻愪氦瀵煎叆鏂囦欢
+const submitImportFile = () => {
+ importUpload.isUploading = true;
+ proxy.$refs["importUploadRef"].submit();
+};
- try {
- // 涓烘瘡涓�変腑鐨勯攢鍞彴璐﹁褰曟煡璇㈠搴旂殑浜у搧鏁版嵁
- const printDataWithProducts = [];
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+/** 鍒ゆ柇鍗曚釜浜у搧鏄惁宸插彂璐э紙鏍规嵁shippingStatus鍒ゆ柇锛屽凡鍙戣揣鎴栧鏍搁�氳繃涓嶅彲缂栬緫鍜屽垹闄わ級 */
+const isProductShipped = (product) => {
+ if (!product) return false;
+ const status = String(product.shippingStatus || "").trim();
+ // 濡傛灉鍙戣揣鐘舵�佹槸"宸插彂璐�"鎴�"瀹℃牳閫氳繃"锛屽垯涓嶅彲缂栬緫鍜屽垹闄�
+ return status === "宸插彂璐�" || status === "瀹℃牳閫氳繃";
+};
- for (const row of selectedRows.value) {
- try {
- // 璋冪敤productList鎺ュ彛鏌ヨ浜у搧鏁版嵁
- const productRes = await productList({
- salesLedgerId: row.id,
- type: 1,
- });
+/** 鍒ゆ柇閿�鍞鍗曚笅鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝侊紙涓嶅彲鍒犻櫎锛� */
+const hasShippedProducts = (products) => {
+ if (!products || !products.length) return false;
+ return products.some((p) => {
+ const status = String(p.shippingStatus || "").trim();
+ // 鏈夊彂璐ф棩鏈熸垨杞︾墝鍙疯涓哄凡鍙戣揣
+ if (p.shippingDate || p.shippingCarNumber) return true;
+ // 宸茶繘琛屽彂璐с�佸彂璐у畬鎴愩�佸凡鍙戣揣 鍧囦笉鍙垹闄�
+ return (
+ status === "宸茶繘琛屽彂璐�" || status === "鍙戣揣瀹屾垚" || status === "宸插彂璐�"
+ );
+ });
+};
- // 灏嗕骇鍝佹暟鎹暣鍚堝埌閿�鍞彴璐﹁褰曚腑
- const rowWithProducts = {
- ...row,
- products: productRes.data || [],
- };
+// 鍒犻櫎
+const handleDelete = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ const unauthorizedRows = selectedRows.value.filter(
+ (row) => !canDeleteLedger(row)
+ );
+ if (unauthorizedRows.length > 0) {
+ proxy.$modal.msgWarning("褰撳墠鐧诲綍鐢ㄦ埛涓嶆槸褰曞叆浜猴紝涓嶈兘鍒犻櫎璇ユ暟鎹�");
+ return;
+ }
+ const ids = selectedRows.value.map((item) => item.id);
- printDataWithProducts.push(rowWithProducts);
- } catch (error) {
- console.error(`鑾峰彇閿�鍞彴璐� ${row.id} 鐨勪骇鍝佹暟鎹け璐�:`, error);
- // 鍗充娇鏌愪釜璁板綍鐨勪骇鍝佹暟鎹幏鍙栧け璐ワ紝涔熻鍖呭惈璇ヨ褰�
- printDataWithProducts.push({
- ...row,
- products: [],
- });
- }
+ // 妫�鏌ユ槸鍚︽湁宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曪紝鑻ユ湁鍒欎笉鍏佽鍒犻櫎
+ const cannotDeleteNames = [];
+ for (const row of selectedRows.value) {
+ let products =
+ row.children && row.children.length > 0 ? row.children : null;
+ if (!products) {
+ try {
+ const res = await productList({ salesLedgerId: row.id, type: 1 });
+ products = res.data || [];
+ } catch {
+ products = [];
}
-
- printData.value = printDataWithProducts;
- console.log("鎵撳嵃鏁版嵁锛堝寘鍚骇鍝侊級:", printData.value);
- printPreviewVisible.value = true;
- } catch (error) {
- console.error("鑾峰彇浜у搧鏁版嵁澶辫触:", error);
- proxy.$modal.msgError("鑾峰彇浜у搧鏁版嵁澶辫触锛岃閲嶈瘯");
- } finally {
- proxy.$modal.closeLoading();
}
- };
- // 鎵ц鎵撳嵃
- const executePrint = () => {
- console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
- console.log("鎵撳嵃鏁版嵁:", printData.value);
+ if (hasShippedProducts(products)) {
+ cannotDeleteNames.push(row.salesContractNo || `ID:${row.id}`);
+ }
+ }
+ if (cannotDeleteNames.length > 0) {
+ proxy.$modal.msgWarning(
+ "宸茶繘琛屽彂璐ф垨鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄わ細" + cannotDeleteNames.join("銆�")
+ );
+ return;
+ }
- // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
- const printWindow = window.open("", "_blank", "width=800,height=600");
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ delLedger(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
- // 鏋勫缓鎵撳嵃鍐呭
- let printContent = `
+// 鎵撳嵃鍔熻兘
+ const handlePrint = async () => {
+ if (selectedRows.value.length === 0) {
+ proxy.$modal.msgWarning("璇烽�夋嫨瑕佹墦鍗扮殑鏁版嵁");
+ return;
+ }
+
+ // 鏄剧ず鍔犺浇鐘舵��
+ proxy.$modal.loading("姝e湪鑾峰彇浜у搧鏁版嵁锛岃绋嶅��...");
+
+ try {
+ // 涓烘瘡涓�変腑鐨勯攢鍞彴璐﹁褰曟煡璇㈠搴旂殑浜у搧鏁版嵁
+ const printDataWithProducts = [];
+
+ for (const row of selectedRows.value) {
+ try {
+ // 璋冪敤productList鎺ュ彛鏌ヨ浜у搧鏁版嵁
+ const productRes = await productList({
+ salesLedgerId: row.id,
+ type: 1,
+ });
+
+ // 灏嗕骇鍝佹暟鎹暣鍚堝埌閿�鍞彴璐﹁褰曚腑
+ const rowWithProducts = {
+ ...row,
+ products: productRes.data || [],
+ };
+
+ printDataWithProducts.push(rowWithProducts);
+ } catch (error) {
+ console.error(`鑾峰彇閿�鍞彴璐� ${row.id} 鐨勪骇鍝佹暟鎹け璐�:`, error);
+ // 鍗充娇鏌愪釜璁板綍鐨勪骇鍝佹暟鎹幏鍙栧け璐ワ紝涔熻鍖呭惈璇ヨ褰�
+ printDataWithProducts.push({
+ ...row,
+ products: [],
+ });
+ }
+ }
+
+ printData.value = printDataWithProducts;
+ console.log("鎵撳嵃鏁版嵁锛堝寘鍚骇鍝侊級:", printData.value);
+ printPreviewVisible.value = true;
+ } catch (error) {
+ console.error("鑾峰彇浜у搧鏁版嵁澶辫触:", error);
+ proxy.$modal.msgError("鑾峰彇浜у搧鏁版嵁澶辫触锛岃閲嶈瘯");
+ } finally {
+ proxy.$modal.closeLoading();
+ }
+};
+// 鎵ц鎵撳嵃
+const executePrint = () => {
+ console.log("寮�濮嬫墽琛屾墦鍗帮紝鏁版嵁鏉℃暟:", printData.value.length);
+ console.log("鎵撳嵃鏁版嵁:", printData.value);
+
+ // 鍒涘缓涓�涓柊鐨勬墦鍗扮獥鍙�
+ const printWindow = window.open("", "_blank", "width=800,height=600");
+
+ // 鏋勫缓鎵撳嵃鍐呭
+ let printContent = `
<!DOCTYPE html>
<html>
<head>
@@ -2214,15 +2347,15 @@
<body>
`;
- // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
- printData.value.forEach((item, index) => {
- printContent += `
+ // 涓烘瘡鏉℃暟鎹敓鎴愭墦鍗伴〉闈�
+ printData.value.forEach((item, index) => {
+ printContent += `
<div class="print-page">
<div class="delivery-note">
<div class="header">
<div class="document-title">闆跺敭鍙戣揣鍗�</div>
</div>
-
+
<div class="info-section">
<div class="info-row">
<div>
@@ -2268,7 +2401,9 @@
0
? item.products
.map(
- product => `
+ (
+ product
+ ) => `
<tr>
<td>${
product.productCategory ||
@@ -2354,694 +2489,690 @@
</div>
</div>
`;
- });
+ });
- printContent += `
+ printContent += `
</body>
</html>
`;
- // 鍐欏叆鍐呭鍒版柊绐楀彛
- printWindow.document.write(printContent);
- printWindow.document.close();
+ // 鍐欏叆鍐呭鍒版柊绐楀彛
+ printWindow.document.write(printContent);
+ printWindow.document.close();
- // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
- printWindow.onload = () => {
- setTimeout(() => {
- printWindow.print();
- printWindow.close();
- printPreviewVisible.value = false;
- }, 500);
- };
+ // 绛夊緟鍐呭鍔犺浇瀹屾垚鍚庢墦鍗�
+ printWindow.onload = () => {
+ setTimeout(() => {
+ printWindow.print();
+ printWindow.close();
+ printPreviewVisible.value = false;
+ }, 500);
};
- // 鏍煎紡鍖栨棩鏈�
- const formatDate = dateString => {
- if (!dateString) return getCurrentDate();
- const date = new Date(dateString);
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- return `${year}/${month}/${day}`;
- };
- // 鏍煎紡鍖栨棩鏈熸椂闂�
- const formatDateTime = date => {
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, "0");
- const day = String(date.getDate()).padStart(2, "0");
- const hours = String(date.getHours()).padStart(2, "0");
- const minutes = String(date.getMinutes()).padStart(2, "0");
- const seconds = String(date.getSeconds()).padStart(2, "0");
- return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
- };
- // 璁$畻浜у搧鎬绘暟閲�
- const getTotalQuantity = products => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.quantity) || 0);
- }, 0);
- return total.toFixed(2);
- };
+};
+// 鏍煎紡鍖栨棩鏈�
+const formatDate = (dateString) => {
+ if (!dateString) return getCurrentDate();
+ return dayjs(dateString).format("YYYY/MM/DD HH:mm:ss");
+};
+// 鏍煎紡鍖栨棩鏈熸椂闂�
+const formatDateTime = (date) => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, "0");
+ const day = String(date.getDate()).padStart(2, "0");
+ const hours = String(date.getHours()).padStart(2, "0");
+ const minutes = String(date.getMinutes()).padStart(2, "0");
+ const seconds = String(date.getSeconds()).padStart(2, "0");
+ return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
+};
+// 璁$畻浜у搧鎬绘暟閲�
+const getTotalQuantity = (products) => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.quantity) || 0);
+ }, 0);
+ return total.toFixed(2);
+};
- // 璁$畻浜у搧鎬婚噾棰�
- const getTotalAmount = products => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
- }, 0);
- return total.toFixed(2);
- };
+// 璁$畻浜у搧鎬婚噾棰�
+const getTotalAmount = (products) => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+ }, 0);
+ return total.toFixed(2);
+};
- // 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
- const getTotalQuantityForPrint = products => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.quantity) || 0);
- }, 0);
- return total.toFixed(2);
- };
+// 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
+const getTotalQuantityForPrint = (products) => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.quantity) || 0);
+ }, 0);
+ return total.toFixed(2);
+};
- const getTotalAmountForPrint = products => {
- if (!products || products.length === 0) return "0";
- const total = products.reduce((sum, product) => {
- return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
- }, 0);
- return total.toFixed(2);
- };
+const getTotalAmountForPrint = (products) => {
+ if (!products || products.length === 0) return "0";
+ const total = products.reduce((sum, product) => {
+ return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+ }, 0);
+ return total.toFixed(2);
+};
- const mathNum = () => {
- console.log("productForm.value", productForm.value);
- if (!productForm.value.taxInclusiveUnitPrice) {
- return;
- }
- if (!productForm.value.quantity) {
- return;
- }
- // 鍚◣鎬讳环璁$畻
- productForm.value.taxInclusiveTotalPrice =
- proxy.calculateTaxIncludeTotalPrice(
- productForm.value.taxInclusiveUnitPrice,
- productForm.value.quantity
- );
- if (productForm.value.taxRate) {
- // 涓嶅惈绋庢�讳环璁$畻
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
- };
-
- // 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
- const calculateFromTotalPrice = () => {
- if (isCalculating.value) return;
-
- const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
- const quantity = parseFloat(productForm.value.quantity);
-
- if (!totalPrice || !quantity || quantity <= 0) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- totalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
- };
-
- // 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
- const calculateFromExclusiveTotalPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const exclusiveTotalPrice = parseFloat(
- productForm.value.taxExclusiveTotalPrice
+const mathNum = () => {
+ console.log("productForm.value", productForm.value);
+ if (!productForm.value.taxInclusiveUnitPrice) {
+ return;
+ }
+ if (!productForm.value.quantity) {
+ return;
+ }
+ // 鍚◣鎬讳环璁$畻
+ productForm.value.taxInclusiveTotalPrice =
+ proxy.calculateTaxIncludeTotalPrice(
+ productForm.value.taxInclusiveUnitPrice,
+ productForm.value.quantity
);
- const quantity = parseFloat(productForm.value.quantity);
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
- const taxRateDecimal = taxRate / 100;
- const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
- productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
-
- // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
- productForm.value.taxInclusiveUnitPrice = (
- inclusiveTotalPrice / quantity
- ).toFixed(2);
-
- isCalculating.value = false;
- };
-
- // 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
- const calculateFromQuantity = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
- };
-
- // 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
- const calculateFromUnitPrice = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const quantity = parseFloat(productForm.value.quantity);
- const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-
- if (!quantity || quantity <= 0 || !unitPrice) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻鍚◣鎬讳环
- productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-
- // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
- if (productForm.value.taxRate) {
- productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(
- productForm.value.taxInclusiveTotalPrice,
- productForm.value.taxRate
- );
- }
-
- isCalculating.value = false;
- };
-
- // 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
- const calculateFromTaxRate = () => {
- if (!productForm.value.taxRate) {
- proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
- return;
- }
- if (isCalculating.value) return;
-
- const inclusiveTotalPrice = parseFloat(
- productForm.value.taxInclusiveTotalPrice
- );
- const taxRate = parseFloat(productForm.value.taxRate);
-
- if (!inclusiveTotalPrice || !taxRate) {
- return;
- }
-
- isCalculating.value = true;
-
- // 璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ // 涓嶅惈绋庢�讳环璁$畻
productForm.value.taxExclusiveTotalPrice =
- proxy.calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate);
-
- isCalculating.value = false;
- };
- /**
- * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
- * @param row 琛屾暟鎹�
- */
- const getShippingStatusText = row => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
- // if (row.shippingDate || row.shippingCarNumber) {
- // return "宸插彂璐�";
- // }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
- if (status === null || status === undefined || status === "") {
- return "寰呭彂璐�";
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const statusTextMap = {
- 寰呭彂璐�: "寰呭彂璐�",
- 寰呭鏍�: "寰呭鏍�",
- 瀹℃牳涓�: "瀹℃牳涓�",
- 瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
- 瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
- 宸插彂璐�: "宸插彂璐�",
- 閮ㄥ垎鍙戣揣: "閮ㄥ垎鍙戣揣",
- };
- return statusTextMap[statusStr] || "寰呭彂璐�";
- };
-
- /**
- * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
- * @param row 琛屾暟鎹�
- */
- const getShippingStatusType = row => {
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
- if (row.shippingStatus === "宸插彂璐�") {
- return "success";
- }
-
- // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
- const status = row.shippingStatus;
-
- // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
- if (status === null || status === undefined || status === "") {
- return "info";
- }
-
- // 鐘舵�佹槸瀛楃涓�
- const statusStr = String(status).trim();
- const typeTextMap = {
- 寰呭彂璐�: "info",
- 寰呭鏍�: "info",
- 瀹℃牳涓�: "warning",
- 瀹℃牳鎷掔粷: "danger",
- 瀹℃牳閫氳繃: "success",
- 宸插彂璐�: "success",
- 閮ㄥ垎鍙戣揣: "warning",
- };
- return typeTextMap[statusStr] || "info";
- };
-
- /**
- * 鍒ゆ柇鏄惁鍙互鍙戣揣
- * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
- * @param row 琛屾暟鎹�
- */
- const canShip = row => {
- // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
- if (row.approveStatus !== 1) {
- return false;
- }
-
- // 鑾峰彇鍙戣揣鐘舵��
- const shippingStatus = row.shippingStatus;
-
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
- if (shippingStatus === "宸插彂璐�") {
- return false;
- }
-
- // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
- const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
- return (
- statusStr === "寰呭彂璐�" ||
- statusStr === "瀹℃牳鎷掔粷" ||
- statusStr === "閮ㄥ垎鍙戣揣"
- );
- };
-
- // 鎵撳紑闄勪欢寮圭獥
- const recordId = ref(0);
- const fileDialogVisible = ref(false);
-
- // 鎵撳紑闄勪欢寮规
- const openFileDialog = async row => {
- recordId.value = row.id;
- fileDialogVisible.value = true;
- };
-
- // 鎵撳紑鍙戣揣寮规
- const openDeliveryForm = async row => {
- // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
- if (!canShip(row)) {
- proxy.$modal.msgWarning(
- "鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
);
- return;
- }
+ }
+};
- currentDeliveryRow.value = row;
- const batchNoList = await getDeliveryBatchNoList(
- row.productModelId || row.modelId
+// 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+const calculateFromTotalPrice = () => {
+ if (isCalculating.value) return;
+
+ const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
+ const quantity = parseFloat(productForm.value.quantity);
+
+ if (!totalPrice || !quantity || quantity <= 0) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ totalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+};
+
+// 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
+const calculateFromExclusiveTotalPrice = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const exclusiveTotalPrice = parseFloat(
+ productForm.value.taxExclusiveTotalPrice
+ );
+ const quantity = parseFloat(productForm.value.quantity);
+ const taxRate = parseFloat(productForm.value.taxRate);
+
+ if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
+ const taxRateDecimal = taxRate / 100;
+ const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
+ productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
+
+ // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+ productForm.value.taxInclusiveUnitPrice = (
+ inclusiveTotalPrice / quantity
+ ).toFixed(2);
+
+ isCalculating.value = false;
+};
+
+// 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
+const calculateFromQuantity = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+};
+
+// 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
+const calculateFromUnitPrice = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const quantity = parseFloat(productForm.value.quantity);
+ const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+
+ if (!quantity || quantity <= 0 || !unitPrice) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻鍚◣鎬讳环
+ productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+
+ // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+ if (productForm.value.taxRate) {
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(
+ productForm.value.taxInclusiveTotalPrice,
+ productForm.value.taxRate
+ );
+ }
+
+ isCalculating.value = false;
+};
+
+// 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
+const calculateFromTaxRate = () => {
+ if (!productForm.value.taxRate) {
+ proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
+ return;
+ }
+ if (isCalculating.value) return;
+
+ const inclusiveTotalPrice = parseFloat(
+ productForm.value.taxInclusiveTotalPrice
+ );
+ const taxRate = parseFloat(productForm.value.taxRate);
+
+ if (!inclusiveTotalPrice || !taxRate) {
+ return;
+ }
+
+ isCalculating.value = true;
+
+ // 璁$畻涓嶅惈绋庢�讳环
+ productForm.value.taxExclusiveTotalPrice =
+ proxy.calculateTaxExclusiveTotalPrice(inclusiveTotalPrice, taxRate);
+
+ isCalculating.value = false;
+};
+/**
+ * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
+ * @param row 琛屾暟鎹�
+ */
+const getShippingStatusText = (row) => {
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
+ // if (row.shippingDate || row.shippingCarNumber) {
+ // return "宸插彂璐�";
+ // }
+
+ // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+ const status = row.shippingStatus;
+
+ // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
+ if (status === null || status === undefined || status === "") {
+ return "寰呭彂璐�";
+ }
+
+ // 鐘舵�佹槸瀛楃涓�
+ const statusStr = String(status).trim();
+ const statusTextMap = {
+ 寰呭彂璐�: "寰呭彂璐�",
+ 寰呭鏍�: "寰呭鏍�",
+ 瀹℃牳涓�: "瀹℃牳涓�",
+ 瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
+ 瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
+ 宸插彂璐�: "宸插彂璐�",
+ 閮ㄥ垎鍙戣揣: "閮ㄥ垎鍙戣揣",
+ };
+ return statusTextMap[statusStr] || "寰呭彂璐�";
+};
+
+/**
+ * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
+ * @param row 琛屾暟鎹�
+ */
+const getShippingStatusType = (row) => {
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
+ if (row.shippingStatus === "宸插彂璐�") {
+ return "success";
+ }
+
+ // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+ const status = row.shippingStatus;
+
+ // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
+ if (status === null || status === undefined || status === "") {
+ return "info";
+ }
+
+ // 鐘舵�佹槸瀛楃涓�
+ const statusStr = String(status).trim();
+ const typeTextMap = {
+ 寰呭彂璐�: "info",
+ 寰呭鏍�: "info",
+ 瀹℃牳涓�: "warning",
+ 瀹℃牳鎷掔粷: "danger",
+ 瀹℃牳閫氳繃: "success",
+ 宸插彂璐�: "success",
+ 閮ㄥ垎鍙戣揣: "warning",
+ };
+ return typeTextMap[statusStr] || "info";
+};
+
+/**
+ * 鍒ゆ柇鏄惁鍙互鍙戣揣
+ * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
+ * @param row 琛屾暟鎹�
+ */
+const canShip = (row) => {
+ // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
+ if (row.approveStatus !== 1) {
+ return false;
+ }
+
+ // 鑾峰彇鍙戣揣鐘舵��
+ const shippingStatus = row.shippingStatus;
+
+ // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
+ if (shippingStatus === "宸插彂璐�") {
+ return false;
+ }
+
+ // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
+ const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
+ return (
+ statusStr === "寰呭彂璐�" ||
+ statusStr === "瀹℃牳鎷掔粷" ||
+ statusStr === "閮ㄥ垎鍙戣揣"
+ );
+};
+
+// 鎵撳紑闄勪欢寮圭獥
+const recordId = ref(0);
+const fileDialogVisible = ref(false);
+
+// 鎵撳紑闄勪欢寮规
+const openFileDialog = async (row) => {
+ recordId.value = row.id;
+ fileDialogVisible.value = true;
+};
+
+// 鎵撳紑鍙戣揣寮规
+const openDeliveryForm = async (row) => {
+ // 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
+ if (!canShip(row)) {
+ proxy.$modal.msgWarning(
+ "鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣"
);
- deliveryForm.value = {
- shippingCarNumber: "",
- expressCompany: "",
- expressNumber: "",
- type: "璐ц溅",
- batchNo: [],
- batchNoList,
- };
- deliveryFileList.value = [];
- deliveryFormVisible.value = true;
- };
+ return;
+ }
- // 鎻愪氦鍙戣揣琛ㄥ崟
- const submitDelivery = () => {
- proxy.$refs["deliveryFormRef"].validate(valid => {
- if (valid) {
- const selectedBatchRows = getSelectedDeliveryBatchRows();
- if (selectedBatchRows.length === 0) {
- proxy.$modal.msgWarning("璇疯嚦灏戝~鍐欎竴涓壒鍙风殑鍙戣揣鏁伴噺");
- return;
- }
- const totalDeliveryQuantity = selectedBatchRows.reduce(
- (sum, item) => sum + Number(item.deliveryQuantity || 0),
- 0
- );
- const currentRowNoQuantity = Number(
- currentDeliveryRow.value?.noQuantity || 0
- );
- if (
- currentRowNoQuantity > 0 &&
- totalDeliveryQuantity > currentRowNoQuantity
- ) {
- proxy.$modal.msgWarning("鎵瑰彿鍙戣揣鎬绘暟涓嶈兘瓒呰繃寰呭彂璐ф暟閲�");
- return;
- }
- // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
- const currentExpandedKeys = [...expandedRowKeys.value];
- const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
- deliveryForm.value.batchNo = selectedBatchRows.map(item => item.id);
- const productModelId =
- currentDeliveryRow.value.productModelId ||
- currentDeliveryRow.value.modelId;
- addShippingInfo({
- salesLedgerId: salesLedgerId,
- salesLedgerProductId: currentDeliveryRow.value.id,
- type: deliveryForm.value.type,
- shippingCarNumber:
- deliveryForm.value.type === "璐ц溅"
- ? deliveryForm.value.shippingCarNumber
- : "",
- expressCompany:
- deliveryForm.value.type === "蹇��"
- ? deliveryForm.value.expressCompany
- : "",
- expressNumber:
- deliveryForm.value.type === "蹇��"
- ? deliveryForm.value.expressNumber
- : "",
- storageBlobDTOs: deliveryFileList.value || [],
- batchNo: deliveryForm.value.batchNo,
- batchNoDetailList: selectedBatchRows.map(item => ({
- stockInventoryId: item.id,
- batchNo: item.batchNo,
- quantity: Number(item.deliveryQuantity || 0),
- productModelId: productModelId,
- })),
- }).then(() => {
- proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
- closeDeliveryDia();
- // 鍒锋柊涓昏〃鏁版嵁
- getList().then(() => {
- // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
- if (currentExpandedKeys.length > 0) {
- // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
- const loadPromises = currentExpandedKeys.map(ledgerId => {
- return productList({ salesLedgerId: ledgerId, type: 1 }).then(
- res => {
- const index = tableData.value.findIndex(
- item => item.id === ledgerId
- );
- if (index > -1) {
- tableData.value[index].children = res.data;
- }
- }
- );
- });
- Promise.all(loadPromises).then(() => {
- // 鎭㈠灞曞紑鐘舵��
- expandedRowKeys.value = currentExpandedKeys;
- });
- }
- });
- });
+ currentDeliveryRow.value = row;
+ const batchNoList = await getDeliveryBatchNoList(
+ row.productModelId || row.modelId
+ );
+ deliveryForm.value = {
+ shippingCarNumber: "",
+ expressCompany: "",
+ expressNumber: "",
+ type: "璐ц溅",
+ batchNo: [],
+ batchNoList,
+ };
+ deliveryFileList.value = [];
+ deliveryFormVisible.value = true;
+};
+
+// 鎻愪氦鍙戣揣琛ㄥ崟
+const submitDelivery = () => {
+ proxy.$refs["deliveryFormRef"].validate((valid) => {
+ if (valid) {
+ const selectedBatchRows = getSelectedDeliveryBatchRows();
+ if (selectedBatchRows.length === 0) {
+ proxy.$modal.msgWarning("璇疯嚦灏戝~鍐欎竴涓壒鍙风殑鍙戣揣鏁伴噺");
+ return;
}
- });
- };
-
- // 鍏抽棴鍙戣揣寮规
- const handleDeliveryTypeChange = val => {
- if (val === "璐ц溅") {
- deliveryForm.value.expressCompany = "";
- deliveryForm.value.expressNumber = "";
- } else {
- deliveryForm.value.shippingCarNumber = "";
+ const totalDeliveryQuantity = selectedBatchRows.reduce(
+ (sum, item) => sum + Number(item.deliveryQuantity || 0),
+ 0
+ );
+ const currentRowNoQuantity = Number(
+ currentDeliveryRow.value?.noQuantity || 0
+ );
+ if (
+ currentRowNoQuantity > 0 &&
+ totalDeliveryQuantity > currentRowNoQuantity
+ ) {
+ proxy.$modal.msgWarning("鎵瑰彿鍙戣揣鎬绘暟涓嶈兘瓒呰繃寰呭彂璐ф暟閲�");
+ return;
+ }
+ // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
+ const currentExpandedKeys = [...expandedRowKeys.value];
+ const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
+ deliveryForm.value.batchNo = selectedBatchRows.map((item) => item.id);
+ const productModelId =
+ currentDeliveryRow.value.productModelId ||
+ currentDeliveryRow.value.modelId;
+ addShippingInfo({
+ salesLedgerId: salesLedgerId,
+ salesLedgerProductId: currentDeliveryRow.value.id,
+ type: deliveryForm.value.type,
+ shippingCarNumber:
+ deliveryForm.value.type === "璐ц溅"
+ ? deliveryForm.value.shippingCarNumber
+ : "",
+ expressCompany:
+ deliveryForm.value.type === "蹇��"
+ ? deliveryForm.value.expressCompany
+ : "",
+ expressNumber:
+ deliveryForm.value.type === "蹇��"
+ ? deliveryForm.value.expressNumber
+ : "",
+ storageBlobDTOs: deliveryFileList.value || [],
+ batchNo: deliveryForm.value.batchNo,
+ batchNoDetailList: selectedBatchRows.map((item) => ({
+ stockInventoryId: item.id,
+ batchNo: item.batchNo,
+ quantity: Number(item.deliveryQuantity || 0),
+ productModelId: productModelId,
+ })),
+ }).then(() => {
+ proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
+ closeDeliveryDia();
+ // 鍒锋柊涓昏〃鏁版嵁
+ getList().then(() => {
+ // 濡傛灉涔嬪墠鏈夊睍寮�鐨勮锛岄噸鏂板姞杞借繖浜涜鐨勫瓙琛ㄦ牸鏁版嵁
+ if (currentExpandedKeys.length > 0) {
+ // 浣跨敤 Promise.all 骞惰鍔犺浇鎵�鏈夊睍寮�琛岀殑瀛愯〃鏍兼暟鎹�
+ const loadPromises = currentExpandedKeys.map((ledgerId) => {
+ return productList({ salesLedgerId: ledgerId, type: 1 }).then(
+ (res) => {
+ const index = tableData.value.findIndex(
+ (item) => item.id === ledgerId
+ );
+ if (index > -1) {
+ tableData.value[index].children = res.data;
+ }
+ }
+ );
+ });
+ Promise.all(loadPromises).then(() => {
+ // 鎭㈠灞曞紑鐘舵��
+ expandedRowKeys.value = currentExpandedKeys;
+ });
+ }
+ });
+ });
}
- };
-
- const closeDeliveryDia = () => {
- proxy.resetForm("deliveryFormRef");
- deliveryFileList.value = [];
- deliveryFormVisible.value = false;
- currentDeliveryRow.value = null;
- };
- const currentFactoryName = ref("");
- const getCurrentFactoryName = async () => {
- let res = await userStore.getInfo();
- currentFactoryName.value = res.user.currentFactoryName;
- };
- onMounted(() => {
- searchForm.salesContractNo = route.query.salesContractNo;
- getList();
- userListNoPage().then(res => {
- userList.value = res.data;
- });
- getCurrentFactoryName();
});
+};
+
+// 鍏抽棴鍙戣揣寮规
+const handleDeliveryTypeChange = (val) => {
+ if (val === "璐ц溅") {
+ deliveryForm.value.expressCompany = "";
+ deliveryForm.value.expressNumber = "";
+ } else {
+ deliveryForm.value.shippingCarNumber = "";
+ }
+};
+
+const closeDeliveryDia = () => {
+ proxy.resetForm("deliveryFormRef");
+ deliveryFileList.value = [];
+ deliveryFormVisible.value = false;
+ currentDeliveryRow.value = null;
+};
+const currentFactoryName = ref("");
+const getCurrentFactoryName = async () => {
+ let res = await userStore.getInfo();
+ currentFactoryName.value = res.user.currentFactoryName;
+};
+onMounted(() => {
+ searchForm.salesContractNo = route.query.salesContractNo;
+ getList();
+ userListNoPage().then((res) => {
+ userList.value = res.data;
+ });
+ getCurrentFactoryName();
+});
</script>
<style scoped lang="scss">
- .ml-10 {
- margin-left: 10px;
+.ml-10 {
+ margin-left: 10px;
+}
+
+:deep(.yellow) {
+ background-color: #faf0de;
+}
+
+:deep(.pink) {
+ background-color: #fae1de;
+}
+
+:deep(.red) {
+ background-color: #fae1de;
+}
+
+:deep(.purple) {
+ background-color: #f4defa;
+}
+
+.table_list {
+ margin-top: unset;
+}
+
+.actions {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 10px;
+}
+
+.print-preview-dialog {
+ .el-dialog__body {
+ padding: 0;
+ max-height: 80vh;
+ overflow-y: auto;
}
+}
- :deep(.yellow) {
- background-color: #faf0de;
- }
-
- :deep(.pink) {
- background-color: #fae1de;
- }
-
- :deep(.red) {
- background-color: #fae1de;
- }
-
- :deep(.purple) {
- background-color: #f4defa;
- }
-
- .table_list {
- margin-top: unset;
- }
-
- .actions {
- display: flex;
- justify-content: space-between;
- margin-bottom: 10px;
- }
-
- .print-preview-dialog {
- .el-dialog__body {
- padding: 0;
- max-height: 80vh;
- overflow-y: auto;
- }
- }
-
- .print-preview-container {
- .print-preview-header {
- padding: 15px;
- border-bottom: 1px solid #e4e7ed;
- text-align: center;
-
- .el-button {
- margin: 0 10px;
- }
- }
-
- .print-preview-content {
- padding: 20px;
- background-color: #f5f5f5;
- min-height: 400px;
- }
- }
-
- .print-page {
- width: 220mm;
- height: 90mm;
- padding: 10mm;
- margin: 0 auto;
- background: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- margin-bottom: 10px;
- box-sizing: border-box;
- }
-
- .delivery-note {
- width: 100%;
- height: 100%;
- font-family: "SimSun", serif;
- font-size: 10px;
- line-height: 1.2;
- display: flex;
- flex-direction: column;
- }
-
- .header {
+.print-preview-container {
+ .print-preview-header {
+ padding: 15px;
+ border-bottom: 1px solid #e4e7ed;
text-align: center;
- margin-bottom: 8px;
- .company-name {
- font-size: 18px;
- font-weight: bold;
- margin-bottom: 4px;
- }
-
- .document-title {
- font-size: 16px;
- font-weight: bold;
+ .el-button {
+ margin: 0 10px;
}
}
- .info-section {
- margin-bottom: 8px;
- display: flex;
- justify-content: space-between;
- align-items: center;
+ .print-preview-content {
+ padding: 20px;
+ background-color: #f5f5f5;
+ min-height: 400px;
+ }
+}
- .info-row {
- line-height: 20px;
+.print-page {
+ width: 220mm;
+ height: 90mm;
+ padding: 10mm;
+ margin: 0 auto;
+ background: white;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ margin-bottom: 10px;
+ box-sizing: border-box;
+}
+
+.delivery-note {
+ width: 100%;
+ height: 100%;
+ font-family: "SimSun", serif;
+ font-size: 10px;
+ line-height: 1.2;
+ display: flex;
+ flex-direction: column;
+}
+
+.header {
+ text-align: center;
+ margin-bottom: 8px;
+
+ .company-name {
+ font-size: 18px;
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+
+ .document-title {
+ font-size: 16px;
+ font-weight: bold;
+ }
+}
+
+.info-section {
+ margin-bottom: 8px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .info-row {
+ line-height: 20px;
+
+ .label {
+ font-weight: bold;
+ width: 60px;
+ font-size: 14px;
+ }
+
+ .value {
+ margin-right: 20px;
+ min-width: 80px;
+ font-size: 14px;
+ }
+ }
+}
+
+.table-section {
+ margin-bottom: 4px;
+ flex: 1;
+
+ .product-table {
+ width: 100%;
+ border-collapse: collapse;
+ border: 1px solid #000;
+
+ th,
+ td {
+ border: 1px solid #000;
+ padding: 6px;
+ text-align: center;
+ font-size: 14px;
+ line-height: 1.4;
+ }
+
+ th {
+ font-weight: bold;
+ }
+
+ .total-label {
+ text-align: right;
+ font-weight: bold;
+ }
+
+ .total-value {
+ font-weight: bold;
+ }
+ }
+}
+
+.footer-section {
+ .footer-row {
+ display: flex;
+ margin-bottom: 3px;
+ line-height: 20px;
+ justify-content: space-between;
+
+ .footer-item {
+ display: flex;
+ margin-right: 20px;
.label {
font-weight: bold;
- width: 60px;
+ width: 80px;
font-size: 14px;
}
.value {
- margin-right: 20px;
min-width: 80px;
font-size: 14px;
}
- }
- }
- .table-section {
- margin-bottom: 4px;
- flex: 1;
-
- .product-table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid #000;
-
- th,
- td {
- border: 1px solid #000;
- padding: 6px;
- text-align: center;
- font-size: 14px;
- line-height: 1.4;
- }
-
- th {
- font-weight: bold;
- }
-
- .total-label {
- text-align: right;
- font-weight: bold;
- }
-
- .total-value {
- font-weight: bold;
- }
- }
- }
-
- .footer-section {
- .footer-row {
- display: flex;
- margin-bottom: 3px;
- line-height: 20px;
- justify-content: space-between;
-
- .footer-item {
- display: flex;
- margin-right: 20px;
-
- .label {
- font-weight: bold;
- width: 80px;
- font-size: 14px;
- }
-
- .value {
- min-width: 80px;
- font-size: 14px;
- }
-
- &.address-item {
- .address-value {
- min-width: 200px;
- }
+ &.address-item {
+ .address-value {
+ min-width: 200px;
}
}
}
}
+}
- @media print {
- .app-container {
- display: none;
- }
-
- .print-page {
- box-shadow: none;
- margin: 0;
- padding: 10mm;
- padding-left: 20mm;
- page-break-inside: avoid;
- page-break-after: always;
- }
- .print-page:last-child {
- page-break-after: avoid;
- }
+@media print {
+ .app-container {
+ display: none;
}
+
+ .print-page {
+ box-shadow: none;
+ margin: 0;
+ padding: 10mm;
+ padding-left: 20mm;
+ page-break-inside: avoid;
+ page-break-after: always;
+ }
+ .print-page:last-child {
+ page-break-after: avoid;
+ }
+}
</style>
\ No newline at end of file
diff --git a/src/views/systemArchitecture/index.vue b/src/views/systemArchitecture/index.vue
index 334194f..8484afe 100644
--- a/src/views/systemArchitecture/index.vue
+++ b/src/views/systemArchitecture/index.vue
@@ -9,9 +9,7 @@
<section class="section-card section-card--top">
<article class="module-title module-title--basic">
<div class="module-title__icon">
- <span class="module-title__icon-shape">
- <svg-icon icon-class="system" />
- </span>
+ <img :src="jichupeizhi" alt="鍩虹閰嶇疆" />
</div>
<div class="module-title__text">
<h2>鍩虹閰嶇疆</h2>
@@ -24,7 +22,7 @@
<div class="flow-item">
<article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon">
- <svg-icon :icon-class="item.icon" />
+ <img :src="item.icon" :alt="item.name" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -37,9 +35,7 @@
<div class="panel-card panel-card--sale">
<article class="module-title module-title--sale">
<div class="module-title__icon">
- <span class="module-title__icon-shape">
- <svg-icon icon-class="chart" />
- </span>
+ <img :src="xiaoshoupeizhi" alt="閿�鍞厤缃�" />
</div>
<div class="module-title__text">
<h2>閿�鍞厤缃�</h2>
@@ -52,7 +48,7 @@
<div class="grid-cell">
<article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon" :class="{ 'flow-node__icon--accent': item.accent }">
- <svg-icon :icon-class="item.icon" />
+ <img :src="item.icon" :alt="item.name" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -70,11 +66,6 @@
</div>
<div class="ai-stage">
- <div class="ai-stage__connector ai-stage__connector--top"></div>
- <div class="ai-stage__connector ai-stage__connector--left"></div>
- <div class="ai-stage__connector ai-stage__connector--right"></div>
- <div class="ai-stage__connector ai-stage__connector--bottom"></div>
-
<div class="ai-stage__ring">
<div class="ai-stage__core">
<img :src="aiHead" alt="AI 鏍稿績寮曟搸" />
@@ -85,9 +76,7 @@
<div class="panel-card panel-card--purchase">
<article class="module-title module-title--purchase">
<div class="module-title__icon">
- <span class="module-title__icon-shape">
- <svg-icon icon-class="shopping" />
- </span>
+ <img :src="caigoupeizhi" alt="閲囪喘閰嶇疆" />
</div>
<div class="module-title__text">
<h2>閲囪喘閰嶇疆</h2>
@@ -100,7 +89,7 @@
<div class="grid-cell">
<article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon" :class="{ 'flow-node__icon--accent': item.accent }">
- <svg-icon :icon-class="item.icon" />
+ <img :src="item.icon" :alt="item.name" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -121,9 +110,7 @@
<section class="section-card section-card--bottom">
<article class="module-title module-title--produce">
<div class="module-title__icon">
- <span class="module-title__icon-shape">
- <svg-icon icon-class="build" />
- </span>
+ <img :src="shengchanpeizhi" alt="鐢熶骇閰嶇疆" />
</div>
<div class="module-title__text">
<h2>鐢熶骇閰嶇疆</h2>
@@ -136,7 +123,7 @@
<div class="flow-item">
<article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon" :class="{ 'flow-node__icon--green': item.green, 'flow-node__icon--accent': item.accent }">
- <svg-icon :icon-class="item.icon" />
+ <img :src="item.icon" :alt="item.name" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -149,9 +136,7 @@
<section class="section-card section-card--bottom">
<article class="module-title module-title--store">
<div class="module-title__icon">
- <span class="module-title__icon-shape">
- <svg-icon icon-class="redis" />
- </span>
+ <img :src="cangchuwuliu" alt="浠撳偍鐗╂祦" />
</div>
<div class="module-title__text">
<h2>浠撳偍鐗╂祦</h2>
@@ -164,7 +149,7 @@
<div class="flow-item">
<article class="flow-node" @click.stop="goPage(item.key)">
<div class="flow-node__icon">
- <svg-icon :icon-class="item.icon" />
+ <img :src="item.icon" :alt="item.name" />
</div>
<span>{{ item.name }}</span>
</article>
@@ -178,8 +163,40 @@
</template>
<script setup>
-import { useRouter } from 'vue-router'
-import aiHead from '@/assets/images/head.svg'
+import aiHead from '@/assets/system/ai.svg'
+import jichupeizhi from '@/assets/system/jichupeizhi.svg'
+import xiaoshoupeizhi from '@/assets/system/xiaoshoupeizhi.svg'
+import caigoupeizhi from '@/assets/system/caigoupeizhi.svg'
+import shengchanpeizhi from '@/assets/system/shengchanpeizhi.svg'
+import cangchuwuliu from '@/assets/system/cangchuwuliu.svg'
+
+import yonghuguanli from '@/assets/system/yonghuguanli.svg'
+import shenpiguanli from '@/assets/system/shenpiguanli.svg'
+import chanpinweihu from '@/assets/system/chanpinweihu.svg'
+
+import kehudangan from '@/assets/system/kehudangan.svg'
+import xiaoshoubaojia from '@/assets/system/xiaoshoubaojia.svg'
+import xiaoshoutaizhang from '@/assets/system/xiaoshoutaizhang.svg'
+import fahuotaizhang from '@/assets/system/fahuotaizhang.svg'
+import xiaoshoutuihuo from '@/assets/system/xiaoshoutuihuo.svg'
+
+import gongyingshangdangan from '@/assets/system/gongyingshangdangan.svg'
+import caigoutaizhang from '@/assets/system/caigoutaizhang.svg'
+import caigoutuihuo from '@/assets/system/caigoutuihuo.svg'
+import gongyingshangwanglai from '@/assets/system/gongyingshangwanglai.svg'
+import caigoubaobiao from '@/assets/system/caigoubaobiao.svg'
+
+import gongxu from '@/assets/system/gongxu.svg'
+import BOM from '@/assets/system/BOM.svg'
+import shengchandingdan from '@/assets/system/shengchandingdan.svg'
+import shengchanpaichan from '@/assets/system/shengchanpaichan.svg'
+import baogong from '@/assets/system/baogong.svg'
+import baogongtaizhang from '@/assets/system/baogongtaizhang.svg'
+import shengchanheduan from '@/assets/system/shengchanheduan.svg'
+
+import rukuguanli from '@/assets/system/rukuguanli.svg'
+import chukuguanli from '@/assets/system/chukuguanli.svg'
+import kucunguanli from '@/assets/system/kucunguanli.svg'
const router = useRouter()
@@ -221,45 +238,41 @@
}
const basicFlow = [
- { key: 'basic-role', name: '瑙掕壊绠$悊', icon: 'user' },
- { key: 'basic-user', name: '鐢ㄦ埛绠$悊', icon: 'peoples' },
- { key: 'basic-post', name: '宀椾綅绠$悊', icon: 'tree' },
- { key: 'basic-dept', name: '閮ㄩ棬绠$悊', icon: 'tree' },
- { key: 'basic-product', name: '浜у搧缁存姢', icon: 'table' },
- { key: 'basic-approval', name: '瀹℃壒绠$悊', icon: 'form' }
+ { key: 'basic-user', name: '鐢ㄦ埛绠$悊', icon: yonghuguanli },
+ { key: 'basic-approval', name: '瀹℃壒绠$悊', icon: shenpiguanli },
+ { key: 'basic-product', name: '浜у搧缁存姢', icon: chanpinweihu }
]
const saleFlow = [
- { key: 'sale-customer', name: '瀹㈡埛妗f', icon: 'peoples', arrow: 'right' },
- { key: 'sale-quote', name: '閿�鍞姤浠�', icon: 'form', arrow: 'right' },
- { key: 'sale-ledger', name: '閿�鍞彴璐�', icon: 'monitor', arrow: 'right' },
- { key: 'sale-delivery', name: '鍙戣揣鍙拌处', icon: 'clipboard', arrow: 'right' },
- { key: 'sale-return', name: '閿�鍞��璐�', icon: 'nested', accent: true }
+ { key: 'sale-customer', name: '瀹㈡埛妗f', icon: kehudangan, arrow: 'right' },
+ { key: 'sale-quote', name: '閿�鍞姤浠�', icon: xiaoshoubaojia, arrow: 'right' },
+ { key: 'sale-ledger', name: '閿�鍞彴璐�', icon: xiaoshoutaizhang, arrow: 'right' },
+ { key: 'sale-delivery', name: '鍙戣揣鍙拌处', icon: fahuotaizhang, arrow: 'right' },
+ { key: 'sale-return', name: '閿�鍞��璐�', icon: xiaoshoutuihuo, accent: true }
]
const purchaseFlow = [
- { key: 'purchase-supplier', name: '渚涘簲鍟嗘。妗�', icon: 'people', arrow: 'right' },
- { key: 'purchase-ledger', name: '閲囪喘鍙拌处', icon: 'monitor', arrow: 'right' },
- { key: 'purchase-return', name: '閲囪喘閫�璐�', icon: 'nested', accent: true },
- { key: 'purchase-contact', name: '渚涘簲鍟嗗線鏉�', icon: 'peoples', arrow: 'right' },
- { key: 'purchase-report', name: '閲囪喘鎶ヨ〃', icon: 'chart' }
+ { key: 'purchase-supplier', name: '渚涘簲鍟嗘。妗�', icon: gongyingshangdangan, arrow: 'right' },
+ { key: 'purchase-ledger', name: '閲囪喘鍙拌处', icon: caigoutaizhang, arrow: 'right' },
+ { key: 'purchase-return', name: '閲囪喘閫�璐�', icon: caigoutuihuo, accent: true },
+ { key: 'purchase-contact', name: '渚涘簲鍟嗗線鏉�', icon: gongyingshangwanglai, arrow: 'right' },
+ { key: 'purchase-report', name: '閲囪喘鎶ヨ〃', icon: caigoubaobiao }
]
const produceFlow = [
- { key: 'produce-process', name: '宸ュ簭', icon: 'list' },
- { key: 'produce-bom', name: 'BOM', icon: 'monitor' },
- { key: 'produce-route', name: '宸ヨ壓璺嚎', icon: 'tree', green: true },
- { key: 'produce-order', name: '鐢熶骇璁㈠崟', icon: 'peoples', green: true },
- { key: 'produce-schedule', name: '鐢熶骇鎺掍骇', icon: 'time' },
- { key: 'produce-work', name: '鐢熶骇鎶ュ伐', icon: 'edit' },
- { key: 'produce-ledger', name: '鎶ュ伐鍙拌处', icon: 'form' },
- { key: 'produce-cost', name: '鐢熶骇鏍哥畻', icon: 'money', accent: true }
+ { key: 'produce-process', name: '宸ュ簭', icon: gongxu },
+ { key: 'produce-bom', name: 'BOM', icon: BOM },
+ { key: 'produce-order', name: '鐢熶骇璁㈠崟', icon: shengchandingdan, green: true },
+ { key: 'produce-schedule', name: '鐢熶骇鎺掍骇', icon: shengchanpaichan },
+ { key: 'produce-work', name: '鐢熶骇鎶ュ伐', icon: baogong },
+ { key: 'produce-ledger', name: '鎶ュ伐鍙拌处', icon: baogongtaizhang },
+ { key: 'produce-cost', name: '鐢熶骇鏍哥畻', icon: shengchanheduan, accent: true }
]
const storeFlow = [
- { key: 'store-in', name: '鍏ュ簱绠$悊', icon: 'download' },
- { key: 'store-out', name: '鍑哄簱绠$悊', icon: 'guide' },
- { key: 'store-stock', name: '搴撳瓨绠$悊', icon: 'redis-list' }
+ { key: 'store-in', name: '鍏ュ簱绠$悊', icon: rukuguanli },
+ { key: 'store-out', name: '鍑哄簱绠$悊', icon: chukuguanli },
+ { key: 'store-stock', name: '搴撳瓨绠$悊', icon: kucunguanli }
]
</script>
@@ -340,24 +353,15 @@
}
.module-title__icon {
- width: 44px;
- height: 50px;
- position: relative;
+ width: 72px;
+ height: 72px;
display: grid;
place-items: center;
- transform: translateY(-1px);
- filter: drop-shadow(0 10px 14px rgba(82, 125, 211, 0.28))
- drop-shadow(0 4px 8px rgba(82, 125, 211, 0.18));
}
-.module-title__icon-shape {
+.module-title__icon img {
width: 100%;
height: 100%;
- clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
- display: grid;
- place-items: center;
- color: #fff;
- font-size: 18px;
}
.module-title__text h2 {
@@ -373,50 +377,7 @@
color: #7f8ba3;
}
-.module-title--basic .module-title__icon {
- filter: drop-shadow(0 10px 14px rgba(47, 110, 236, 0.28))
- drop-shadow(0 4px 8px rgba(47, 110, 236, 0.18));
-}
-.module-title--basic .module-title__icon-shape {
- background: linear-gradient(135deg, #2069ff 0%, #5bb0ff 100%);
-}
-
-.module-title--sale .module-title__icon {
- filter: drop-shadow(0 10px 14px rgba(123, 66, 255, 0.24))
- drop-shadow(0 4px 8px rgba(123, 66, 255, 0.16));
-}
-
-.module-title--sale .module-title__icon-shape {
- background: linear-gradient(135deg, #7b42ff 0%, #a172ff 100%);
-}
-
-.module-title--purchase .module-title__icon {
- filter: drop-shadow(0 10px 14px rgba(52, 161, 255, 0.24))
- drop-shadow(0 4px 8px rgba(52, 161, 255, 0.16));
-}
-
-.module-title--purchase .module-title__icon-shape {
- background: linear-gradient(135deg, #34a1ff 0%, #66c6ff 100%);
-}
-
-.module-title--produce .module-title__icon {
- filter: drop-shadow(0 10px 14px rgba(36, 183, 118, 0.24))
- drop-shadow(0 4px 8px rgba(36, 183, 118, 0.16));
-}
-
-.module-title--produce .module-title__icon-shape {
- background: linear-gradient(135deg, #24b776 0%, #62d49d 100%);
-}
-
-.module-title--store .module-title__icon {
- filter: drop-shadow(0 10px 14px rgba(119, 81, 255, 0.24))
- drop-shadow(0 4px 8px rgba(119, 81, 255, 0.16));
-}
-
-.module-title--store .module-title__icon-shape {
- background: linear-gradient(135deg, #7751ff 0%, #9b76ff 100%);
-}
.flow-row {
display: flex;
@@ -462,6 +423,12 @@
place-items: center;
color: #3f76f3;
font-size: 24px;
+}
+
+.flow-node__icon img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
}
.flow-node__icon--accent {
@@ -614,47 +581,6 @@
font-size: 14px;
font-weight: 700;
box-shadow: 0 10px 20px rgba(118, 147, 204, 0.08);
-}
-
-.ai-stage__connector {
- position: absolute;
- border-color: rgba(145, 181, 247, 0.5);
- border-style: dashed;
- border-width: 1px;
- pointer-events: none;
-}
-
-.ai-stage__connector--top {
- top: 24px;
- left: 50%;
- width: 0;
- height: 64px;
- border-left-width: 1px;
- transform: translateX(-50%);
-}
-
-.ai-stage__connector--left,
-.ai-stage__connector--right {
- top: 148px;
- width: 74px;
- border-top-width: 1px;
-}
-
-.ai-stage__connector--left {
- left: 18px;
-}
-
-.ai-stage__connector--right {
- right: 18px;
-}
-
-.ai-stage__connector--bottom {
- bottom: 32px;
- left: 50%;
- width: 0;
- height: 64px;
- border-left-width: 1px;
- transform: translateX(-50%);
}
@media (max-width: 1440px) {
--
Gitblit v1.9.3