gaoluyang
4 天以前 6e173210a874ff7601aa68eab56e912f5619c79c
Merge remote-tracking branch 'origin/dev_宁夏_英泽防锈' into dev_宁夏_英泽防锈

# Conflicts:
# multiple/config.json
# src/api/basicData/customer.js
# src/api/inventoryManagement/stockInventory.js
# src/api/procurementManagement/purchase_return_order.js
# src/api/salesManagement/deliveryLedger.js
# src/assets/styles/element-ui.scss
# src/assets/styles/index.scss
# src/assets/styles/sidebar.scss
# src/assets/styles/variables.module.scss
# src/components/AIChatSidebar/index.vue
# src/components/Breadcrumb/index.vue
# src/components/Dialog/FileList.vue
# src/components/ProcessParamListDialog.vue
# src/components/PurchaseAIChatSidebar/index.vue
# src/layout/components/AppMain.vue
# src/layout/components/Navbar.vue
# src/layout/components/Sidebar/Logo.vue
# src/layout/components/Sidebar/index.vue
# src/layout/components/TagsView/ScrollPane.vue
# src/layout/components/TagsView/index.vue
# src/layout/index.vue
# src/router/index.js
# src/store/modules/permission.js
# src/store/modules/user.js
# src/views/basicData/customerFile/index.vue
# src/views/basicData/customerFileOpenSea/index.vue
# src/views/basicData/product/index.vue
# src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
# src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
# src/views/collaborativeApproval/approvalProcess/index.vue
# src/views/customerService/expiryAfterSales/index.vue
# src/views/customerService/feedbackRegistration/components/formDia.vue
# src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
# src/views/equipmentManagement/repair/Modal/RepairModal.vue
# src/views/equipmentManagement/repair/index.vue
# src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue
# src/views/equipmentManagement/upkeep/Form/PlanModal.vue
# src/views/equipmentManagement/upkeep/index.vue
# src/views/financialManagement/assets/fixedAssets.vue
# src/views/financialManagement/assets/intangibleAssets.vue
# src/views/financialManagement/generalLedger/index.vue
# src/views/financialManagement/payable/purchaseIn.vue
# src/views/financialManagement/receivable/salesOut.vue
# src/views/financialManagement/receivable/salesReturn.vue
# src/views/financialManagement/voucher/detailLedger.vue
# src/views/financialManagement/voucher/generalLedger.vue
# src/views/financialManagement/voucher/index.vue
# src/views/index.vue
# src/views/inventoryManagement/dispatchLog/Record.vue
# src/views/inventoryManagement/receiptManagement/Record.vue
# src/views/inventoryManagement/stockManagement/Record.vue
# src/views/login.vue
# src/views/oaSystem/projectManagement/components/milestoneList.vue
# src/views/oaSystem/projectManagement/components/taskTree.vue
# src/views/oaSystem/projectManagement/index.vue
# src/views/oaSystem/projectManagement/projectDetail.vue
# src/views/personnelManagement/dimission/components/formDia.vue
# src/views/personnelManagement/employeeRecord/index.vue
# src/views/procurementManagement/procurementLedger/index.vue
# src/views/procurementManagement/purchaseReturnOrder/New.vue
# src/views/procurementManagement/purchaseReturnOrder/index.vue
# src/views/productionManagement/processRoute/index.vue
# src/views/productionManagement/processRoute/processRouteItem/index.vue
# src/views/productionManagement/productStructure/Detail/index.vue
# src/views/productionManagement/productionCosting/index.vue
# src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
# src/views/productionManagement/productionOrder/index.vue
# src/views/productionManagement/productionProcess/index.vue
# src/views/productionManagement/productionTraceability/index.vue
# src/views/productionManagement/workOrderEdit/index.vue
# src/views/productionManagement/workOrderManagement/index.vue
# src/views/productionPlan/productionPlan/index.vue
# src/views/qualityManagement/finalInspection/index.vue
# src/views/safeProduction/safeWorkApproval/components/infoFormDia.vue
# src/views/salesManagement/deliveryLedger/index.vue
# src/views/salesManagement/returnOrder/components/formDia.vue
# src/views/salesManagement/returnOrder/index.vue
# src/views/salesManagement/salesLedger/index.vue
# src/views/systemArchitecture/index.vue
已添加76个文件
已修改156个文件
已删除10个文件
34764 ■■■■■ 文件已修改
FINANCIAL_MANAGEMENT_BACKEND_SPEC.md 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/BTYXfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/DYKJfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/DZZBfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/HYJCfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/HYLQfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/HYZCfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/JHHGfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/JHYfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/JXJHfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/JXSMico.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/KSfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/KYHGfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/PCDZico.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/QXYfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/SDJCfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/WTXCfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/XCDQfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/XLZBico.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/XSWHfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/YSJXico.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/YTJZfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/YZFXfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/ZQSYfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/ZXZNfavicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/favicon/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/BTYXLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/DYKJLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/DZZBLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/HYJCLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/HYLQLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/HYZCLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/JHHGLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/JHYLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/JXJHLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/JXSMLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/KSLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/KYHGLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/Logo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/PCDZLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/QXYLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/SDJCLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/WTXCLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/XCDQLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/XLZBLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/XSWHLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/YSJXLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/YTJZLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/ZQSYLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/logo/ZXZNLogo.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/screen/PCDZView.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/assets/screen/login-background.png 补丁 | 查看 | 原始文档 | blame | 历史
multiple/config.json 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
multiple/multiple-build.js 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicData/customer.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/equipmentManagement/repair.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/financialManagement/accountPurchase.js 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/financialManagement/accountSales.js 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/financialManagement/accountSubject.js 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/financialManagement/fixedAsset.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/financialManagement/intangibleAsset.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/financialManagement/ledger.js 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/financialManagement/voucher.js 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockInventory.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/login.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/oaSystem/projectManagement.js 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/procurementManagement/purchase_return_order.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/salesManagement/deliveryLedger.js 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/viewIndex.js 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/AI/仓储助手.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/AI/待办助手.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/AI/生产助手.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/AI/财务助手.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/AI/质量助手.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/AI/采购助手.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/AI/销售助手.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/aiIndustrialBrain/reference-cards.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/aiIndustrialBrain/reference-chat.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/head.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/logo/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/element-ui.scss 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/index.scss 87 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/sidebar.scss 765 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/styles/variables.module.scss 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AIChatSidebar/assistants/generalAssistant.js 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AIChatSidebar/assistants/index.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AIChatSidebar/assistants/productionAssistant.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AIChatSidebar/assistants/purchaseAssistant.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AIChatSidebar/assistants/salesAssistant.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/AIChatSidebar/index.vue 2740 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Breadcrumb/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Dialog/FileList.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Hamburger/index.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/HeaderSearch/index.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ProcessParamListDialog.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PurchaseAIChatSidebar/index.vue 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/filePreview/index.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/AppMain.vue 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Navbar.vue 488 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/NotificationCenter/index.vue 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Sidebar/Logo.vue 94 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Sidebar/SidebarItem.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Sidebar/index.vue 242 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TagsView/ScrollPane.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/TagsView/index.vue 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/index.vue 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugins/download.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 94 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/settings.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/permission.js 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.js 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/theme.js 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/aiIndustrialBrain/MAINTAIN_RULES.md 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/aiIndustrialBrain/components/AiAssistantWorkspace.vue 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/aiIndustrialBrain/index.vue 1500 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/customerFile/index.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/customerFileOpenSea/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 91 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/supplierManage/components/BlacklistTab.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/supplierManage/components/HomeTab.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/supplierManage/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue 852 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/fileList.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/index.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/sealManagement/index.vue 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/shipmentReview/fileList.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/customerService/expiryAfterSales/components/formDia.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/customerService/expiryAfterSales/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/customerService/feedbackRegistration/components/formDia.vue 895 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/formDia.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue 680 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue 335 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/index.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/ledger/index.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/components/formDia.vue 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/index.vue 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/operationManagement/index.vue 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Modal/AcceptanceModal.vue 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Modal/RepairModal.vue 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/index.vue 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue 357 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/PlanModal.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/formDia.vue 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/index.vue 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/assets/fixedAssets.vue 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/assets/intangibleAssets.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/generalLedger/index.vue 671 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/payable/purchaseIn.vue 326 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/payable/purchaseReturn.vue 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/receivable/salesOut.vue 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/receivable/salesReturn.vue 308 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/voucher/detailLedger.vue 434 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/voucher/generalLedger.vue 382 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/voucher/index.vue 534 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index.vue 3212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/dispatchLog/Record.vue 953 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/Record.vue 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/Record.vue 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockReport/index.vue 1251 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/lavorissue/ledger/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login.vue 1040 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/components/milestoneList.vue 289 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/components/phaseGoalList.vue 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/components/projectForm.vue 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/components/taskTree.vue 834 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/index.vue 481 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/oaSystem/projectManagement/projectDetail.vue 565 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/contractManagement/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/contractManagement/index.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/dimission/components/formDia.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/employeeRecord/index.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/fileList.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/purchaseReturnOrder/New.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/purchaseReturnOrder/ProductList.vue 91 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/purchaseReturnOrder/index.vue 489 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/index.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/processRouteItem/index.vue 284 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productStructure/Detail/index.vue 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionCosting/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionProcess/index.vue 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionReporting/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionTraceability/index.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrder/components/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrderEdit/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrderManagement/components/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrderManagement/index.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/productionPlan/index.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/projectManagement/Management/components/formDia.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/projectManagement/Management/projectDetail.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/projectManagement/projectType/index.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/formDia.vue 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/components/formDia.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/nonconformingManagement/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/formDia.vue 932 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/index.vue 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue 86 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/PSIDataAnalysis/index.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/index.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/center-center.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/center-top.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/left-top.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/components/right-top.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/productionAnalysis/index.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safeProduction/safeWorkApproval/components/infoFormDia.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safeProduction/safeWorkApproval/fileList.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/deliveryLedger/index.vue 654 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/invoiceLedger/index.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/returnOrder/components/detailDia.vue 260 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/returnOrder/components/formDia.vue 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/returnOrder/index.vue 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/fileList.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 3741 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesQuotation/index.vue 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/systemArchitecture/index.vue 961 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FINANCIAL_MANAGEMENT_BACKEND_SPEC.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,233 @@
# è´¢åŠ¡ç®¡ç†åŽç«¯æ–‡æ¡£ï¼ˆä»…è´Ÿè´£æ¨¡å—ï¼‰
更新时间:2026-05-12
适用范围(仅以下 6 ä¸ªæ¨¡å—):
1. å›ºå®šèµ„产(`/financial/fixed-assets`)
2. æ— å½¢èµ„产(`/financial/intangible-assets`)
3. æ€»è´¦ç§‘目(`/financial/general-ledger`)
4. å‡­è¯ï¼ˆ`/financial/voucher`)
5. ç§‘目总账(`/financial/voucher-general-ledger`)
6. ç§‘目明细账(`/financial/voucher-detail-ledger`)
---
## 1. ç»Ÿä¸€çº¦å®š
### 1.1 å“åº”结构
```json
{
  "code": 200,
  "msg": "success",
  "data": {}
}
```
### 1.2 åˆ†é¡µç»“构(如果是分页接口)
请求参数建议:
- `current`(页码)
- `size`(每页条数)
响应建议:
```json
{
  "code": 200,
  "data": {
    "records": [],
    "total": 0
  }
}
```
### 1.3 é‡‘额与精度
- é‡‘额字段建议 `decimal(18,2)`。
- å‰åŽç«¯ç»Ÿä¸€ä¿ç•™ä¸¤ä½å°æ•°ã€‚
---
## 2. æ¨¡å—一:总账科目(已接真实 API)
前端文件:`src/views/financialManagement/generalLedger/index.vue`
API æ–‡ä»¶ï¼š`src/api/financialManagement/accountSubject.js`
### 2.1 æŽ¥å£çŽ°çŠ¶
- `GET /accountSubject/list`
- `POST /accountSubject/add`
- `PUT /accountSubject/edit`
- `DELETE /accountSubject/remove/{ids}`
- `POST /accountSubject/export`
### 2.2 å­—段模型
- `id`
- `subjectCode`(科目编码)
- `subjectName`(科目名称)
- `subjectType`(科目类型)
- `balanceDirection`(余额方向:借方/贷方)
- `status`(0 å¯ç”¨ï¼Œ1 ç¦ç”¨ï¼‰
- `remark`
### 2.3 ä¸šåŠ¡è§„åˆ™
- `subjectCode`、`subjectName`、`subjectType` å¿…填。
- åˆ é™¤éœ€è¦åšå¼•用校验(若已被凭证分录引用,不允许删除)。
---
## 3. æ¨¡å—二:固定资产(当前前端为 mock,待后端实现)
前端文件:`src/views/financialManagement/assets/fixedAssets.vue`
### 3.1 å»ºè®®æŽ¥å£
- `GET /financial/fixedAsset/page`
- `POST /financial/fixedAsset/add`
- `PUT /financial/fixedAsset/update`
- `DELETE /financial/fixedAsset/delete`
- `POST /financial/fixedAsset/depreciate`(按月计提)
### 3.2 å­—段模型
- `id, assetCode, assetName, category, specification`
- `purchaseDate, originalValue, usefulLife, residualRate`
- `accumulatedDepreciation, netValue`
- `location, department, keeper, status, remark`
### 3.3 æ ¸å¿ƒå…¬å¼ï¼ˆå¿…须一致)
- `monthlyDepreciation = originalValue * (1 - residualRate/100) / (usefulLife*12)`
- `accumulatedDepreciation += monthlyDepreciation`
- `netValue = originalValue - accumulatedDepreciation`
### 3.4 çŠ¶æ€å»ºè®®
- `in_use`(在用)
- `idle`(闲置)
- `repair`(维修中)
- `scrapped`(报废)
---
## 4. æ¨¡å—三:无形资产(当前前端为 mock,待后端实现)
前端文件:`src/views/financialManagement/assets/intangibleAssets.vue`
### 4.1 å»ºè®®æŽ¥å£
- `GET /financial/intangibleAsset/page`
- `POST /financial/intangibleAsset/add`
- `PUT /financial/intangibleAsset/update`
- `DELETE /financial/intangibleAsset/delete`
- `POST /financial/intangibleAsset/amortize`(按月摊销)
### 4.2 å­—段模型
- `id, assetCode, assetName, category, certificateNo`
- `acquisitionDate, originalValue, amortizationPeriod, residualRate`
- `accumulatedAmortization, netValue`
- `validityDate, status, description, remark`
### 4.3 æ ¸å¿ƒå…¬å¼ï¼ˆå¿…须一致)
- `monthlyAmortization = originalValue * (1 - residualRate/100) / (amortizationPeriod*12)`
- `accumulatedAmortization += monthlyAmortization`
- `netValue = originalValue - accumulatedAmortization`
- å½“ `netValue <= 0`:
  - `netValue = 0`
  - `status = amortized`
### 4.4 çŠ¶æ€å»ºè®®
- `in_use`(在用)
- `expired`(到期)
- `amortized`(已摊销完)
---
## 5. æ¨¡å—四:凭证(当前前端为 mock,待后端实现)
前端文件:`src/views/financialManagement/voucher/index.vue`
### 5.1 å»ºè®®æŽ¥å£
- `GET /financial/voucher/page`
- `POST /financial/voucher/add`
- `PUT /financial/voucher/update`
- `POST /financial/voucher/post`(过账)
- `POST /financial/voucher/cancel`(作废)
- `GET /financial/voucher/detail/{id}`
### 5.2 ä¸»è¡¨å­—段
- `id, voucherNo, voucherDate, summary`
- `debit, credit, creator, status, attachmentCount, remark`
### 5.3 åˆ†å½•字段
- `subjectCode, subjectName, summary, debit, credit`
### 5.4 å…³é”®æ ¡éªŒ
- åˆ†å½•至少一条有效行(科目不空,且借方或贷方 > 0)。
- å€Ÿè´·å¹³è¡¡ï¼š`sum(debit) == sum(credit)` ä¸” > 0,不满足禁止保存。
### 5.5 çŠ¶æ€æµè½¬
- `unposted -> posted`
- `unposted -> cancelled`
---
## 6. æ¨¡å—五:科目总账(当前前端为 mock,待后端实现)
前端文件:`src/views/financialManagement/voucher/generalLedger.vue`
### 6.1 å»ºè®®æŽ¥å£
- `GET /financial/ledger/general`
### 6.2 è¯·æ±‚参数
- `subjectCode`(末级或指定科目)
- `startMonth`(YYYY-MM)
- `endMonth`(YYYY-MM)
### 6.3 å“åº”字段
- `date, voucherNo, summary`
- `debit, credit, direction, balance`
### 6.4 è§„则
- ä»…在选择科目后返回数据。
- æ”¯æŒâ€œæœŸåˆä½™é¢ / æœ¬æœˆåˆè®¡ / æœ¬å¹´ç´¯è®¡â€è¡Œï¼ˆå¯é€šè¿‡ `rowType` å­—段区分)。
---
## 7. æ¨¡å—六:科目明细账(当前前端为 mock,待后端实现)
前端文件:`src/views/financialManagement/voucher/detailLedger.vue`
### 7.1 å»ºè®®æŽ¥å£
- `GET /financial/ledger/detail`
### 7.2 è¯·æ±‚参数
- `subjectCode`
- `auxiliaryType`(customer/supplier/department/employee/project)
- `auxiliaryId`
- `startMonth`(YYYY-MM)
- `endMonth`(YYYY-MM)
### 7.3 å“åº”字段
- `date, voucherNo, summary`
- `debit, credit, direction, balance`
### 7.4 è§„则
- å…ˆé€‰ç§‘目,再查明细。
- è¾…助核算条件为可选,但建议后端支持维度过滤。
---
## 8. æŽ¨èæœ€å°è¡¨è®¾è®¡ï¼ˆä»…本范围)
- `fin_account_subject`
- `fin_fixed_asset`
- `fin_intangible_asset`
- `fin_voucher`
- `fin_voucher_entry`
- `fin_ledger_snapshot_general`(可选,做性能优化)
- `fin_ledger_snapshot_detail`(可选,做性能优化)
---
## 9. AI ç”ŸæˆåŽç«¯ä»»åŠ¡é¡ºåºï¼ˆå»ºè®®ï¼‰
1. å…ˆå®Œæˆ **总账科目**(已有 API,最稳定)。
2. å®Œæˆ **凭证 + åˆ†å½• + å€Ÿè´·å¹³è¡¡æ ¡éªŒ + çŠ¶æ€æµè½¬**。
3. å®žçް **科目总账 / ç§‘目明细账** æŸ¥è¯¢ã€‚
4. å®žçް **固定资产折旧** ä¸Ž **无形资产摊销**。
5. è¡¥æµ‹è¯•:
   - å€Ÿè´·å¹³è¡¡æ ¡éªŒ
   - æŠ˜æ—§/摊销公式
   - ç§‘目被引用禁止删除
multiple/assets/favicon/BTYXfavicon.ico
multiple/assets/favicon/DYKJfavicon.ico
multiple/assets/favicon/DZZBfavicon.ico
multiple/assets/favicon/HYJCfavicon.ico
multiple/assets/favicon/HYLQfavicon.ico
multiple/assets/favicon/HYZCfavicon.ico
multiple/assets/favicon/JHHGfavicon.ico
multiple/assets/favicon/JHYfavicon.ico
multiple/assets/favicon/JXJHfavicon.ico
multiple/assets/favicon/JXSMico.ico
multiple/assets/favicon/KSfavicon.ico
multiple/assets/favicon/KYHGfavicon.ico
multiple/assets/favicon/PCDZico.ico
Binary files differ
multiple/assets/favicon/QXYfavicon.ico
multiple/assets/favicon/SDJCfavicon.ico
multiple/assets/favicon/WTXCfavicon.ico
multiple/assets/favicon/XCDQfavicon.ico
multiple/assets/favicon/XLZBico.ico
multiple/assets/favicon/XSWHfavicon.ico
multiple/assets/favicon/YSJXico.ico
multiple/assets/favicon/YTJZfavicon.ico
multiple/assets/favicon/YZFXfavicon.ico
multiple/assets/favicon/ZQSYfavicon.ico
multiple/assets/favicon/ZXZNfavicon.ico
multiple/assets/favicon/favicon.ico

multiple/assets/logo/BTYXLogo.png
multiple/assets/logo/DYKJLogo.png
multiple/assets/logo/DZZBLogo.png
multiple/assets/logo/HYJCLogo.png
multiple/assets/logo/HYLQLogo.png
multiple/assets/logo/HYZCLogo.png
multiple/assets/logo/JHHGLogo.png
multiple/assets/logo/JHYLogo.png
multiple/assets/logo/JXJHLogo.png
multiple/assets/logo/JXSMLogo.png
multiple/assets/logo/KSLogo.png
multiple/assets/logo/KYHGLogo.png
multiple/assets/logo/Logo.png
multiple/assets/logo/PCDZLogo.png
Binary files differ
multiple/assets/logo/QXYLogo.png
multiple/assets/logo/SDJCLogo.png
multiple/assets/logo/WTXCLogo.png
multiple/assets/logo/XCDQLogo.png
multiple/assets/logo/XLZBLogo.png
multiple/assets/logo/XSWHLogo.png
multiple/assets/logo/YSJXLogo.png
multiple/assets/logo/YTJZLogo.png
multiple/assets/logo/ZQSYLogo.png
multiple/assets/logo/ZXZNLogo.png
multiple/assets/screen/PCDZView.png
Binary files differ
multiple/assets/screen/login-background.png

multiple/config.json
@@ -3,31 +3,27 @@
    "env": {
      "VITE_APP_TITLE": "芯导云(管理信息系统)"
    },
    "screen": "screen/PCDZView.png",
    "logo": "logo/PCDZLogo.png",
    "favicon": "favicon/PCDZico.ico"
    "logo": "logo/Logo.png",
    "favicon": "favicon/favicon.ico"
  },
  "TEST": {
    "env": {
      "VITE_APP_TITLE": "信息管理",
      "VITE_BASE_API": "http://1.15.17.182:9003",
      "VITE_JAVA_API": "http://1.15.17.182:9002"
      "VITE_APP_TITLE": "工厂数字化MOM系统",
      "VITE_BASE_API": "http://1.15.17.182:9048",
      "VITE_JAVA_API": "http://1.15.17.182:9049"
    },
    "screen": "screen/login-background.png",
    "logo": "logo/PCDZLogo.png",
    "logo": "logo/Logo.png",
    "favicon": "favicon/favicon.ico"
  },
  "YZFX": {
    "env": {
      "VITE_APP_TITLE": "英泽防锈新材料信息管理",
      "VITE_BASE_API": "http://1.15.17.182:9021",
      "VITE_JAVA_API": "http://1.15.17.182:9020"
      "VITE_APP_TITLE": "宁夏英泽防锈新材料有限公司",
      "VITE_BASE_API": "http://42.63.70.231:9000",
      "VITE_JAVA_API": "http://42.63.70.231:9001"
    },
    "screen": "screen/login-background.png",
    "logo": "logo/YZFXLogo.png",
    "favicon": "favicon/YZFXico.ico"
    "favicon": "favicon/YZFXfavicon.ico"
  },
  "screen": "/src/assets/images/login-background.png",
  "logo": "/src/assets/logo/logo.png",
  "favicon": "/public/favicon.ico"
}
multiple/multiple-build.js
@@ -1,86 +1,152 @@
import fs from 'fs/promises';
import fsSync from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import fs from "fs/promises";
import fsSync from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { execSync } from "child_process";
// èŽ·å– __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// è¯»å– JSON é…ç½®
const data = await fs.readFile(path.join(__dirname, 'config.json'), 'utf-8');
const data = await fs.readFile(path.join(__dirname, "config.json"), "utf-8");
const config = JSON.parse(data);
// é¡¹ç›®è·¯å¾„
const rootPath = path.resolve(__dirname, '..');
const resourcePath = path.join(rootPath, 'multiple', 'assets');
const replacePath = path.join(rootPath, 'replace');
const rootPath = path.resolve(__dirname, "..");
const resourcePath = path.join(rootPath, "multiple", "assets");
const replacePath = path.join(rootPath, "replace");
const envFilePath = path.join(rootPath, ".env.production.local");
// èŽ·å–å‘½ä»¤è¡Œå‚æ•°
const params = parseArgs(process.argv);
const company = params["company"] ?? "default";
const company = resolveCompany(params);
const companyMap = config[company];
const envFilePath = path.join(process.cwd(), '.env.production.local');
try {
    // 1️⃣ ç”Ÿæˆ .env
    console.log("=======生成.env=======");
    const envContent = Object.entries(companyMap.env)
        .map(([key, value]) => `${key}='${value}'`)
        .join('\n') + '\n';
    await fs.writeFile(envFilePath, envContent, 'utf-8');
    // 2️⃣ å¤‡ä»½åŽŸå§‹èµ„æºå¹¶æ›¿æ¢
    console.log("=======修改资源=======");
    for (const [key, value] of Object.entries(companyMap)) {
        if (key === 'env') continue;
        const originFile = path.join(rootPath, config[key]);
        const backupFile = path.join(replacePath, config[key]);
        const replaceFile = path.join(resourcePath, companyMap[key]);
        await fs.mkdir(path.dirname(backupFile), { recursive: true });
        await fs.copyFile(originFile, backupFile);
        await fs.copyFile(replaceFile, originFile);
    }
    console.log("=====开始打包======");
    execSync("vite build", { stdio: "inherit" });
    console.log("=====打包完成======");
} finally {
    console.log("=====恢复资源======");
    // åˆ é™¤ä¸´æ—¶ .env æ–‡ä»¶
    if (fsSync.existsSync(envFilePath)) {
        await fs.unlink(envFilePath);
        console.log(`🗑️ å·²åˆ é™¤ ${envFilePath}`);
    }
    // æ¢å¤èµ„源文件
    if (fsSync.existsSync(replacePath)) {
        for (const [key, value] of Object.entries(companyMap)) {
            if (key === 'env') continue;
            const originFile = path.join(rootPath, config[key]);
            const backupFile = path.join(replacePath, config[key]);
            await fs.copyFile(backupFile, originFile);
        }
        await fs.rm(replacePath, { recursive: true, force: true });
        console.log(`🗑️ å·²åˆ é™¤ ${replacePath}`);
    }
if (!companyMap) {
  const availableCompanies = Object.entries(config)
    .filter(([, value]) => value && typeof value === "object" && value.env)
    .map(([key]) => key)
    .sort();
  throw new Error(
    `未知 company: "${company}"。可选值: ${availableCompanies.join(", ")}`
  );
}
// ç®€å•命令行参数解析
function parseArgs(argv) {
    const params = {};
    for (const arg of argv.slice(2)) {
        if (arg.startsWith('--')) {
            const [key, value] = arg.slice(2).split('=');
            params[key] = value ?? true;
        }
console.log(`当前 company: ${company}`);
async function copyFileWithOverwrite(src, dest) {
  await fs.mkdir(path.dirname(dest), { recursive: true });
  if (fsSync.existsSync(dest)) {
    try {
      await fs.chmod(dest, 0o666);
    } catch {
      // Ignore chmod failure and continue.
    }
    return params;
    await fs.rm(dest, { force: true });
  }
  await fs.copyFile(src, dest);
}
try {
  console.log("=======生成.env=======");
  const envContent =
    Object.entries(companyMap.env)
      .map(([key, value]) => `${key}='${value}'`)
      .join("\n") + "\n";
  await fs.writeFile(envFilePath, envContent, "utf-8");
  console.log("=======修改资源=======");
  for (const [key] of Object.entries(companyMap)) {
    if (key === "env") continue;
    const originFile = path.join(rootPath, config[key]);
    const backupFile = path.join(replacePath, config[key]);
    const replaceFile = path.join(resourcePath, companyMap[key]);
    await copyFileWithOverwrite(originFile, backupFile);
    await copyFileWithOverwrite(replaceFile, originFile);
  }
  console.log("=====开始打包=====");
  const buildEnv = createBuildEnv(companyMap.env);
  execSync("vite build", { stdio: "inherit", cwd: rootPath, env: buildEnv });
  console.log("=====打包完成======");
} finally {
  console.log("=====恢复资源======");
  if (fsSync.existsSync(envFilePath)) {
    await fs.unlink(envFilePath);
    console.log(`🗑️ å·²åˆ é™¤ ${envFilePath}`);
  }
  if (fsSync.existsSync(replacePath)) {
    for (const [key] of Object.entries(companyMap)) {
      if (key === "env") continue;
      const originFile = path.join(rootPath, config[key]);
      const backupFile = path.join(replacePath, config[key]);
      await copyFileWithOverwrite(backupFile, originFile);
    }
    await fs.rm(replacePath, { recursive: true, force: true });
    console.log(`🗑️ å·²åˆ é™¤ ${replacePath}`);
  }
}
function parseArgs(argv) {
  const params = {};
  for (let index = 2; index < argv.length; index++) {
    const arg = argv[index];
    if (!arg.startsWith("--")) continue;
    const normalized = arg.slice(2);
    const equalIndex = normalized.indexOf("=");
    if (equalIndex >= 0) {
      const key = normalized.slice(0, equalIndex);
      const value = normalized.slice(equalIndex + 1);
      params[key] = value || true;
      continue;
    }
    const nextArg = argv[index + 1];
    if (nextArg && !nextArg.startsWith("--")) {
      params[normalized] = nextArg;
      index += 1;
      continue;
    }
    params[normalized] = true;
  }
  return params;
}
function resolveCompany(parsedParams) {
  const fromArg = parseValue(parsedParams.company);
  if (fromArg) return fromArg;
  const fromNpmConfig = parseValue(process.env.npm_config_company);
  if (fromNpmConfig) return fromNpmConfig;
  const fromEnv = parseValue(process.env.COMPANY ?? process.env.company);
  if (fromEnv) return fromEnv;
  return "default";
}
function parseValue(value) {
  if (value == null || value === true) return undefined;
  if (typeof value !== "string") return undefined;
  const trimmed = value.trim();
  if (!trimmed) return undefined;
  return trimmed.replace(/^["']|["']$/g, "");
}
function createBuildEnv(companyEnv) {
  const env = { ...process.env };
  for (const key of Object.keys(env)) {
    if (key.startsWith("VITE_")) {
      delete env[key];
    }
  }
  return {
    ...env,
    ...companyEnv,
    VITE_APP_ENV: "production",
  };
}
package.json
@@ -56,5 +56,6 @@
  },
  "overrides": {
    "quill": "2.0.2"
  }
  },
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
public/favicon.ico

src/api/basicData/customer.js
@@ -26,6 +26,14 @@
    })
}
// æµå…¥å…¬æµ·
export function backCustomer(id) {
    return request({
        url: '/basic/customer/back/' + id,
        method: 'post'
    })
}
export function shareCustomer(data) {
    return request({
        url: '/basic/customer/together',
src/api/equipmentManagement/repair.js
@@ -70,3 +70,16 @@
    data,
  });
};
/**
 * @desc éªŒæ”¶å®¡æ‰¹
 * @param {验收参数} data
 * @returns
 */
export const repairAcceptance = (data) => {
  return request({
    url: `/device/repair/acceptance`,
    method: "post",
    data,
  });
};
src/api/financialManagement/accountPurchase.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
import request from "@/utils/request";
/** é‡‡è´­å…¥åº“分页列表 */
export const listPageAccountPurchase = (params) => {
  return request({
    url: "/accountPurchase/listPageAccountPurchase",
    method: "get",
    params,
  });
};
/** é‡‡è´­é€€è´§åˆ†é¡µåˆ—表 */
export const listPageAccountPurchaseReturn = (params) => {
  return request({
    url: "/accountPurchase/listPageAccountPurchaseReturn",
    method: "get",
    params,
  });
};
src/api/financialManagement/accountSales.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
import request from "@/utils/request";
/** é”€å”®å‡ºåº“分页列表 */
export const listPageAccountSales = (params) => {
  return request({
    url: "/accountSales/listPageAccountSales",
    method: "get",
    params,
  });
};
/** é”€å”®é€€è´§åˆ†é¡µåˆ—表 */
export const listPageAccountSalesReturn = (params) => {
  return request({
    url: "/accountSales/listPageAccountSalesReturn",
    method: "get",
    params,
  });
};
src/api/financialManagement/accountSubject.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
import request from "@/utils/request";
// æŸ¥è¯¢æ€»å¸ç§‘目列表
export function listAccountSubject(query) {
  return request({
    url: "/accountSubject/list",
    method: "get",
    params: query,
  });
}
// æ–°å¢žæ€»å¸ç§‘ç›®
export function addAccountSubject(data) {
  return request({
    url: "/accountSubject/add",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹æ€»å¸ç§‘ç›®
export function updateAccountSubject(data) {
  return request({
    url: "/accountSubject/edit",
    method: "put",
    data: data,
  });
}
// åˆ é™¤æ€»å¸ç§‘ç›®
export function delAccountSubject(ids) {
  return request({
    url: "/accountSubject/remove/" + ids,
    method: "delete",
  });
}
// å¯¼å‡ºæ€»å¸ç§‘ç›®
export function exportAccountSubject(data) {
  return request({
    url: "/accountSubject/export",
    method: "post",
    data: data,
    responseType: "blob",
  });
}
src/api/financialManagement/fixedAsset.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
import request from "@/utils/request";
// å›ºå®šèµ„产分页查询(current/size)
export function listFixedAssetPage(params) {
  return request({
    url: "/financial/fixedAsset/page",
    method: "get",
    params,
  });
}
// æ–°å¢žå›ºå®šèµ„产
export function addFixedAsset(data) {
  return request({
    url: "/financial/fixedAsset/add",
    method: "post",
    data,
  });
}
// ä¿®æ”¹å›ºå®šèµ„产
export function updateFixedAsset(data) {
  return request({
    url: "/financial/fixedAsset/update",
    method: "put",
    data,
  });
}
// åˆ é™¤å›ºå®šèµ„产(后端要求 ids=1&ids=2 å½¢å¼ï¼‰
export function deleteFixedAsset(ids) {
  const idList = Array.isArray(ids) ? ids : [ids];
  const query = idList
    .filter(id => id !== undefined && id !== null && id !== "")
    .map(id => `ids=${encodeURIComponent(id)}`)
    .join("&");
  return request({
    url: `/financial/fixedAsset/delete?${query}`,
    method: "delete",
  });
}
// æŠ˜æ—§è®¡æï¼ˆ{} è¡¨ç¤ºå…¨éƒ¨åœ¨ç”¨èµ„产)
export function depreciateFixedAsset(data = {}) {
  return request({
    url: "/financial/fixedAsset/depreciate",
    method: "post",
    data,
  });
}
src/api/financialManagement/intangibleAsset.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
import request from "@/utils/request";
// æ— å½¢èµ„产分页查询(current/size)
export function listIntangibleAssetPage(params) {
  return request({
    url: "/financial/intangibleAsset/page",
    method: "get",
    params,
  });
}
// æ–°å¢žæ— å½¢èµ„产
export function addIntangibleAsset(data) {
  return request({
    url: "/financial/intangibleAsset/add",
    method: "post",
    data,
  });
}
// ä¿®æ”¹æ— å½¢èµ„产
export function updateIntangibleAsset(data) {
  return request({
    url: "/financial/intangibleAsset/update",
    method: "put",
    data,
  });
}
// åˆ é™¤æ— å½¢èµ„产(后端要求 ids=1&ids=2 å½¢å¼ï¼‰
export function deleteIntangibleAsset(ids) {
  const idList = Array.isArray(ids) ? ids : [ids];
  const query = idList
    .filter(id => id !== undefined && id !== null && id !== "")
    .map(id => `ids=${encodeURIComponent(id)}`)
    .join("&");
  return request({
    url: `/financial/intangibleAsset/delete?${query}`,
    method: "delete",
  });
}
// æ‘Šé”€è®¡æï¼ˆ{} è¡¨ç¤ºå…¨éƒ¨åœ¨ç”¨èµ„产)
export function amortizeIntangibleAsset(data = {}) {
  return request({
    url: "/financial/intangibleAsset/amortize",
    method: "post",
    data,
  });
}
src/api/financialManagement/ledger.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
import request from "@/utils/request";
// ç§‘目总账
export function getGeneralLedger(params) {
  return request({
    url: "/financial/ledger/general",
    method: "get",
    params,
  });
}
// ç§‘目明细账
export function getDetailLedger(params) {
  return request({
    url: "/financial/ledger/detail",
    method: "get",
    params,
  });
}
src/api/financialManagement/voucher.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
import request from "@/utils/request";
// å‡­è¯åˆ†é¡µæŸ¥è¯¢ï¼ˆcurrent/size + è¿‡æ»¤æ¡ä»¶ï¼‰
export function listVoucherPage(params) {
  return request({
    url: "/financial/voucher/page",
    method: "get",
    params,
  });
}
// æ–°å¢žå‡­è¯
export function addVoucher(data) {
  return request({
    url: "/financial/voucher/add",
    method: "post",
    data,
  });
}
// ä¿®æ”¹å‡­è¯ï¼ˆä»…未过账)
export function updateVoucher(data) {
  return request({
    url: "/financial/voucher/update",
    method: "put",
    data,
  });
}
// è¿‡è´¦
export function postVoucher(data) {
  return request({
    url: "/financial/voucher/post",
    method: "post",
    data,
  });
}
// ä½œåºŸ
export function cancelVoucher(data) {
  return request({
    url: "/financial/voucher/cancel",
    method: "post",
    data,
  });
}
// è¯¦æƒ…
export function getVoucherDetail(id) {
  return request({
    url: `/financial/voucher/detail/${id}`,
    method: "get",
  });
}
src/api/inventoryManagement/stockInventory.js
@@ -17,6 +17,14 @@
    });
};
export const getStockInventoryBatchNoQty = (params) => {
    return request({
        url: "/stockInventory/getBatchNoQty",
        method: "get",
        params,
    });
};
// åˆ›å»ºåº“存记录
export const createStockInventory = (params) => {
    return request({
src/api/login.js
@@ -1,4 +1,5 @@
import request from '@/utils/request'
import request from '@/utils/request'
import { getToken } from '@/utils/auth'
// ç™»å½•方法
export function login(username, password, code, uuid) {
@@ -32,12 +33,14 @@
}
// èŽ·å–ç”¨æˆ·è¯¦ç»†ä¿¡æ¯
export function getInfo() {
  return request({
    url: '/getInfo',
    method: 'get'
  })
}
export function getInfo() {
  const token = getToken()
  return request({
    url: '/getInfo',
    headers: token ? { Authorization: `Bearer ${token}` } : {},
    method: 'get'
  })
}
// é€€å‡ºæ–¹æ³•
export function logout() {
src/api/oaSystem/projectManagement.js
ÎļþÒÑɾ³ý
src/api/procurementManagement/purchase_return_order.js
@@ -19,6 +19,15 @@
    });
}
// æ ¹æ®é‡‡è´­å°è´¦ ID æŸ¥è¯¢å¯é€€äº§å“ç­‰ä¿¡æ¯
export function getPurchaseReturnOrderByPurchaseLedgerId(query) {
    return request({
        url: "/purchaseReturnOrders/getByPurchaseLedgerId",
        method: "get",
        params: query,
    });
}
// æŸ¥çœ‹è¯¦æƒ…
// purchaseReturnOrders/selectById/xxx
export function getPurchaseReturnOrderDetail(id) {
src/api/salesManagement/deliveryLedger.js
@@ -17,6 +17,14 @@
    method: "get",
  });
}
// ä¿®æ”¹å‘货台账
export function getDeliveryDetailByShippingNo(query) {
  return request({
    url: "/shippingInfo/getDateilByShippingNo",
    method: "get",
    params: query,
  });
}
export function addOrUpdateDeliveryLedger(query) {
  return request({
@@ -51,4 +59,3 @@
    data,
  });
}
src/api/viewIndex.js
@@ -326,3 +326,72 @@
    method: "get",
  });
};
export const productionOverview = () => {
  return request({
    url: "/home/productionOverview",
    method: "get",
    headers: {
      handleAuthError: false,
    },
  });
};
export const productionRealtimeBoard = () => {
  return request({
    url: "/home/productionRealtimeBoard",
    method: "get",
    headers: {
      handleAuthError: false,
    },
  });
};
const HOME_PROGRESS_STATUS_LIST = ["all", "waiting", "inProgress", "completed", "paused", "1", "2", "3", "4"];
const HOME_PROGRESS_TAB_LIST = ["all", "inProgress", "completed", "paused"];
const HOME_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
const normalizeDateParam = (value) => {
  const dateText = typeof value === "string" ? value.trim() : "";
  return HOME_DATE_PATTERN.test(dateText) ? dateText : undefined;
};
export const productionOrderProgress = (params = {}) => {
  const safePageNum = Math.max(1, Number(params.pageNum || 1));
  const safePageSize = Math.min(50, Math.max(1, Number(params.pageSize || 10)));
  const rawStatus = String(params.status ?? "").trim();
  const safeStatus = HOME_PROGRESS_STATUS_LIST.includes(rawStatus) ? rawStatus : undefined;
  const safeTab = HOME_PROGRESS_TAB_LIST.includes(params.tab) ? params.tab : "all";
  const normalizedTab = safeStatus && HOME_PROGRESS_TAB_LIST.includes(safeStatus) ? safeStatus : safeTab;
  return request({
    url: "/home/productionOrderProgress",
    method: "get",
    params: {
      ...params,
      status: safeStatus,
      tab: normalizedTab,
      bizDate: normalizeDateParam(params.bizDate),
      pageNum: safePageNum,
      pageSize: safePageSize,
    },
    headers: {
      handleAuthError: false,
    },
  });
};
export const todayProductionPlan = (params = {}) => {
  const safeLimit = Math.min(20, Math.max(1, Number(params.limit || 4)));
  return request({
    url: "/home/todayProductionPlan",
    method: "get",
    params: {
      ...params,
      limit: safeLimit,
      planDate: normalizeDateParam(params.planDate),
    },
    headers: {
      handleAuthError: false,
    },
  });
};
src/assets/AI/²Ö´¢ÖúÊÖ.png
src/assets/AI/´ý°ìÖúÊÖ.png
src/assets/AI/Éú²úÖúÊÖ.png
src/assets/AI/²ÆÎñÖúÊÖ.png
src/assets/AI/ÖÊÁ¿ÖúÊÖ.png
src/assets/AI/²É¹ºÖúÊÖ.png
src/assets/AI/ÏúÊÛÖúÊÖ.png
src/assets/aiIndustrialBrain/reference-cards.png
src/assets/aiIndustrialBrain/reference-chat.png
src/assets/images/head.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="452" height="285" viewBox="0 0 452 285"><defs><pattern x="0" y="80.0157699584961" width="452" height="204.98422241210938" patternUnits="userSpaceOnUse" id="master_svg0_143_34844"><image x="-0.11198217826978407" y="0" width="452.22396435653957" height="204.98422241210938" xlink:href="data:image/png;base64,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"/></pattern><pattern x="111.42742919921875" y="0" 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="0" y="80.0157699584961" width="452" height="204.98422241210938" rx="0" fill="url(#master_svg0_143_34844)" fill-opacity="1"/><rect x="111.42742919921875" y="0" width="206.67991638183594" height="206.78233337402344" rx="0" fill="url(#master_svg1_143_34837)" fill-opacity="1"/><g><path d="M171.28799999,112L197.784,47.968002L213.431999,47.968002L239.928001,112L223.99200100000002,112L217.751999,97.216003L193.464001,97.216003L187.224001,112L171.28799999,112ZM205.656002,63.424L196.535999,85.792L214.776001,85.792L205.656002,63.424ZM246.840004,112L246.840004,47.968002L260.472,47.968002L260.472,112L246.840004,112Z" fill="#FFFFFF" fill-opacity="1"/><path d="M217.751999,97.216003L223.99200100000002,112L239.928001,112L239.514206,111L213.431999,47.968002L197.784002,47.968002L171.70179313,111L171.28799999,112L187.224003,112L193.464001,97.216003L217.751999,97.216003ZM186.560656,111L192.800652,96.216003L218.41535199999998,96.216003L224.655346,111L238.43197600000002,111L212.763565,48.968002L198.452438,48.968002L172.7840257,111L186.560656,111ZM246.840012,111L246.840012,112L260.472008,112L260.472008,47.968002L246.840012,47.968002L246.840012,111ZM247.840012,111L259.472008,111L259.472008,48.968002L247.840012,48.968002L247.840012,111ZM206.581993,63.046455L204.730011,63.046455L195.048351,86.79200399999999L216.263653,86.79200399999999L206.581993,63.046455ZM205.116039,64.748333L205.656002,63.424004L206.195965,64.748333L214.368279,84.79200399999999L214.776001,85.79200399999999L196.536001,85.79200399999999L196.943726,84.79200399999999L205.116039,64.748333Z" fill-rule="evenodd" fill="#E2E6F7" fill-opacity="1"/></g></svg>
src/assets/logo/logo.png

src/assets/styles/element-ui.scss
@@ -52,17 +52,17 @@
  left: 0;
  position: relative;
  margin: 0 auto;
  border-radius: 24px;
  border-radius: 16px;
  padding: 0 !important;
  border: 1px solid var(--surface-border);
  box-shadow: var(--shadow-md);
  background: rgba(255, 255, 255, 0.96);
  background: rgba(255, 255, 255, 0.95);
}
.el-dialog__header {
  background: linear-gradient(180deg, rgba(247, 250, 248, 0.98), rgba(242, 247, 244, 0.88));
  background: linear-gradient(180deg, rgba(248, 251, 255, 1), rgba(242, 247, 255, 0.98));
  padding: 18px 24px 14px;
  border-bottom: 1px solid var(--surface-border);
  border-radius: 24px 24px 0 0;
  border-radius: 14px 14px 0 0;
}
.el-dialog__title {
  font-weight: 600;
@@ -80,15 +80,16 @@
}
.el-message-box {
  padding: 0 !important;
  border-radius: 22px;
  border-radius: 16px;
  border: 1px solid var(--surface-border);
  box-shadow: var(--shadow-md);
  background: rgba(255, 255, 255, 0.96);
}
.el-message-box__header {
  background: linear-gradient(180deg, rgba(247, 250, 248, 0.98), rgba(242, 247, 244, 0.88));
  background: linear-gradient(180deg, rgba(248, 251, 255, 1), rgba(242, 247, 255, 0.98));
  padding: 18px 24px 14px;
  border-bottom: 1px solid var(--surface-border);
  border-radius: 22px 22px 0 0;
  border-radius: 14px 14px 0 0;
}
.el-message-box__title {
  font-weight: 600;
@@ -161,7 +162,7 @@
}
.el-button {
  border-radius: 12px;
  border-radius: 8px;
  font-weight: 600;
  box-shadow: none !important;
}
@@ -180,41 +181,44 @@
.el-select__wrapper,
.el-date-editor.el-input__wrapper,
.el-date-editor .el-input__wrapper {
  border-radius: 12px;
  box-shadow: 0 0 0 1px rgba(216, 225, 219, 0.92) inset !important;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 10px;
  box-shadow: 0 0 0 1px rgba(148, 163, 184, 0.28) inset !important;
  background: rgba(255, 255, 255, 0.92);
  color: var(--text-primary);
}
.el-input__wrapper.is-focus,
.el-select__wrapper.is-focused,
.el-textarea__inner:focus {
  box-shadow: 0 0 0 1px rgba(0, 47, 167, 0.28) inset !important;
  box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.56) inset !important;
}
.el-card {
  border: 1px solid var(--surface-border);
  box-shadow: var(--shadow-sm);
  background: rgba(255, 255, 255, 0.88);
  background: var(--panel-mask);
}
.el-table {
  --el-table-border-color: var(--surface-border);
  --el-table-header-bg-color: var(--surface-soft);
  --el-table-row-hover-bg-color: #f1f6f4;
  --el-table-current-row-bg-color: #e9f0ed;
  border-radius: 18px;
  --el-table-header-bg-color: #f2f7ff;
  --el-table-row-hover-bg-color: #f8fbff;
  --el-table-current-row-bg-color: #edf4ff;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.94) !important;
}
.el-table th.el-table__cell {
  background: var(--surface-soft) !important;
  color: var(--text-secondary);
  background: #f2f7ff !important;
  color: #3b4f6c;
  font-weight: 600;
}
.el-table tr,
.el-table td.el-table__cell,
.el-table__body tr > td.el-table__cell {
  background: var(--surface-base) !important;
  background: rgba(255, 255, 255, 0.92) !important;
  color: var(--text-secondary);
}
.el-table .el-table__body tr:hover > td.el-table__cell {
@@ -239,3 +243,19 @@
.el-pagination {
  margin-top: 18px;
}
.el-empty__description p,
.el-form-item__label,
.el-radio-button__inner,
.el-checkbox__label,
.el-tabs__item,
.el-select-dropdown__item,
.el-dropdown-menu__item {
  color: var(--text-secondary);
}
.el-date-editor .el-range-input,
.el-input__inner,
.el-textarea__inner {
  color: var(--text-primary);
}
src/assets/styles/index.scss
@@ -6,18 +6,19 @@
@import './btn.scss';
@import './ruoyi.scss';
body {
  height: 100%;
  margin: 0;
body {
  height: 100%;
  margin: 0;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  background:
    radial-gradient(circle at top left, rgba(214, 226, 219, 0.8), transparent 28%),
    linear-gradient(180deg, #f7faf8 0%, var(--app-bg) 100%);
  color: var(--text-primary);
}
  text-rendering: optimizeLegibility;
  font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  background:
    radial-gradient(circle at 9% -6%, rgba(59, 130, 246, 0.14), transparent 36%),
    radial-gradient(circle at 88% -8%, rgba(56, 189, 248, 0.12), transparent 30%),
    linear-gradient(165deg, #f3f7fc 0%, #eef5ff 54%, #f8fbff 100%);
  color: var(--text-primary);
}
label {
  font-weight: 600;
@@ -33,11 +34,11 @@
  height: 100%;
}
html,
body,
#app {
  background-color: var(--app-bg);
}
html,
body,
#app {
  background-color: var(--app-bg);
}
*,
*:before,
@@ -109,16 +110,17 @@
  }
}
aside {
  background: #eef1f6;
  padding: 8px 24px;
  margin-bottom: 20px;
  border-radius: 2px;
aside {
  background: rgba(255, 255, 255, 0.84);
  padding: 8px 24px;
  margin-bottom: 20px;
  border-radius: 12px;
  border: 1px solid var(--surface-border);
  display: block;
  line-height: 32px;
  font-size: 16px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  color: #2c3e50;
  color: var(--text-secondary);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
@@ -136,24 +138,25 @@
.app-container {
  padding: 20px 24px 24px;
}
.search_form {
.search_form {
  display: flex;
  align-items: center;
  justify-content: space-between;
  .search_title {
  .search_title {
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
  }
}
.table_list {
  background: rgba(255, 255, 255, 0.88);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: 18px;
}
    color: var(--text-secondary);
  }
}
.table_list {
  background: var(--panel-mask);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  backdrop-filter: blur(12px);
  padding: 18px;
}
.components-container {
  margin: 30px 50px;
  position: relative;
@@ -187,15 +190,15 @@
  }
}
.link-type,
.link-type:focus {
  color: var(--el-color-primary);
  cursor: pointer;
  &:hover {
    color: #165e57;
  }
}
.link-type,
.link-type:focus {
  color: var(--accent-light);
  cursor: pointer;
  &:hover {
    color: #2563eb;
  }
}
.filter-container {
  padding-bottom: 10px;
src/assets/styles/sidebar.scss
@@ -1,8 +1,8 @@
#app {
  .main-container {
    min-height: 100%;
    transition: margin-left 0.28s;
    margin-left: $base-sidebar-width;
    min-height: 100vh;
    margin-left: var(--sidebar-width);
    transition: margin-left 0.25s ease;
    position: relative;
    background: transparent;
  }
@@ -12,32 +12,98 @@
  }
  .sidebar-container {
    transition: width 0.28s;
    width: $base-sidebar-width !important;
    height: 100%;
    transition: width 0.25s ease;
    width: var(--sidebar-width) !important;
    height: 100vh;
    position: fixed;
    font-size: 0px;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 1001;
    overflow: hidden;
    padding: 12px 0 16px 16px;
    background: transparent;
    box-shadow: none;
    padding: 0;
    font-size: 0;
    background: var(--sidebar-bg);
    border-right: 1px solid rgba(255, 255, 255, 0.08);
    box-shadow: 8px 0 24px rgba(15, 23, 42, 0.08);
    isolation: isolate;
    // reset element-ui css
    &::before {
      content: "";
      position: absolute;
      inset: -28% -52% -18% -38%;
      z-index: 0;
      pointer-events: none;
      background:
        radial-gradient(circle at 9% 12%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.62), transparent 44%),
        radial-gradient(circle at 87% 18%, rgba(56, 189, 248, 0.4), transparent 48%),
        radial-gradient(circle at 20% 82%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3), transparent 43%),
        radial-gradient(circle at 66% 62%, rgba(125, 211, 252, 0.24), transparent 50%),
        conic-gradient(
          from 210deg at 58% 38%,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 0deg,
          rgba(56, 189, 248, 0.05) 76deg,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16) 180deg,
          rgba(125, 211, 252, 0.04) 290deg,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 360deg
        );
      filter: blur(7px) saturate(1.24) contrast(1.05);
      opacity: 0.96;
      transform: translate3d(0, 0, 0);
      transform-origin: 44% 58%;
      animation:
        sidebarAuroraDrift 17.9s cubic-bezier(0.31, 0.03, 0.18, 0.99) infinite,
        sidebarAuroraBreath 9.7s ease-in-out infinite,
        sidebarAuroraSkew 6.9s steps(23, end) infinite;
    }
    &::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 0;
      pointer-events: none;
      background:
        linear-gradient(
          108deg,
          transparent 10%,
          rgba(255, 255, 255, 0.17) 34%,
          rgba(255, 255, 255, 0.04) 48%,
          transparent 72%
        ),
        linear-gradient(
          202deg,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24) 0%,
          transparent 34%,
          rgba(56, 189, 248, 0.18) 66%,
          transparent 100%
        ),
        radial-gradient(circle at 74% 12%, rgba(125, 211, 252, 0.25), transparent 50%),
        radial-gradient(circle at 22% 84%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14), transparent 56%);
      background-size: 236% 100%, 186% 186%, 164% 164%, 180% 180%;
      background-position: 224% 0, 14% 16%, 78% 10%, 18% 82%;
      opacity: 0.52;
      transform: translate3d(0, 0, 0);
      animation:
        sidebarSheenSweep 13.1s linear infinite,
        sidebarSheenJitter 4.7s steps(31, end) infinite;
    }
    > * {
      position: relative;
      z-index: 1;
    }
    .horizontal-collapse-transition {
      transition: 0s width ease-in-out, 0s padding-left ease-in-out,
        0s padding-right ease-in-out;
      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
    }
    .scrollbar-wrapper {
      overflow-x: hidden !important;
      overflow-y: auto !important;
    }
    .el-scrollbar__bar.is-vertical {
      right: 0px;
      right: 2px;
    }
    .el-scrollbar {
@@ -46,8 +112,7 @@
    &.has-logo {
      .el-scrollbar {
        height: calc(100% - 72px);
        margin-top: 10px;
        height: calc(100% - 78px);
      }
    }
@@ -61,22 +126,19 @@
      overflow: hidden;
    }
    .svg-icon {
      margin-right: 16px;
    .el-menu {
      border: none !important;
      height: 100%;
      width: 100% !important;
      padding: 10px 0 16px;
      border-radius: 0;
      background: transparent !important;
      box-shadow: none;
      backdrop-filter: none;
    }
    .el-menu {
      border: none;
      height: 100%;
      width: 100% !important;
      padding: 10px 8px 18px;
      border-radius: 22px;
      background: var(--menu-surface);
      backdrop-filter: blur(18px);
      box-shadow: var(--shadow-sm);
    }
    .el-menu-item,
    .el-sub-menu__title,
    .menu-title {
      overflow: hidden !important;
      text-overflow: ellipsis !important;
@@ -84,181 +146,223 @@
    }
    .el-menu-item .el-menu-tooltip__trigger {
      display: inline-block !important;
      display: inline-flex !important;
      width: 100%;
      align-items: center;
    }
    // menu hover
    .submenu-title-noDropdown,
    .el-sub-menu__title {
      &:hover {
        background-color: var(--menu-hover) !important;
        border-radius: 14px;
      }
    }
    & .theme-light .is-active > .el-sub-menu__title {
      color: var(--current-color) !important;
    .submenu-title-noDropdown,
    .el-sub-menu__title,
    .el-menu-item {
      min-width: 0 !important;
      width: calc(100% - 24px) !important;
      margin: 0 12px 8px !important;
      height: 50px;
      line-height: 50px;
      border-radius: 14px;
      padding-left: 16px !important;
      padding-right: 36px !important;
      box-sizing: border-box;
      transition: all 0.28s ease;
      color: var(--sidebar-text);
      background: linear-gradient(128deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.01));
      border: 1px solid rgba(255, 255, 255, 0.06) !important;
      position: relative;
      overflow: hidden;
    }
    & .nest-menu .el-sub-menu > .el-sub-menu__title,
    & .el-sub-menu .el-menu-item {
      min-width: 0 !important;
      margin: 0 12px 6px;
      width: calc(100% - 24px);
      padding-left: 8px !important;
      padding-right: 8px !important;
      box-sizing: border-box;
      &:hover {
        background-color: var(--menu-hover) !important;
      }
      &.is-active {
        background-color: var(--menu-active-bg) !important;
        border-radius: 14px;
      }
    }
    .submenu-title-noDropdown::after,
    .el-sub-menu__title::after,
    .el-menu-item::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(115deg, transparent 12%, rgba(255, 255, 255, 0.16), transparent 78%);
      transform: translateX(-100%);
      opacity: 0;
      transition: transform 0.45s ease, opacity 0.26s ease;
      pointer-events: none;
    }
    & .theme-light .nest-menu .el-sub-menu > .el-sub-menu__title,
    & .theme-light .el-sub-menu .el-menu-item {
      //background-color: transparent;
      &:hover {
        background-color: var(--menu-hover) !important;
        border-radius: 14px;
      }
    }
  }
    .submenu-title-noDropdown:hover,
    .el-sub-menu__title:hover,
    .el-menu-item:hover {
      background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.28), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.08)) !important;
      border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.32) !important;
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 8px 18px rgba(8, 36, 76, 0.24);
      transform: translateX(3px);
    }
  .hideSidebar {
    .sidebar-container {
      width: 68px !important;
      padding-left: 0;
      padding-right: 0;
    }
    .main-container {
      margin-left: 84px;
    }
    .submenu-title-noDropdown:hover::after,
    .el-sub-menu__title:hover::after,
    .el-menu-item:hover::after,
    .el-menu-item.is-active::after,
    .el-sub-menu.is-active > .el-sub-menu__title::after {
      transform: translateX(100%);
      opacity: 1;
    }
    .submenu-title-noDropdown {
      padding: 0 !important;
      position: relative;
      display: flex !important;
      align-items: center;
      justify-content: center;
      .svg-icon {
        margin-right: 0;
      }
      .el-tooltip {
        padding: 0 !important;
        display: inline-flex !important;
        align-items: center;
        justify-content: center;
        width: 100%;
        .svg-icon {
          margin-left: 0;
        }
      }
      .el-menu-tooltip__trigger {
        width: 100%;
        display: inline-flex !important;
        align-items: center;
        justify-content: center;
        .svg-icon {
          width: 18px;
          height: 18px;
          margin-right: 0;
          flex-shrink: 0;
        }
      }
    }
    .el-sub-menu {
      overflow: hidden;
      & > .el-sub-menu__title {
        padding: 0 !important;
        display: flex !important;
        align-items: center;
        justify-content: center;
        .svg-icon {
          margin-left: 0;
          margin-right: 0;
        }
      }
    }
    .el-menu--collapse {
      width: 100% !important;
      padding: 10px 6px 18px;
      > .el-menu-item,
      .el-sub-menu {
        & > .el-sub-menu__title,
        &.el-menu-item {
          margin: 0 0 6px;
          width: 100%;
          padding-left: 0 !important;
          padding-right: 0 !important;
          box-sizing: border-box;
          display: flex !important;
          align-items: center;
          justify-content: center;
          .svg-icon {
            width: 18px;
            height: 18px;
            margin-right: 0;
            flex-shrink: 0;
          }
          &:hover {
            border-radius: 14px;
          }
          & > span {
            height: 0;
            width: 0;
            overflow: hidden;
            visibility: hidden;
            display: inline-block;
    & .theme-light .is-active > .el-sub-menu__title,
    & .theme-dark .is-active > .el-sub-menu__title,
    & .el-menu-item.is-active {
      color: #fff !important;
      background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important;
      background-size: 180% 180%;
      box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
      border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.5) !important;
      animation: sidebarActiveFlow 4.6s ease infinite;
    }
    & .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;
      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));
      &: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);
      }
      &.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%;
        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;
      }
    }
  }
  .hideSidebar {
    .sidebar-container {
      width: var(--sidebar-collapsed-width) !important;
    }
    .main-container {
      margin-left: var(--sidebar-collapsed-width);
    }
    .submenu-title-noDropdown {
      padding: 0 !important;
      position: relative;
      display: flex !important;
      align-items: center;
      justify-content: center;
      .svg-icon {
        margin-right: 0;
      }
      .el-tooltip {
        padding: 0 !important;
        display: inline-flex !important;
        align-items: center;
        justify-content: center;
        width: 100%;
        .svg-icon {
          margin-left: 0;
        }
      }
      .el-menu-tooltip__trigger {
        width: 100%;
        display: inline-flex !important;
        align-items: center;
        justify-content: center;
        .svg-icon {
          width: 22px;
          height: 22px;
          margin-right: 0;
          flex-shrink: 0;
        }
      }
    }
    .el-sub-menu {
      overflow: hidden;
      & > .el-sub-menu__title {
        padding: 0 !important;
        display: flex !important;
        align-items: center;
        justify-content: center;
        .svg-icon {
          margin-left: 0;
          margin-right: 0;
        }
      }
    }
    .el-menu--collapse {
      width: 100% !important;
      padding: 12px 0 16px;
      > .el-menu-item,
      .el-sub-menu {
        & > .el-sub-menu__title,
        &.el-menu-item {
          width: calc(100% - 12px) !important;
          margin: 0 6px 8px !important;
          padding-left: 0 !important;
          padding-right: 0 !important;
          box-sizing: border-box;
          display: flex !important;
          align-items: center;
          justify-content: center;
          .svg-icon {
            width: 22px;
            height: 22px;
            margin-right: 0;
            flex-shrink: 0;
          }
          & > i {
          & > span {
            height: 0;
            width: 0;
            overflow: hidden;
            visibility: hidden;
            display: inline-block;
          }
        }
      }
    }
  }
  .el-menu--collapse .el-menu .el-sub-menu {
    min-width: $base-sidebar-width !important;
          }
        }
      }
    }
  }
  // mobile responsive
  .el-menu--collapse .el-menu .el-sub-menu {
    min-width: var(--sidebar-width) !important;
  }
  .mobile {
    .main-container {
      margin-left: 0px;
      margin-left: 0;
    }
    .sidebar-container {
      transition: transform 0.28s;
      width: $base-sidebar-width !important;
      transition: transform 0.25s;
      width: var(--sidebar-width) !important;
    }
    &.hideSidebar {
      .sidebar-container {
        pointer-events: none;
        transition-duration: 0.3s;
        transform: translate3d(-$base-sidebar-width, 0, 0);
        transform: translate3d(calc(-1 * var(--sidebar-width)), 0, 0);
      }
    }
  }
@@ -271,53 +375,290 @@
  }
}
// when menu collapsed
.el-menu--vertical {
  & > .el-menu {
    .svg-icon {
      margin-right: 16px;
      margin-right: 10px;
    }
  }
  .nest-menu .el-sub-menu > .el-sub-menu__title,
  .el-menu-item {
    min-width: 0 !important;
    margin: 0 12px 6px;
    width: calc(100% - 24px);
    padding-left: 8px !important;
    padding-right: 8px !important;
    box-sizing: border-box;
    &:hover {
      // you can use $sub-menuHover
      background-color: var(--menu-hover) !important;
    }
    &.is-active {
      background-color: var(--menu-active-bg) !important;
      border-radius: 14px;
    }
  }
  .nest-menu .el-sub-menu > .el-sub-menu__title,
  .el-menu-item {
    min-width: 0 !important;
    margin: 0 10px 8px;
    width: calc(100% - 20px);
    height: 46px;
    line-height: 46px;
    padding-left: 12px !important;
    padding-right: 12px !important;
    box-sizing: border-box;
    border-radius: 12px;
    color: var(--sidebar-text);
    border: 1px solid rgba(255, 255, 255, 0.06) !important;
    background: linear-gradient(128deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.01));
    transition: all 0.24s ease;
  // the scroll bar appears when the sub-menu is too long
    &: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);
    }
    &.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%;
      color: #fff !important;
      border-radius: 12px;
      box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
      border-color: rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.5) !important;
      animation: sidebarActiveFlow 4.6s ease infinite;
    }
  }
  > .el-menu--popup {
    max-height: 100vh;
    overflow-y: auto;
    padding: 8px;
    border-radius: 18px;
    border: 1px solid var(--surface-border);
    box-shadow: var(--shadow-md);
    overflow: hidden;
    padding: 10px;
    border-radius: 14px;
    position: relative;
    isolation: isolate;
    border: 1px solid rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.26);
    box-shadow:
      0 18px 40px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16),
      var(--shadow-md);
    background: var(--sidebar-bg);
    backdrop-filter: blur(16px);
    &::-webkit-scrollbar-track-piece {
      background: #dfe7e1;
    &::before {
      content: "";
      position: absolute;
      inset: -28% -52% -18% -38%;
      z-index: 0;
      pointer-events: none;
      background:
        radial-gradient(circle at 9% 12%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.62), transparent 44%),
        radial-gradient(circle at 87% 18%, rgba(56, 189, 248, 0.4), transparent 48%),
        radial-gradient(circle at 20% 82%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.3), transparent 43%),
        radial-gradient(circle at 66% 62%, rgba(125, 211, 252, 0.24), transparent 50%),
        conic-gradient(
          from 210deg at 58% 38%,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 0deg,
          rgba(56, 189, 248, 0.05) 76deg,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.16) 180deg,
          rgba(125, 211, 252, 0.04) 290deg,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14) 360deg
        );
      filter: blur(7px) saturate(1.24) contrast(1.05);
      opacity: 0.96;
      transform: translate3d(0, 0, 0);
      transform-origin: 44% 58%;
      animation:
        sidebarAuroraDrift 17.9s cubic-bezier(0.31, 0.03, 0.18, 0.99) infinite,
        sidebarAuroraBreath 9.7s ease-in-out infinite,
        sidebarAuroraSkew 6.9s steps(23, end) infinite;
    }
    &::-webkit-scrollbar {
      width: 6px;
    &::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 0;
      pointer-events: none;
      background:
        linear-gradient(
          108deg,
          transparent 10%,
          rgba(255, 255, 255, 0.17) 34%,
          rgba(255, 255, 255, 0.04) 48%,
          transparent 72%
        ),
        linear-gradient(
          202deg,
          rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.24) 0%,
          transparent 34%,
          rgba(56, 189, 248, 0.18) 66%,
          transparent 100%
        ),
        radial-gradient(circle at 74% 12%, rgba(125, 211, 252, 0.25), transparent 50%),
        radial-gradient(circle at 22% 84%, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.14), transparent 56%);
      background-size: 236% 100%, 186% 186%, 164% 164%, 180% 180%;
      background-position: 224% 0, 14% 16%, 78% 10%, 18% 82%;
      opacity: 0.52;
      transform: translate3d(0, 0, 0);
      animation:
        sidebarSheenSweep 13.1s linear infinite,
        sidebarSheenJitter 4.7s steps(31, end) infinite;
    }
    &::-webkit-scrollbar-thumb {
      background: #9aa79e;
      border-radius: 20px;
    > * {
      position: relative;
      z-index: 1;
    }
    > .el-menu {
      max-height: calc(100vh - 20px);
      overflow-y: auto;
      overflow-x: hidden;
      &::-webkit-scrollbar-track-piece {
        background: var(--surface-muted);
      }
      &::-webkit-scrollbar {
        width: 5px;
      }
      &::-webkit-scrollbar-thumb {
        background: var(--accent-light);
        border-radius: 10px;
      }
    }
  }
}
@keyframes sidebarActiveFlow {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
@keyframes sidebarAuroraDrift {
  0% {
    transform: translate3d(-6.3%, -1.8%, 0) scale(1.05) rotate(-1.8deg);
  }
  6% {
    transform: translate3d(2.2%, -4.6%, 0) scale(1.08) rotate(0.7deg);
  }
  17% {
    transform: translate3d(-3.7%, 4.4%, 0) scale(1.11) rotate(2deg);
  }
  27% {
    transform: translate3d(5.6%, 1.2%, 0) scale(1.03) rotate(-1deg);
  }
  39% {
    transform: translate3d(-4.8%, -3.1%, 0) scale(1.09) rotate(1.5deg);
  }
  52% {
    transform: translate3d(2.9%, 4.8%, 0) scale(1.04) rotate(-1.4deg);
  }
  64% {
    transform: translate3d(-6.4%, 0.3%, 0) scale(1.08) rotate(0.5deg);
  }
  73% {
    transform: translate3d(4.8%, -3.9%, 0) scale(1.05) rotate(1.6deg);
  }
  81% {
    transform: translate3d(-2.4%, 2.9%, 0) scale(1.1) rotate(-0.8deg);
  }
  92% {
    transform: translate3d(3.7%, -1.7%, 0) scale(1.06) rotate(-1.6deg);
  }
  100% {
    transform: translate3d(-5.9%, 0.8%, 0) scale(1.08) rotate(1.2deg);
  }
}
@keyframes sidebarAuroraBreath {
  0% {
    opacity: 0.76;
    filter: blur(5px) saturate(1.08);
  }
  15% {
    opacity: 1;
    filter: blur(7px) saturate(1.28);
  }
  37% {
    opacity: 0.84;
    filter: blur(8px) saturate(1.12);
  }
  61% {
    opacity: 0.98;
    filter: blur(6px) saturate(1.24);
  }
  83% {
    opacity: 0.86;
    filter: blur(7px) saturate(1.16);
  }
  100% {
    opacity: 0.94;
    filter: blur(6px) saturate(1.2);
  }
}
@keyframes sidebarAuroraSkew {
  0% {
    transform-origin: 44% 58%;
  }
  21% {
    transform-origin: 62% 42%;
  }
  43% {
    transform-origin: 31% 66%;
  }
  66% {
    transform-origin: 68% 74%;
  }
  100% {
    transform-origin: 39% 45%;
  }
}
@keyframes sidebarSheenSweep {
  0% {
    background-position: 232% 0, 10% 18%, 80% 12%, 20% 82%;
  }
  8% {
    background-position: 186% 0, 16% 30%, 74% 18%, 28% 74%;
  }
  21% {
    background-position: 116% 0, 34% 10%, 62% 26%, 18% 64%;
  }
  37% {
    background-position: 52% 0, 50% 24%, 46% 12%, 32% 58%;
  }
  52% {
    background-position: -4% 0, 34% 54%, 22% 22%, 12% 46%;
  }
  69% {
    background-position: -62% 0, 14% 36%, 32% 34%, 24% 56%;
  }
  84% {
    background-position: -106% 0, 20% 20%, 46% 20%, 34% 70%;
  }
  100% {
    background-position: -136% 0, 10% 18%, 80% 12%, 20% 82%;
  }
}
@keyframes sidebarSheenJitter {
  0% {
    opacity: 0.28;
    transform: translate3d(0, 0, 0);
  }
  17% {
    opacity: 0.56;
    transform: translate3d(1.8%, -0.5%, 0);
  }
  38% {
    opacity: 0.34;
    transform: translate3d(-1.2%, 0.8%, 0);
  }
  63% {
    opacity: 0.6;
    transform: translate3d(2.3%, -0.3%, 0);
  }
  81% {
    opacity: 0.3;
    transform: translate3d(-1.6%, 0.7%, 0);
  }
  100% {
    opacity: 0.52;
    transform: translate3d(2%, -0.1%, 0);
  }
}
src/assets/styles/variables.module.scss
@@ -8,31 +8,32 @@
$yellow: #fec171;
$panGreen: #30b08f;
// menu palette
$menuText: #677287;
$menuActiveText: #1f7a72;
$menuBg: #f4f7f4;
$menuHover: #e7eeea;
// menu palette - ä½¿ç”¨ä¸»é¢˜è‰²
$menuText: #5a6478;
$menuActiveText: #ffffff;
$menuBg: #f8fafb;
$menuHover: rgba(var(--el-color-primary-rgb, 13, 148, 136), 0.08);
// light theme
$menuLightBg: #f4f7f4;
$menuLightHover: #e7eeea;
$menuLightText: #3b4658;
$menuLightActiveText: #1f7a72;
// light theme - ä½¿ç”¨ä¸»é¢˜è‰²
$menuLightBg: #f8fafb;
$menuLightHover: rgba(var(--el-color-primary-rgb, 13, 148, 136), 0.08);
$menuLightText: #3d4858;
$menuLightActiveText: #ffffff;
// layout
$base-sidebar-width: 216px;
$base-sidebar-collapsed-width: 72px;
$sideBarWidth: 216px;
// sidebar
$base-menu-color: #677287;
$base-menu-color-active: #1f7a72;
$base-menu-background: #f4f7f4;
$base-sub-menu-background: #eef3ef;
// sidebar - ä¼˜åŒ–后的侧边栏配色
$base-menu-color: #5a6478;
$base-menu-color-active: #0d9488;
$base-menu-background: #f8fafb;
$base-sub-menu-background: #f0f5f4;
$base-sub-menu-hover: #ffffff;
// component
$--color-primary: #1f7a72;
// component - ä¼˜åŒ–后的主题色
$--color-primary: #0d9488;
$--color-success: #67c23a;
$--color-warning: #d89b41;
$--color-danger: #d25b52;
@@ -64,88 +65,130 @@
}
:root {
  --sidebar-bg: #{$menuBg};
  --sidebar-text: #{$menuText};
  --sidebar-muted: #93a0b1;
  --menu-hover: #{$menuHover};
  --menu-active-bg: #dfe9e4;
  --menu-surface: rgba(255, 255, 255, 0.72);
  --sidebar-width: 216px;
  --sidebar-collapsed-width: 72px;
  --topbar-height: 64px;
  --tagsbar-height: 40px;
  --content-gap: 16px;
  --content-radius: 16px;
  --layout-header-z: 20;
  --app-bg: #eef2ee;
  --app-bg-accent: #dfe8e2;
  --surface-base: #ffffff;
  --surface-soft: #f7faf8;
  --surface-muted: #eff4f1;
  --surface-border: #d8e1db;
  --surface-border-strong: #c9d5ce;
  --text-primary: #21313f;
  --text-secondary: #5f6d7e;
  --text-tertiary: #8a98a8;
  --shadow-sm: 0 10px 30px rgba(31, 49, 38, 0.06);
  --shadow-md: 0 18px 50px rgba(31, 49, 38, 0.1);
  --radius-lg: 24px;
  --radius-md: 18px;
  --el-color-primary: #2563eb;
  --el-color-primary-rgb: 37, 99, 235;
  --el-color-success: #14b8a6;
  --el-color-warning: #f59e0b;
  --el-color-danger: #ef4444;
  --sidebar-bg: linear-gradient(180deg, #0e2a4f 0%, #123e69 55%, #0e2a4f 100%);
  --sidebar-text: rgba(234, 242, 255, 0.82);
  --sidebar-muted: rgba(234, 242, 255, 0.82);
  --menu-hover: rgba(147, 197, 253, 0.2);
  --menu-active-bg: linear-gradient(135deg, #2f80ff 0%, #38bdf8 100%);
  --menu-active-text: #f8fbff;
  --menu-surface: linear-gradient(180deg, rgba(13, 43, 79, 0.97) 0%, rgba(8, 28, 52, 0.94) 100%);
  --menu-active-glow: 0 8px 18px rgba(56, 139, 255, 0.28);
  --app-bg: #f3f7fc;
  --app-bg-accent: #eef5ff;
  --surface-base: rgba(255, 255, 255, 0.92);
  --surface-soft: rgba(255, 255, 255, 0.88);
  --surface-muted: #f5f9ff;
  --surface-border: rgba(148, 163, 184, 0.18);
  --surface-border-strong: rgba(96, 165, 250, 0.34);
  --text-primary: #1e293b;
  --text-secondary: #334155;
  --text-tertiary: #64748b;
  --shadow-sm: 0 12px 32px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 20px 42px rgba(15, 23, 42, 0.1);
  --shadow-menu: 0 16px 36px rgba(8, 27, 58, 0.26);
  --radius-lg: 20px;
  --radius-md: 16px;
  --radius-sm: 12px;
  --radius-xs: 10px;
  --navbar-bg: rgba(255, 255, 255, 0.78);
  --navbar-text: #21313f;
  --navbar-hover: rgba(31, 122, 114, 0.08);
  --navbar-bg: rgba(255, 255, 255, 0.86);
  --navbar-text: #1f3658;
  --navbar-hover: rgba(37, 99, 235, 0.08);
  --tags-bg: transparent;
  --tags-item-bg: rgba(255, 255, 255, 0.74);
  --tags-item-border: rgba(201, 213, 206, 0.88);
  --tags-item-text: #5f6d7e;
  --tags-item-hover: rgba(31, 122, 114, 0.08);
  --tags-close-hover: rgba(31, 122, 114, 0.18);
  --tags-item-bg: rgba(255, 255, 255, 0.9);
  --tags-item-border: rgba(148, 163, 184, 0.22);
  --tags-item-text: #334155;
  --tags-item-hover: #f4f8ff;
  --tags-close-hover: rgba(37, 99, 235, 0.16);
  --splitpanes-default-bg: #ffffff;
  --accent-primary: #2563eb;
  --accent-light: #3b82f6;
  --accent-lighter: #60a5fa;
  --panel-mask: rgba(255, 255, 255, 0.88);
  --panel-glow: inset 0 1px 0 rgba(255, 255, 255, 0.58);
  --splitpanes-default-bg: #f3f7fc;
}
html.dark {
  --el-bg-color: #141414;
  --el-bg-color-overlay: #1d1e1f;
  --el-text-color-primary: #ffffff;
  --el-text-color-regular: #d0d0d0;
  --el-border-color: #434343;
  --el-border-color-light: #434343;
  --el-bg-color: #f8fbff;
  --el-bg-color-overlay: #f3f7fd;
  --el-text-color-primary: #1e293b;
  --el-text-color-regular: #475569;
  --el-border-color: rgba(148, 163, 184, 0.2);
  --el-border-color-light: rgba(148, 163, 184, 0.18);
  --sidebar-bg: #141414;
  --sidebar-text: #ffffff;
  --menu-hover: #2d2d2d;
  --menu-active-text: #{$menuActiveText};
  --sidebar-bg: linear-gradient(180deg, #0e2a4f 0%, #123e69 55%, #0e2a4f 100%);
  --sidebar-text: rgba(234, 242, 255, 0.82);
  --sidebar-muted: rgba(234, 242, 255, 0.82);
  --menu-hover: rgba(147, 197, 253, 0.2);
  --menu-active-bg: linear-gradient(135deg, #2f80ff 0%, #38bdf8 100%);
  --menu-active-text: #f8fbff;
  --menu-surface: linear-gradient(180deg, rgba(13, 43, 79, 0.97) 0%, rgba(8, 28, 52, 0.94) 100%);
  --navbar-bg: #141414;
  --navbar-text: #ffffff;
  --navbar-hover: #141414;
  --text-primary: #1e293b;
  --text-secondary: #334155;
  --text-tertiary: #64748b;
  --accent-primary: #2563eb;
  --accent-light: #3b82f6;
  --tags-bg: #141414;
  --tags-item-bg: #1d1e1f;
  --tags-item-border: #303030;
  --tags-item-text: #d0d0d0;
  --tags-item-hover: #2d2d2d;
  --tags-close-hover: #64666a;
  --navbar-bg: rgba(255, 255, 255, 0.86);
  --navbar-text: #1f3658;
  --navbar-hover: rgba(37, 99, 235, 0.08);
  --splitpanes-bg: #141414;
  --splitpanes-border: #303030;
  --splitpanes-splitter-bg: #1d1e1f;
  --splitpanes-splitter-hover-bg: #2d2d2d;
  --tags-bg: transparent;
  --tags-item-bg: rgba(255, 255, 255, 0.9);
  --tags-item-border: rgba(148, 163, 184, 0.22);
  --tags-item-text: #334155;
  --tags-item-hover: #f4f8ff;
  --tags-close-hover: rgba(37, 99, 235, 0.16);
  --blockquote-bg: #1d1e1f;
  --blockquote-border: #303030;
  --blockquote-text: #d0d0d0;
  --cron-border: #303030;
  --splitpanes-default-bg: #141414;
  --splitpanes-bg: #f3f7fc;
  --splitpanes-border: rgba(148, 163, 184, 0.22);
  --splitpanes-splitter-bg: #e7eef8;
  --splitpanes-splitter-hover-bg: #d9e6f7;
  --blockquote-bg: #f3f7ff;
  --blockquote-border: rgba(59, 130, 246, 0.36);
  --blockquote-text: #334155;
  --cron-border: rgba(148, 163, 184, 0.22);
  --splitpanes-default-bg: #f3f7fc;
  .sidebar-container {
    .el-menu-item,
    .menu-title {
      color: var(--el-text-color-regular);
      color: var(--sidebar-text);
    }
    .el-menu-item.is-active,
    .el-menu-item.is-active .menu-title {
      color: var(--menu-active-text) !important;
    }
    & .theme-dark .nest-menu .el-sub-menu > .el-sub-menu__title,
    & .theme-dark .el-sub-menu .el-menu-item {
      background-color: var(--el-bg-color) !important;
    }
    & .theme-dark .el-sub-menu .el-menu-item.is-active {
      background-color: var(--menu-active-bg) !important;
    }
  }
  .el-menu--horizontal {
src/components/AIChatSidebar/assistants/generalAssistant.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
import { Cpu } from '@element-plus/icons-vue'
export const generalAssistant = {
  key: 'general',
  label: '待办助理',
  title: '待办智能助理',
  tooltip: '待办助手',
  icon: Cpu,
  apiBase: '/xiaozhi',
  storageKey: 'ai_chat_uuid',
  placeholder: '请输入您的问题... (Enter å‘送, Shift+Enter æ¢è¡Œ)',
  welcomeMessage: '你好',
  description: '我可以回答你的问题,为你提供业务数据解读信息、处理建议和辅助决策支持。',
  allowFileUpload: true,
  emptySessionText: '暂无历史会话',
  quickPrompts: [
    '我当前有哪些审批待办需要处理?',
    '帮我列出今天新增的审批待办。',
    '当前待我审批的单据,按时间倒序列出来。',
    '我发起的审批里,哪些还在处理中?',
    '查询流程编号 XXX çš„审批详情。',
    '流程编号 XXX çŽ°åœ¨å¡åœ¨å“ªä¸ªå®¡æ‰¹èŠ‚ç‚¹ï¼Ÿå½“å‰å®¡æ‰¹äººæ˜¯è°ï¼Ÿ',
    '帮我查看流程编号 XXX çš„审批流转记录。',
    '近7天我的审批待办统计情况怎么样?',
    '本月我的审批中,通过、驳回、处理中各有多少?',
    '近30天各类型审批数量分布是什么?',
    '帮我审批通过流程编号 XXX,备注“同意”。',
    '帮我驳回流程编号 XXX,备注“请补充说明”。',
    '撤销我刚刚对流程编号 XXX çš„审批操作。',
    '帮我修改流程编号 XXX çš„备注为“已补充附件”。',
    '删除我发起的流程编号 XXX。'
  ]
}
src/components/AIChatSidebar/assistants/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
import { generalAssistant } from './generalAssistant'
import { purchaseAssistant } from './purchaseAssistant'
import { productionAssistant } from './productionAssistant'
import { salesAssistant } from './salesAssistant'
export { generalAssistant, purchaseAssistant, productionAssistant, salesAssistant }
export const assistantRegistry = {
  general: generalAssistant,
  sales: salesAssistant,
  purchase: purchaseAssistant,
  production: productionAssistant
}
export const builtInAssistants = [generalAssistant, salesAssistant, purchaseAssistant, productionAssistant]
src/components/AIChatSidebar/assistants/productionAssistant.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
import { Operation } from '@element-plus/icons-vue'
export const productionAssistant = {
  key: 'production',
  label: '生产助理',
  title: '生产智能助理',
  tooltip: '生产智能助手',
  icon: Operation,
  apiBase: '/manufacturing-ai',
  storageKey: 'production_ai_chat_uuid',
  placeholder: '请输入生产相关问题... (Enter å‘送, Shift+Enter æ¢è¡Œ)',
  welcomeMessage: '你好',
  description: '我可以围绕生产现场、计划、工单、设备、质量、物料、异常处理提供查询、预警、分析和办理建议。',
  allowFileUpload: false,
  emptySessionText: '暂无生产会话',
  quickPrompts: [
    '查询本月生产计划',
    '查看最近10条工单',
    '查设备A-01的维修情况',
    '查质量不合格记录',
    '查低库存物料',
    '查近7天异常处理',
    '生成制造预警看板',
    '分析本月生产完成率和异常率',
    '给出工单逾期和设备待修的办理建议'
  ]
}
src/components/AIChatSidebar/assistants/purchaseAssistant.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
import { ShoppingCart } from '@element-plus/icons-vue'
export const purchaseAssistant = {
  key: 'purchase',
  label: '采购助理',
  title: '采购智能助理',
  tooltip: '采购智能助理',
  icon: ShoppingCart,
  apiBase: '/purchase-ai',
  storageKey: 'purchase_ai_chat_uuid',
  placeholder: '请输入采购问题... (Enter å‘送, Shift+Enter æ¢è¡Œ)',
  welcomeMessage: '你好',
  description: '我可以协助你分析采购订单、到货进度、供应商表现和付款情况,帮助你快速定位采购异常。',
  allowFileUpload: true,
  allowMultipleFileUpload: true,
  fileAnalyzeUrl: '/purchase-ai/analyze-files',
  emptySessionText: '暂无采购会话',
  quickPrompts: [
    '本月采购金额排名前十的物料有哪些?',
    '哪些采购订单还未入库?',
    '最近7天供应商到货异常有哪些?',
    '帮我统计待付款采购单!',
    '列出本月采购退货情况'
  ]
}
src/components/AIChatSidebar/assistants/salesAssistant.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
import { TrendCharts } from '@element-plus/icons-vue'
export const salesAssistant = {
  key: 'sales',
  label: '销售助手',
  title: '销售智能助手',
  tooltip: '销售智能助手',
  icon: TrendCharts,
  apiBase: '/sales-ai',
  storageKey: 'sales_ai_chat_uuid',
  placeholder: '请输入销售相关问题... (Enter å‘送 / Shift+Enter æ¢è¡Œ)',
  welcomeMessage: '你好',
  description: '我可以协助你查询客户档案、销售报价、销售台账、销售退货、客户往来、发货台账,并重点分析客户流失风险及回款/报价策略。',
  allowFileUpload: false,
  emptySessionText: '暂无销售会话',
  quickPrompts: [
    '查询私海客户档案前10条',
    '查询公海客户档案',
    '查询本月销售报价',
    '查询本月销售台账',
    '查询近30天销售退货',
    '查询近30天客户回款往来',
    '查询本月发货台账',
    '查看销售指标统计',
    '帮我做客户流失风险分析,近30天,前20条',
    '生成回款与报价策略建议,优先高风险客户'
  ]
}
src/components/AIChatSidebar/index.vue
@@ -1,10 +1,10 @@
<template>
  <div class="ai-chat-sidebar-wrapper">
    <!-- æ‚¬æµ®å›¾æ ‡ -->
    <div class="ai-chat-trigger" @click="toggleSidebar" v-show="!visible">
    <div v-if="!hideTrigger" class="ai-chat-trigger" @click="toggleSidebar" v-show="!visible">
      <el-tooltip :content="currentAssistant.tooltip" placement="left">
        <div class="trigger-icon">
          <el-icon :size="30" color="#fff"><component :is="currentAssistant.icon" /></el-icon>
          <el-icon :size="22" color="#fff"><component :is="currentAssistant.icon" /></el-icon>
        </div>
      </el-tooltip>
    </div>
@@ -12,14 +12,16 @@
    <!-- ä¾§è¾¹æ å¯¹è¯æ¡† -->
    <el-drawer
        v-model="visible"
        :size="drawerSize"
        direction="rtl"
        :size="computedDrawerSize"
        :direction="drawerDirection"
        :with-header="true"
        class="ai-chat-drawer"
        :modal="false"
        modal-class="ai-chat-overlay"
        :show-close="false"
        :append-to-body="false"
        :close-on-press-escape="!hideTrigger"
        :close-on-click-modal="!hideTrigger"
        @close="handleClose"
    >
      <template #header>
@@ -50,8 +52,16 @@
                <el-icon :size="18"><Plus /></el-icon>
              </el-button>
            </el-tooltip>
            <div class="action-divider"></div>
            <el-tooltip content="关闭" placement="bottom">
            <el-button
                v-if="headerExtraActionText"
                link
                class="header-action-btn header-action-btn--text"
                @click="handleHeaderExtraAction"
            >
              {{ headerExtraActionText }}
            </el-button>
            <div v-if="!hideTrigger" class="action-divider"></div>
            <el-tooltip v-if="!hideTrigger" content="关闭" placement="bottom">
              <el-button link class="header-action-btn close-btn" @click="handleManualClose">
                <el-icon :size="18"><Close /></el-icon>
              </el-button>
@@ -105,23 +115,17 @@
              <div class="assistant-scan-ring"></div>
              <div class="assistant-orbit assistant-orbit-a"></div>
              <div class="assistant-orbit assistant-orbit-b"></div>
              <div class="assistant-bot">
                <div class="assistant-bot-antenna assistant-bot-antenna-left"></div>
                <div class="assistant-bot-antenna assistant-bot-antenna-right"></div>
                <div class="assistant-bot-head">
                  <div class="assistant-bot-head-glow"></div>
                  <div class="assistant-bot-eye assistant-bot-eye-left"></div>
                  <div class="assistant-bot-eye assistant-bot-eye-right"></div>
                  <div class="assistant-bot-mouth"></div>
                </div>
                <div class="assistant-bot-neck"></div>
                <div class="assistant-bot-body">
                  <div class="assistant-bot-core">
                    <div class="assistant-bot-core-ring"></div>
                    <el-icon :size="22"><component :is="currentAssistant.icon" /></el-icon>
              <div class="assistant-model-shell">
                <div class="assistant-model-cut">
                  <img
                      v-if="currentAssistantAvatar"
                      class="assistant-model-img"
                      :src="currentAssistantAvatar"
                      :alt="currentAssistant.label"
                  />
                  <div v-else class="assistant-model-fallback">
                    <el-icon :size="30"><component :is="currentAssistant.icon" /></el-icon>
                  </div>
                  <div class="assistant-bot-arm assistant-bot-arm-left"></div>
                  <div class="assistant-bot-arm assistant-bot-arm-right"></div>
                </div>
              </div>
              <div class="assistant-status">
@@ -169,10 +173,6 @@
            </div>
          </div>
          <div v-show="!hasMessages" class="hero-dot-grid" aria-hidden="true">
            <span v-for="dot in 28" :key="dot"></span>
          </div>
          <div class="message-list" ref="messageListRef">
            <div
                v-for="(message, index) in messages"
@@ -186,6 +186,37 @@
              <div class="message-content">
                <!-- æ–‡æœ¬å†…容 -->
                <div class="text-box" v-html="message.htmlContent"></div>
                <div v-if="message.localUploadFiles?.length" class="message-local-file-list">
                  <div
                      v-for="(file, fileIndex) in message.localUploadFiles"
                      :key="`${file.previewId || file.name}-${fileIndex}`"
                      :class="['message-local-file-item', { clickable: !!file.accessUrl && !file.isImage }]"
                      @click="handleMessageFileClick(file)"
                  >
                    <el-image
                        v-if="file.isImage && file.previewUrl"
                        :src="file.previewUrl"
                        :preview-src-list="getImagePreviewList(message.localUploadFiles)"
                        :initial-index="getImagePreviewInitialIndex(message.localUploadFiles, file.previewUrl)"
                        :z-index="4000"
                        preview-teleported
                        fit="cover"
                        class="message-local-file-thumb"
                    />
                    <el-icon v-else class="message-local-file-icon"><Document /></el-icon>
                    <div class="message-local-file-meta">
                      <span
                          :class="['message-local-file-name', { clickable: !!file.accessUrl }]"
                          :title="file.name"
                          @click.stop="openMessageAttachment(file)"
                      >
                        {{ file.name }}
                      </span>
                      <small v-if="Number(file.size) > 0" class="message-local-file-size">{{ formatFileSize(file.size) }}</small>
                    </div>
                  </div>
                </div>
                <!-- å›¾è¡¨å†…容 -->
                <div v-if="message.chartOptions && message.chartRenderReady" class="charts-wrapper">
@@ -211,7 +242,303 @@
                  </el-table>
                </div>
                <!-- æ‰“字中动画 -->
                <div v-if="message.manufacturingData" class="manufacturing-card">
                  <div class="manufacturing-card__title">{{ getManufacturingTypeLabel(message.type) }}</div>
                  <div
                      v-if="message.manufacturingData.summaryEntries?.length || message.manufacturingData.coreMetrics?.length"
                      class="manufacturing-summary-grid"
                  >
                    <div
                        v-for="(entry, entryIndex) in message.manufacturingData.summaryEntries"
                        :key="`summary-${entry.key}-${entryIndex}`"
                        class="manufacturing-summary-item"
                    >
                      <span class="manufacturing-summary-label">{{ entry.label }}</span>
                      <strong class="manufacturing-summary-value">{{ entry.value }}</strong>
                    </div>
                    <div
                        v-for="(metric, metricIndex) in message.manufacturingData.coreMetrics"
                        :key="`core-${metric.key}-${metricIndex}`"
                        class="manufacturing-summary-item manufacturing-summary-item--core"
                    >
                      <span class="manufacturing-summary-label">{{ metric.label }}</span>
                      <strong class="manufacturing-summary-value">{{ metric.value }}</strong>
                    </div>
                  </div>
                  <div v-if="message.manufacturingData.warningItems?.length" class="manufacturing-warning-list">
                    <div
                        v-for="(warning, warningIndex) in message.manufacturingData.warningItems"
                        :key="`warning-${warning.title || warningIndex}`"
                        class="manufacturing-warning-item"
                    >
                      <div class="manufacturing-warning-item__head">
                        <el-tag size="small" :type="getManufacturingWarningLevelType(warning.level)">
                          {{ getManufacturingWarningLevelLabel(warning.level) }}
                        </el-tag>
                        <strong>{{ warning.title || `预警 ${warningIndex + 1}` }}</strong>
                        <span v-if="warning.count !== '' && warning.count !== null && warning.count !== undefined" class="manufacturing-warning-count">
                          {{ warning.count }}
                        </span>
                      </div>
                      <p v-if="warning.detail" class="manufacturing-warning-detail">{{ warning.detail }}</p>
                    </div>
                  </div>
                  <div
                      v-if="message.manufacturingData.listItems?.length && message.manufacturingData.columns?.length"
                      class="table-wrapper manufacturing-table-wrapper"
                  >
                    <el-table :data="message.manufacturingData.listItems" border stripe size="small" style="width: 100%">
                      <el-table-column
                          v-for="col in message.manufacturingData.columns"
                          :key="col"
                          :label="getStructuredFieldLabel(col)"
                          min-width="140"
                          show-overflow-tooltip
                      >
                        <template #default="{ row }">
                          {{ formatStructuredValue(row[col]) }}
                        </template>
                      </el-table-column>
                    </el-table>
                  </div>
                  <div v-if="message.manufacturingData.actionCards?.length" class="manufacturing-action-list">
                    <div
                        v-for="(card, cardIndex) in message.manufacturingData.actionCards"
                        :key="card.runtimeKey || `${card.code}-${card.targetApi}-${cardIndex}`"
                        class="manufacturing-action-card"
                    >
                      <div class="manufacturing-action-card__head">
                        <strong>{{ card.name || `动作 ${cardIndex + 1}` }}</strong>
                        <el-tag size="small" type="info">{{ getNormalizedRequestMethod(card.method) }}</el-tag>
                      </div>
                      <div class="manufacturing-action-card__meta">
                        <span>{{ card.code || '--' }}</span>
                        <span>{{ card.targetApi || '--' }}</span>
                      </div>
                      <p v-if="card.description" class="manufacturing-action-card__desc">{{ card.description }}</p>
                      <div v-if="card.requiredFields?.length" class="manufacturing-required-fields">
                        <span>必填字段</span>
                        <el-tag
                            v-for="field in card.requiredFields"
                            :key="field"
                            size="small"
                            type="warning"
                        >
                          {{ getStructuredPathLabel(field) }}
                        </el-tag>
                      </div>
                      <el-input
                          v-model="card.payloadText"
                          type="textarea"
                          :rows="6"
                          resize="vertical"
                          :disabled="card.executing"
                          placeholder="请输入 JSON è¯·æ±‚参数"
                      />
                      <div class="manufacturing-action-footer">
                        <span
                            v-if="card.executeResult"
                            :class="['manufacturing-action-result', card.executeError ? 'error' : 'success']"
                        >
                          {{ card.executeResult }}
                        </span>
                        <el-button
                            type="primary"
                            size="small"
                            :loading="card.executing"
                            @click="executeManufacturingAction(message, card, cardIndex)"
                        >
                          ç¡®è®¤å¹¶æ‰§è¡Œ
                        </el-button>
                      </div>
                    </div>
                  </div>
                </div>
                <div v-if="message.salesData" class="sales-structured-card">
                  <div class="sales-structured-card__title">{{ getSalesTypeLabel(message.type) }}</div>
                  <div v-if="message.salesData.summaryEntries?.length" class="sales-summary-grid">
                    <div
                        v-for="(entry, entryIndex) in message.salesData.summaryEntries"
                        :key="`sales-summary-${entry.key}-${entryIndex}`"
                        class="sales-summary-item"
                    >
                      <span class="sales-summary-label">{{ entry.label }}</span>
                      <strong class="sales-summary-value">{{ entry.value }}</strong>
                    </div>
                  </div>
                  <div v-if="message.type === 'sales_customer_churn_risk' && message.salesData.listItems?.length" class="sales-focus-list">
                    <div
                        v-for="(item, itemIndex) in message.salesData.listItems"
                        :key="`risk-${item.customerName || itemIndex}`"
                        class="sales-focus-item"
                    >
                      <div class="sales-focus-item__head">
                        <strong>{{ formatStructuredValue(item.customerName) }}</strong>
                        <div class="sales-focus-tags">
                          <el-tag size="small" :type="getSalesLevelTagType(item.riskLevel)">
                            {{ getSalesLevelLabel(item.riskLevel, 'risk') }}
                          </el-tag>
                          <el-tag size="small" type="warning">风险分 {{ formatStructuredValue(item.riskScore) }}</el-tag>
                        </div>
                      </div>
                      <div class="sales-focus-metrics">
                        <span>待回款:{{ formatStructuredValue(item.pendingAmount) }}</span>
                        <span>待回款占比:{{ formatStructuredValue(item.pendingRate) }}</span>
                        <span>距上次下单:{{ formatStructuredValue(item.daysSinceLastOrder) }}</span>
                      </div>
                      <div v-if="toStructuredStringArray(item.riskReasons).length" class="sales-focus-reasons">
                        <el-tag
                            v-for="(reason, reasonIndex) in toStructuredStringArray(item.riskReasons)"
                            :key="`${item.customerName || itemIndex}-reason-${reasonIndex}`"
                            size="small"
                            type="danger"
                            effect="plain"
                        >
                          {{ reason }}
                        </el-tag>
                      </div>
                    </div>
                  </div>
                  <div v-if="message.type === 'sales_collection_quote_strategy' && message.salesData.listItems?.length" class="sales-focus-list">
                    <div
                        v-for="(item, itemIndex) in message.salesData.listItems"
                        :key="`strategy-${item.customerName || itemIndex}`"
                        class="sales-focus-item sales-focus-item--strategy"
                    >
                      <div class="sales-focus-item__head">
                        <strong>{{ formatStructuredValue(item.customerName) }}</strong>
                        <div class="sales-focus-tags">
                          <el-tag size="small" :type="getSalesLevelTagType(item.priority)">
                            {{ getSalesLevelLabel(item.priority, 'priority') }}
                          </el-tag>
                          <el-tag size="small" type="success">转化率 {{ formatStructuredValue(item.quoteConversionRate) }}</el-tag>
                        </div>
                      </div>
                      <div class="sales-focus-metrics">
                        <span>待回款:{{ formatStructuredValue(item.pendingAmount) }}</span>
                        <span v-if="item.nextAction">下一步:{{ formatStructuredValue(item.nextAction) }}</span>
                      </div>
                      <p v-if="item.collectionStrategy" class="sales-strategy-line">
                        <strong>回款策略:</strong>{{ formatStructuredValue(item.collectionStrategy) }}
                      </p>
                      <p v-if="item.quotationStrategy" class="sales-strategy-line">
                        <strong>报价策略:</strong>{{ formatStructuredValue(item.quotationStrategy) }}
                      </p>
                    </div>
                  </div>
                  <div
                      v-if="message.salesData.listItems?.length && message.salesData.columns?.length && !isSalesFocusType(message.type)"
                      class="table-wrapper manufacturing-table-wrapper"
                  >
                    <el-table :data="message.salesData.listItems" border stripe size="small" style="width: 100%">
                      <el-table-column
                          v-for="col in message.salesData.columns"
                          :key="col"
                          :label="getStructuredFieldLabel(col)"
                          min-width="140"
                          show-overflow-tooltip
                      >
                        <template #default="{ row }">
                          {{ formatStructuredValue(row[col]) }}
                        </template>
                      </el-table-column>
                    </el-table>
                  </div>
                  <div v-if="message.salesData.topCustomers?.length && message.salesData.topCustomerColumns?.length" class="table-wrapper manufacturing-table-wrapper">
                    <div class="sales-section-title">重点客户</div>
                    <el-table :data="message.salesData.topCustomers" border stripe size="small" style="width: 100%">
                      <el-table-column
                          v-for="col in message.salesData.topCustomerColumns"
                          :key="`top-customer-${col}`"
                          :label="getStructuredFieldLabel(col)"
                          min-width="120"
                          show-overflow-tooltip
                      >
                        <template #default="{ row }">
                          {{ formatStructuredValue(row[col]) }}
                        </template>
                      </el-table-column>
                    </el-table>
                  </div>
                  <div v-if="message.salesData.contractTrend?.length && message.salesData.contractTrendColumns?.length" class="table-wrapper manufacturing-table-wrapper">
                    <div class="sales-section-title">合同趋势</div>
                    <el-table :data="message.salesData.contractTrend" border stripe size="small" style="width: 100%">
                      <el-table-column
                          v-for="col in message.salesData.contractTrendColumns"
                          :key="`contract-trend-${col}`"
                          :label="getStructuredFieldLabel(col)"
                          min-width="120"
                          show-overflow-tooltip
                      >
                        <template #default="{ row }">
                          {{ formatStructuredValue(row[col]) }}
                        </template>
                      </el-table-column>
                    </el-table>
                  </div>
                </div>
                <div v-if="message.purchaseData" class="sales-structured-card">
                  <div class="sales-structured-card__title">{{ getPurchaseTypeLabel(message.type) }}</div>
                  <div v-if="message.purchaseData.summaryEntries?.length" class="sales-summary-grid">
                    <div
                        v-for="(entry, entryIndex) in message.purchaseData.summaryEntries"
                        :key="`purchase-summary-${entry.key}-${entryIndex}`"
                        class="sales-summary-item"
                    >
                      <span class="sales-summary-label">{{ entry.label }}</span>
                      <strong class="sales-summary-value">{{ entry.value }}</strong>
                    </div>
                  </div>
                  <div
                      v-if="message.purchaseData.listItems?.length && message.purchaseData.columns?.length"
                      class="table-wrapper manufacturing-table-wrapper"
                  >
                    <el-table :data="message.purchaseData.listItems" border stripe size="small" style="width: 100%">
                      <el-table-column
                          v-for="col in message.purchaseData.columns"
                          :key="col"
                          :label="getStructuredFieldLabel(col)"
                          min-width="140"
                          show-overflow-tooltip
                      >
                        <template #default="{ row }">
                          {{ formatStructuredValue(row[col]) }}
                        </template>
                      </el-table-column>
                    </el-table>
                  </div>
                </div>
                <div v-if="message.purchaseIntentData?.quickPrompts?.length" class="purchase-intent-quick-prompt-wrap">
                  <div class="purchase-intent-quick-prompt-title">试试以下提问</div>
                  <div class="quick-prompt-list purchase-intent-quick-prompt-list">
                    <button
                        v-for="prompt in message.purchaseIntentData.quickPrompts"
                        :key="`purchase-intent-${prompt}`"
                        type="button"
                        class="quick-prompt-btn"
                        :disabled="isSending"
                        @click="sendQuickPrompt(prompt)"
                    >
                      {{ prompt }}
                    </button>
                  </div>
                </div>
                <div v-if="message.purchaseAnalysisData" class="purchase-confirm-card">
                  <div class="purchase-confirm-header">
                    <span>{{ businessTypeLabelMap[message.purchaseAnalysisData.businessType] || message.purchaseAnalysisData.businessType || '采购业务' }}</span>
@@ -443,9 +770,22 @@
            </div>
            <div class="input-box">
              <div v-if="selectedFiles.length" class="selected-file-list">
                <div v-for="(file, fileIndex) in selectedFiles" :key="`${file.name}-${fileIndex}`" class="selected-file-tag">
                  <el-icon><Document /></el-icon>
                  <span class="file-name">{{ file.name }}</span>
                <div v-for="(file, fileIndex) in selectedFileSnapshots" :key="`${file.previewId || file.name}-${fileIndex}`" class="selected-file-tag">
                  <el-image
                      v-if="file.isImage && file.previewUrl"
                      :src="file.previewUrl"
                      :preview-src-list="getImagePreviewList(selectedFileSnapshots)"
                      :initial-index="getImagePreviewInitialIndex(selectedFileSnapshots, file.previewUrl)"
                      :z-index="4000"
                      preview-teleported
                      fit="cover"
                      class="selected-file-thumb"
                  />
                  <el-icon v-else><Document /></el-icon>
                  <div class="selected-file-meta">
                    <span class="file-name">{{ file.name }}</span>
                    <small class="file-size">{{ formatFileSize(file.size) }}</small>
                  </div>
                  <el-icon class="remove-file" @click="removeSelectedFile(fileIndex)"><Close /></el-icon>
                </div>
              </div>
@@ -478,8 +818,17 @@
import { ref, onMounted, onUnmounted, nextTick, watch, computed } from 'vue'
import request from '@/utils/request'
import * as echarts from 'echarts'
import { Cpu, User, Plus, Timer, Delete, ChatDotSquare, VideoPause, Upload, Document, Close, ShoppingCart, Promotion, RefreshRight } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { Cpu, User, Plus, Timer, Delete, ChatDotSquare, VideoPause, Upload, Document, Close, Promotion, RefreshRight } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { builtInAssistants, generalAssistant } from './assistants'
import todoAssistantAvatar from '@/assets/AI/待办助手.png'
import salesAssistantAvatar from '@/assets/AI/销售助手.png'
import purchaseAssistantAvatar from '@/assets/AI/采购助手.png'
import productionAssistantAvatar from '@/assets/AI/生产助手.png'
import financeAssistantAvatar from '@/assets/AI/财务助手.png'
import bossAssistantAvatar from '@/assets/AI/待办助手.png'
const emit = defineEmits(['header-extra-action'])
const props = defineProps({
  assistants: {
@@ -489,72 +838,51 @@
  defaultAssistant: {
    type: String,
    default: ''
  },
  hideTrigger: {
    type: Boolean,
    default: false
  },
  autoOpen: {
    type: Boolean,
    default: false
  },
  drawerSize: {
    type: [String, Number],
    default: ''
  },
  drawerDirection: {
    type: String,
    default: 'rtl'
  },
  headerExtraActionText: {
    type: String,
    default: ''
  }
})
const builtInAssistants = [
  {
    key: 'general',
    label: '待办助理',
    title: '待办智能助理',
    tooltip: '待办助手',
    icon: Cpu,
    apiBase: '/xiaozhi',
    storageKey: 'ai_chat_uuid',
    placeholder: '请输入您的问题... (Enter å‘送, Shift+Enter æ¢è¡Œ)',
    welcomeMessage: '你好',
    description: '我可以回答你的问题,为你提供业务数据解读信息、处理建议和辅助决策支持。',
    allowFileUpload: true,
    emptySessionText: '暂无历史会话'
  },
  {
    key: 'purchase',
    label: '采购助理',
    title: '采购智能助理',
    tooltip: '采购智能助理',
    icon: ShoppingCart,
    apiBase: '/purchase-ai',
    storageKey: 'purchase_ai_chat_uuid',
    placeholder: '请输入采购问题... (Enter å‘送, Shift+Enter æ¢è¡Œ)',
    welcomeMessage: '你好',
    description: '我可以协助你分析采购订单、到货进度、供应商表现和付款情况,帮助你快速定位采购异常。',
    allowFileUpload: true,
    allowMultipleFileUpload: true,
    fileAnalyzeUrl: '/purchase-ai/analyze-files',
    emptySessionText: '暂无采购会话'
  }
]
const hideTrigger = computed(() => props.hideTrigger)
const headerExtraActionText = computed(() => String(props.headerExtraActionText || '').trim())
const drawerDirection = computed(() => (props.drawerDirection === 'ttb' || props.drawerDirection === 'btt' || props.drawerDirection === 'ltr' || props.drawerDirection === 'rtl')
  ? props.drawerDirection
  : 'rtl')
const assistants = computed(() => props.assistants?.length ? props.assistants : builtInAssistants)
const selectedAssistantKey = ref(props.defaultAssistant || assistants.value[0]?.key || 'general')
const currentAssistant = computed(() => assistants.value.find(item => item.key === selectedAssistantKey.value) || assistants.value[0] || builtInAssistants[0])
const showAssistantSwitch = computed(() => assistants.value.length > 1)
const assistantQuickPromptMap = {
  general: [
    '我当前有哪些审批待办需要处理?',
    '帮我列出今天新增的审批待办。',
    '当前待我审批的单据,按时间倒序列出来。',
    '我发起的审批里,哪些还在处理中?',
    '查询流程编号 XXX çš„审批详情。',
    '流程编号 XXX çŽ°åœ¨å¡åœ¨å“ªä¸ªå®¡æ‰¹èŠ‚ç‚¹ï¼Ÿå½“å‰å®¡æ‰¹äººæ˜¯è°ï¼Ÿ',
    '帮我查看流程编号 XXX çš„审批流转记录。',
    '近7天我的审批待办统计情况怎么样?',
    '本月我的审批中,通过、驳回、处理中各有多少?',
    '近30天各类型审批数量分布是什么?',
    '帮我审批通过流程编号 XXX,备注“同意”。',
    '帮我驳回流程编号 XXX,备注“请补充说明”。',
    '撤销我刚刚对流程编号 XXX çš„审批操作。',
    '帮我修改流程编号 XXX çš„备注为“已补充附件”。',
    '删除我发起的流程编号 XXX。'
  ],
  purchase: [
    '本月采购金额排名前十的物料有哪些?',
    '哪些采购订单还未入库?',
    '最近7天供应商到货异常有哪些?',
    '帮我统计待付款采购单',
    '列出本月采购退货情况'
  ]
const assistantAvatarByKey = {
  general: todoAssistantAvatar,
  todo: todoAssistantAvatar,
  purchase: purchaseAssistantAvatar,
  sales: salesAssistantAvatar,
  production: productionAssistantAvatar,
  finance: financeAssistantAvatar,
  boss: bossAssistantAvatar
}
const currentAssistantAvatar = computed(() => {
  const assistant = currentAssistant.value || {}
  return assistant.avatar || assistantAvatarByKey[assistant.key] || ''
})
const showAssistantSwitch = computed(() => assistants.value.length > 1)
const quickPromptLimit = 3
const quickPromptStart = ref(0)
const quickPrompts = computed(() => {
@@ -562,7 +890,7 @@
  if (Array.isArray(assistant.quickPrompts) && assistant.quickPrompts.length) {
    return assistant.quickPrompts
  }
  return assistantQuickPromptMap[assistant.key] || assistantQuickPromptMap.general
  return generalAssistant.quickPrompts || []
})
const displayedQuickPrompts = computed(() => {
  const prompts = quickPrompts.value || []
@@ -578,17 +906,19 @@
const visible = ref(false)
const windowWidth = ref(window.innerWidth)
const drawerSize = computed(() => {
const responsiveDrawerSize = computed(() => {
  if (windowWidth.value < 768) return '100%'
  if (windowWidth.value < 1200) return '50%'
  return '50%'
})
const computedDrawerSize = computed(() => props.drawerSize || responsiveDrawerSize.value)
const messageListRef = ref(null)
const isSending = ref(false)
const currentAbortController = ref(null)
const inputMessage = ref('')
const selectedFiles = ref([])
const uploadFileList = ref([])
const selectedFileSnapshots = ref([])
const messages = ref([])
const uuid = ref('')
const chartInstances = ref({})
@@ -600,6 +930,127 @@
  purchase_return_order: '采购退货单',
  unknown: '未知采购业务'
}
const salesStructuredTypeSet = new Set([
  'sales_customer_profile_list',
  'sales_quotation_list',
  'sales_ledger_list',
  'sales_return_list',
  'sales_customer_interaction_list',
  'sales_shipping_list',
  'sales_dashboard',
  'sales_customer_churn_risk',
  'sales_collection_quote_strategy'
])
const salesFocusTypeSet = new Set([
  'sales_customer_churn_risk',
  'sales_collection_quote_strategy'
])
const salesTypeLabelMap = {
  sales_customer_profile_list: '客户档案',
  sales_quotation_list: '销售报价',
  sales_ledger_list: '销售台账',
  sales_return_list: '销售退货',
  sales_customer_interaction_list: '客户往来',
  sales_shipping_list: '发货台账',
  sales_dashboard: '销售指标统计',
  sales_customer_churn_risk: '客户流失风险分析',
  sales_collection_quote_strategy: '回款与报价策略建议'
}
const purchaseTypeLabelMap = {
  purchase_material_rank: '采购物料金额排行',
  purchase_pending_payment_list: '待付款采购单'
}
const manufacturingStructuredTypeSet = new Set([
  'manufacturing_site_snapshot',
  'manufacturing_plan_list',
  'manufacturing_workorder_list',
  'manufacturing_device_list',
  'manufacturing_device_repair_list',
  'manufacturing_quality_list',
  'manufacturing_material_list',
  'manufacturing_exception_list',
  'manufacturing_warning',
  'manufacturing_analysis',
  'manufacturing_action_plan'
])
const manufacturingListTypeSet = new Set([
  'manufacturing_plan_list',
  'manufacturing_workorder_list',
  'manufacturing_device_list',
  'manufacturing_device_repair_list',
  'manufacturing_quality_list',
  'manufacturing_material_list',
  'manufacturing_exception_list'
])
const manufacturingTypeLabelMap = {
  manufacturing_site_snapshot: '生产现场概览',
  manufacturing_plan_list: '计划查询',
  manufacturing_workorder_list: '工单查询',
  manufacturing_device_list: '设备查询',
  manufacturing_device_repair_list: '设备维修记录查询',
  manufacturing_quality_list: '质量查询',
  manufacturing_material_list: '物料查询',
  manufacturing_exception_list: '异常查询',
  manufacturing_warning: '预警看板',
  manufacturing_analysis: '经营分析',
  manufacturing_action_plan: '办理建议'
}
const structuredFieldLabelMap = {
  workOrderNo: '工单号',
  planEndTime: '计划结束时间',
  planStartTime: '计划开始时间',
  timeRange: '时间范围',
  startDate: '开始日期',
  endDate: '结束日期',
  warningCount: '预警数量',
  overduePlanCount: '逾期计划数',
  overdueWorkOrderCount: '逾期工单数',
  actionCount: '建议动作数',
  qualityOpenCount: '质量待处理数',
  lowStockCount: '低库存数',
  exceptionCount: '异常数',
  userId: '用户ID',
  tenantId: '租户ID',
  status: '状态',
  deviceName: '设备名称',
  deviceModel: '设备型号',
  pendingRepairCount: '待维修数',
  repairTime: '维修时间',
  repairName: '报修人',
  maintenanceName: '维修人员',
  level: '预警等级',
  title: '标题',
  count: '数量',
  detail: '详情',
  remark: '备注',
  createTime: '创建时间',
  updateTime: '更新时间',
  exceptionType: '异常类型',
  materialName: '物料名称',
  stockQty: '库存量'
}
Object.assign(structuredFieldLabelMap, {
  customerName: '客户名称',
  riskLevel: '风险等级',
  riskScore: '风险评分',
  riskReasons: '风险原因',
  pendingAmount: '待回款金额',
  pendingRate: '待回款占比',
  daysSinceLastOrder: '距上次下单天数',
  priority: '优先级',
  quoteConversionRate: '报价转化率',
  collectionStrategy: '回款策略',
  quotationStrategy: '报价策略',
  nextAction: '下一步动作',
  contractAmountTotal: '合同总额',
  receivedAmountTotal: '已回款金额',
  pendingAmountTotal: '待回款总额',
  shipRate: '发货率',
  pendingOrderCount: '待付款订单数',
  totalContractAmount: '待付款合同总额',
  totalPaidAmount: '已付款总额',
  totalPendingAmount: '待付款总额'
})
const purchasePayloadFieldLabelMap = {
  purchaseLedgers: '采购台账',
  productData: '产品明细',
@@ -752,6 +1203,463 @@
  isInspected: 'isInspected',
  isChecked: 'isInspected'
}
const isPlainObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value)
const stringifyStructuredPayload = (value, spaces = 2) => {
  if (typeof value === 'string') return value
  try {
    return JSON.stringify(value ?? {}, null, spaces)
  } catch (err) {
    return '{}'
  }
}
const structuredFieldTokenLabelMap = {
  time: '时间',
  range: '范围',
  start: '开始',
  end: '结束',
  date: '日期',
  warning: '预警',
  overdue: '逾期',
  plan: '计划',
  work: 'å·¥',
  order: '单',
  workorder: '工单',
  count: '数量',
  quality: '质量',
  low: '低',
  stock: '库存',
  exception: '异常',
  action: '动作',
  user: '用户',
  tenant: '租户',
  id: 'ID',
  no: '编号',
  number: '编号',
  code: '编码',
  name: '名称',
  status: '状态',
  level: '等级',
  title: '标题',
  detail: '详情',
  total: '总数',
  rate: '比率',
  type: '类型',
  pending: '待',
  repair: 'ç»´ä¿®',
  device: '设备',
  material: '物料'
}
const convertStructuredFieldKeyToChinese = (fieldKey = '') => {
  const key = String(fieldKey || '').trim()
  if (!key) return '-'
  if (structuredFieldLabelMap[key]) return structuredFieldLabelMap[key]
  if (/[\u4e00-\u9fa5]/.test(key)) return key
  const rawTokens = key
    .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
    .replace(/[_-]+/g, ' ')
    .trim()
    .split(/\s+/)
    .filter(Boolean)
    .map(token => token.toLowerCase())
  if (!rawTokens.length) return '字段'
  const mappedTokens = rawTokens
    .map(token => structuredFieldTokenLabelMap[token] || '')
    .filter(Boolean)
  if (mappedTokens.length) {
    return mappedTokens.join('')
  }
  return '字段'
}
const getStructuredFieldLabel = (fieldKey = '') => {
  return convertStructuredFieldKeyToChinese(fieldKey)
}
const getStructuredPathLabel = (fieldPath = '') => {
  const path = String(fieldPath || '').trim()
  if (!path) return '-'
  const segments = path
    .replace(/\[(\d+)]/g, '.$1')
    .split('.')
    .filter(Boolean)
  if (!segments.length) return getStructuredFieldLabel(path)
  return segments.map((segment) => {
    if (/^\d+$/.test(segment)) {
      return `第${Number(segment) + 1}项`
    }
    return getStructuredFieldLabel(segment)
  }).join(' / ')
}
const formatStructuredValue = (value) => {
  if (value === null || value === undefined || value === '') return '-'
  if (Array.isArray(value)) {
    const preview = value.slice(0, 3).map(item => formatStructuredValue(item)).join('、')
    return value.length > 3 ? `${preview} ç­‰${value.length}项` : preview
  }
  if (isPlainObject(value)) return stringifyStructuredPayload(value, 0)
  return String(value)
}
const normalizeManufacturingSummaryEntries = (summary) => {
  if (!isPlainObject(summary)) return []
  return Object.entries(summary)
    .filter(([, value]) => value !== undefined && value !== null && `${value}`.trim() !== '')
    .map(([key, value]) => ({
      key,
      label: getStructuredFieldLabel(key),
      value: formatStructuredValue(value)
    }))
}
const normalizeManufacturingCoreMetrics = (coreMetrics) => {
  if (Array.isArray(coreMetrics)) {
    return coreMetrics.map((item, index) => {
      if (isPlainObject(item)) {
        const label = item.label || item.name || item.key || `指标${index + 1}`
        const metricValue = item.value ?? item.metricValue ?? item.data ?? '-'
        const unit = item.unit ? ` ${item.unit}` : ''
        return {
          key: String(item.key || item.name || index),
          label,
          value: `${formatStructuredValue(metricValue)}${unit}`.trim()
        }
      }
      return {
        key: String(index),
        label: `指标${index + 1}`,
        value: formatStructuredValue(item)
      }
    })
  }
  if (isPlainObject(coreMetrics)) {
    return Object.entries(coreMetrics).map(([key, value]) => ({
      key,
      label: getStructuredFieldLabel(key),
      value: formatStructuredValue(value)
    }))
  }
  return []
}
const normalizeManufacturingWarningItems = (items = []) => {
  if (!Array.isArray(items)) return []
  return items
    .filter(item => isPlainObject(item))
    .map(item => ({
      level: String(item.level || '').toLowerCase(),
      title: item.title || '',
      count: item.count ?? '',
      detail: item.detail ?? ''
    }))
}
const inferManufacturingColumns = (items = []) => {
  if (!Array.isArray(items) || !items.length) return []
  const fieldSet = new Set()
  items.forEach((item) => {
    if (!isPlainObject(item)) return
    Object.keys(item).forEach((key) => fieldSet.add(key))
  })
  return Array.from(fieldSet)
}
const getManufacturingActionCardRuntimeKey = (card = {}, index = 0) => {
  const code = String(card?.code || '').trim()
  const api = String(card?.targetApi || '').trim()
  const name = String(card?.name || '').trim()
  return `${code}::${api}::${name}::${index}`
}
const normalizeManufacturingActionCards = (actionCards = [], previousCards = []) => {
  const previousMap = new Map()
  if (Array.isArray(previousCards)) {
    previousCards.forEach((card, index) => {
      previousMap.set(getManufacturingActionCardRuntimeKey(card, index), card)
    })
  }
  return (Array.isArray(actionCards) ? actionCards : [])
    .filter(card => isPlainObject(card))
    .map((card, index) => {
      const runtimeKey = getManufacturingActionCardRuntimeKey(card, index)
      const previousCard = previousMap.get(runtimeKey)
      const fallbackPayloadText = stringifyStructuredPayload(card.examplePayload, 2)
      return {
        ...card,
        runtimeKey,
        payloadText: previousCard?.payloadText ?? fallbackPayloadText,
        executing: Boolean(previousCard?.executing),
        executed: Boolean(previousCard?.executed),
        executeResult: previousCard?.executeResult || '',
        executeError: Boolean(previousCard?.executeError)
      }
    })
}
const buildManufacturingStructuredData = (parsedData, previousData = null) => {
  const type = String(parsedData?.type || '')
  if (!manufacturingStructuredTypeSet.has(type)) return null
  const rawData = isPlainObject(parsedData?.data) ? parsedData.data : {}
  const items = Array.isArray(rawData.items) ? rawData.items.filter(item => isPlainObject(item)) : []
  const warningItems = type === 'manufacturing_warning' ? normalizeManufacturingWarningItems(items) : []
  const listItems = manufacturingListTypeSet.has(type) ? items : []
  const actionCards = type === 'manufacturing_action_plan'
    ? normalizeManufacturingActionCards(rawData.actionCards, previousData?.actionCards)
    : []
  return {
    type,
    summaryEntries: normalizeManufacturingSummaryEntries(parsedData?.summary),
    coreMetrics: normalizeManufacturingCoreMetrics(rawData.coreMetrics),
    listItems,
    columns: inferManufacturingColumns(listItems),
    warningItems,
    actionCards
  }
}
const getManufacturingTypeLabel = (type = '') => manufacturingTypeLabelMap[String(type || '')] || '制造结果'
const inferSalesColumns = (items = []) => {
  if (!Array.isArray(items) || !items.length) return []
  const fieldSet = new Set()
  items.forEach((item) => {
    if (!isPlainObject(item)) return
    Object.keys(item).forEach((key) => fieldSet.add(key))
  })
  return Array.from(fieldSet)
}
const normalizeSalesListItems = (items) => {
  if (!Array.isArray(items)) return []
  return items.filter(item => isPlainObject(item))
}
const buildSalesStructuredData = (parsedData) => {
  const type = String(parsedData?.type || '')
  if (!salesStructuredTypeSet.has(type)) return null
  const rawData = isPlainObject(parsedData?.data) ? parsedData.data : {}
  const listItems = normalizeSalesListItems(rawData.items)
  const topCustomers = normalizeSalesListItems(rawData.topCustomers)
  const contractTrend = normalizeSalesListItems(rawData.contractTrend)
  return {
    type,
    summaryEntries: normalizeManufacturingSummaryEntries(parsedData?.summary),
    listItems,
    columns: inferSalesColumns(listItems),
    topCustomers,
    topCustomerColumns: inferSalesColumns(topCustomers),
    contractTrend,
    contractTrendColumns: inferSalesColumns(contractTrend)
  }
}
const getSalesTypeLabel = (type = '') => salesTypeLabelMap[String(type || '')] || '销售查询结果'
const buildPurchaseStructuredData = (parsedData) => {
  if (parsedData?.success !== true) return null
  const type = String(parsedData?.type || '')
  if (!type.startsWith('purchase_')) return null
  const rawData = isPlainObject(parsedData?.data) ? parsedData.data : {}
  const listItems = normalizeSalesListItems(rawData.items)
  return {
    type,
    summaryEntries: normalizeManufacturingSummaryEntries(parsedData?.summary),
    listItems,
    columns: inferSalesColumns(listItems)
  }
}
const getPurchaseTypeLabel = (type = '') => purchaseTypeLabelMap[String(type || '')] || '采购查询结果'
const isSalesFocusType = (type = '') => salesFocusTypeSet.has(String(type || ''))
const getSalesLevelTagType = (level = '') => {
  const normalizedLevel = String(level || '').toLowerCase()
  if (normalizedLevel === 'high') return 'danger'
  if (normalizedLevel === 'medium') return 'warning'
  if (normalizedLevel === 'low') return 'success'
  return 'info'
}
const getSalesLevelLabel = (level = '', mode = 'risk') => {
  const normalizedLevel = String(level || '').toLowerCase()
  const suffix = mode === 'priority' ? '优先级' : '风险'
  if (normalizedLevel === 'high') return `高${suffix}`
  if (normalizedLevel === 'medium') return `中${suffix}`
  if (normalizedLevel === 'low') return `低${suffix}`
  if (!normalizedLevel) return mode === 'priority' ? '未分级' : '未评估'
  return normalizedLevel.toUpperCase()
}
const toStructuredStringArray = (value) => {
  if (Array.isArray(value)) {
    return value.map(item => String(item || '').trim()).filter(Boolean)
  }
  if (typeof value === 'string') {
    return value
      .split(/[,\uFF0C\u3001;\uFF1B\n]/)
      .map(item => item.trim())
      .filter(Boolean)
  }
  return []
}
const normalizePurchaseIntentNotRecognizedData = (parsedData) => {
  if (String(parsedData?.type || '') !== 'purchase_intent_not_recognized') return null
  const quickPrompts = toStructuredStringArray(parsedData?.data?.quickPrompts)
  if (!quickPrompts.length) return null
  return { quickPrompts }
}
const getManufacturingWarningLevelType = (level = '') => {
  const normalizedLevel = String(level || '').toLowerCase()
  if (normalizedLevel === 'high') return 'danger'
  if (normalizedLevel === 'medium') return 'warning'
  return 'info'
}
const getManufacturingWarningLevelLabel = (level = '') => {
  const normalizedLevel = String(level || '').toLowerCase()
  if (normalizedLevel === 'high') return '高'
  if (normalizedLevel === 'medium') return '中'
  return normalizedLevel ? normalizedLevel.toUpperCase() : '一般'
}
const normalizeRequestMethod = (method = 'POST') => {
  const normalized = String(method || 'POST').trim().toUpperCase()
  if (['GET', 'POST', 'PUT', 'DELETE', 'PATCH'].includes(normalized)) return normalized
  return 'POST'
}
const getNormalizedRequestMethod = (method) => normalizeRequestMethod(method)
const getPayloadValueByPath = (payload, fieldPath = '') => {
  const normalizedPath = String(fieldPath || '').trim()
  if (!normalizedPath || !isPlainObject(payload)) return undefined
  const pathSegments = normalizedPath
    .replace(/\[(\d+)]/g, '.$1')
    .split('.')
    .filter(Boolean)
  return pathSegments.reduce((current, segment) => {
    if (current === null || current === undefined) return undefined
    if (!['object', 'function'].includes(typeof current)) return undefined
    return current[segment]
  }, payload)
}
const getMissingRequiredFields = (requiredFields = [], payload = {}) => {
  if (!Array.isArray(requiredFields) || !requiredFields.length) return []
  return requiredFields.filter((fieldPath) => {
    const value = getPayloadValueByPath(payload, fieldPath)
    return !hasMeaningfulPayloadValue(value)
  })
}
const parseManufacturingActionPayload = (payloadText = '') => {
  const text = String(payloadText ?? '').trim()
  if (!text) return {}
  return JSON.parse(text)
}
const executeManufacturingAction = async (message, actionCard, cardIndex = 0) => {
  if (!message?.manufacturingData || !actionCard || actionCard.executing) return
  const actionName = actionCard.name || `动作 ${cardIndex + 1}`
  const targetApi = String(actionCard.targetApi || '').trim()
  if (!targetApi) {
    actionCard.executeError = true
    actionCard.executeResult = '缺少 targetApi,无法执行动作'
    return
  }
  let payload = {}
  try {
    payload = parseManufacturingActionPayload(actionCard.payloadText)
  } catch (err) {
    actionCard.executeError = true
    actionCard.executeResult = '请求参数不是合法 JSON,请检查后重试'
    return
  }
  const requiredFields = Array.isArray(actionCard.requiredFields) ? actionCard.requiredFields : []
  if (requiredFields.length && !isPlainObject(payload)) {
    actionCard.executeError = true
    actionCard.executeResult = '必填字段校验失败:请求参数必须是 JSON å¯¹è±¡'
    return
  }
  const missingFields = getMissingRequiredFields(requiredFields, payload)
  if (missingFields.length) {
    actionCard.executeError = true
    const missingFieldLabels = missingFields.map(field => getStructuredPathLabel(field))
    actionCard.executeResult = `缺少必填字段:${missingFieldLabels.join('、')}`
    return
  }
  try {
    await ElMessageBox.confirm(`确认执行「${actionName}」吗?`, '执行确认', {
      confirmButtonText: '确认执行',
      cancelButtonText: '取消',
      type: 'warning'
    })
  } catch (err) {
    return
  }
  actionCard.executing = true
  actionCard.executeError = false
  actionCard.executeResult = ''
  const method = normalizeRequestMethod(actionCard.method)
  const requestConfig = {
    url: targetApi,
    method: method.toLowerCase()
  }
  if (method === 'GET') {
    requestConfig.params = payload
  } else {
    requestConfig.data = payload
  }
  try {
    const res = await request(requestConfig)
    const successMsg = res?.msg || `${actionName}执行成功`
    actionCard.executed = true
    actionCard.executeError = false
    actionCard.executeResult = successMsg
    ElMessage.success(successMsg)
  } catch (err) {
    actionCard.executed = false
    actionCard.executeError = true
    actionCard.executeResult = err?.message || `${actionName}执行失败,请稍后重试`
  } finally {
    actionCard.executing = false
  }
}
// åŽ†å²ä¼šè¯ç›¸å…³
const purchaseValueTypeOptions = [
@@ -791,6 +1699,142 @@
const showHistory = ref(false)
const sessions = ref([])
const loadingSessions = ref(false)
const isImageFileType = (fileType = '') => String(fileType || '').toLowerCase().startsWith('image/')
const imageFilePathPattern = /\.(png|jpe?g|gif|webp|bmp|svg)$/i
const getPathnameFromFilePath = (filePath = '') => {
  const rawPath = String(filePath || '').trim()
  if (!rawPath) return ''
  try {
    const baseOrigin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost'
    return new URL(rawPath, baseOrigin).pathname || ''
  } catch (err) {
    return rawPath.split('?')[0]
  }
}
const isImageFilePath = (filePath = '') => {
  const pathname = getPathnameFromFilePath(filePath).toLowerCase()
  return imageFilePathPattern.test(pathname)
}
const getHistoryFileName = (filePath = '', index = 0) => {
  const pathname = getPathnameFromFilePath(filePath)
  const fileName = pathname.split('/').filter(Boolean).pop()
  if (!fileName) return `file-${index + 1}`
  try {
    return decodeURIComponent(fileName)
  } catch (err) {
    return fileName
  }
}
const getImagePreviewList = (files = []) => {
  if (!Array.isArray(files)) return []
  return files
    .filter(item => item?.isImage && item?.previewUrl)
    .map(item => item.previewUrl)
}
const getImagePreviewInitialIndex = (files = [], previewUrl = '') => {
  const list = getImagePreviewList(files)
  const index = list.indexOf(previewUrl)
  return index >= 0 ? index : 0
}
const formatFileSize = (size) => {
  const bytes = Number(size)
  if (!Number.isFinite(bytes) || bytes <= 0) return '0 B'
  if (bytes < 1024) return `${bytes} B`
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1).replace(/\.0$/, '')} KB`
  return `${(bytes / (1024 * 1024)).toFixed(1).replace(/\.0$/, '')} MB`
}
const createLocalFileSnapshot = (file, index = 0) => {
  const rawFile = typeof File !== 'undefined' && file instanceof File ? file : null
  const fileType = rawFile?.type || ''
  const isImage = isImageFileType(fileType)
  const canCreateObjectURL = typeof URL !== 'undefined' && typeof URL.createObjectURL === 'function'
  const previewUrl = isImage && rawFile && canCreateObjectURL ? URL.createObjectURL(rawFile) : ''
  return {
    previewId: `${rawFile?.name || 'file'}-${rawFile?.size || 0}-${rawFile?.lastModified || Date.now()}-${index}`,
    name: rawFile?.name || `file-${index + 1}`,
    size: rawFile?.size || 0,
    type: fileType,
    isImage,
    previewUrl,
    accessUrl: '',
    rawFile,
    isObjectUrl: !!previewUrl
  }
}
const createHistoryFileSnapshot = (filePath, memoryId = '', messageIndex = 0, fileIndex = 0) => {
  const normalizedPath = String(filePath || '').trim()
  if (!normalizedPath) return null
  const isImage = isImageFilePath(normalizedPath)
  return {
    previewId: `${memoryId || 'history'}-${messageIndex}-${fileIndex}`,
    name: getHistoryFileName(normalizedPath, fileIndex),
    size: 0,
    type: '',
    isImage,
    previewUrl: isImage ? normalizedPath : '',
    accessUrl: normalizedPath,
    rawFile: null,
    isObjectUrl: false
  }
}
const revokeLocalFileSnapshots = (snapshots = []) => {
  const canRevokeObjectURL = typeof URL !== 'undefined' && typeof URL.revokeObjectURL === 'function'
  if (!canRevokeObjectURL) return
  if (!Array.isArray(snapshots)) return
  snapshots.forEach((snapshot) => {
    if (snapshot?.isObjectUrl && snapshot?.previewUrl) {
      URL.revokeObjectURL(snapshot.previewUrl)
    }
  })
}
const mapHistoryFilePathsToSnapshots = (filePaths = [], memoryId = '', messageIndex = 0) => {
  if (!Array.isArray(filePaths)) return []
  return filePaths
    .map((filePath, fileIndex) => createHistoryFileSnapshot(filePath, memoryId, messageIndex, fileIndex))
    .filter(Boolean)
}
const openMessageAttachment = (file) => {
  const accessUrl = String(file?.accessUrl || '').trim()
  if (!accessUrl) return
  if (typeof window === 'undefined' || typeof window.open !== 'function') return
  window.open(accessUrl, '_blank', 'noopener,noreferrer')
}
const handleMessageFileClick = (file) => {
  if (!file?.accessUrl || file?.isImage) return
  openMessageAttachment(file)
}
const revokeMessageLocalFileSnapshots = (messageList = []) => {
  if (!Array.isArray(messageList)) return
  messageList.forEach((msg) => {
    if (Array.isArray(msg?.localUploadFiles)) {
      revokeLocalFileSnapshots(msg.localUploadFiles)
      msg.localUploadFiles = []
    }
  })
}
const clearSelectedFiles = ({ releaseSnapshots = true } = {}) => {
  if (releaseSnapshots) {
    revokeLocalFileSnapshots(selectedFileSnapshots.value)
  }
  selectedFiles.value = []
  uploadFileList.value = []
  selectedFileSnapshots.value = []
}
const abortCurrentRequest = () => {
  if (!currentAbortController.value) return
@@ -835,6 +1879,7 @@
const selectSession = async (session) => {
  showHistory.value = false
  clearSelectedFiles()
  uuid.value = session.memoryId
  localStorage.setItem(currentAssistant.value.storageKey, uuid.value)
@@ -842,6 +1887,7 @@
  try {
    const res = await request.get(`${currentAssistant.value.apiBase}/history/messages/${uuid.value}`)
    if (res.code === 200) {
      revokeMessageLocalFileSnapshots(messages.value)
      disposeCharts()
      messages.value = []
      const historyMsgs = res.data || []
@@ -853,7 +1899,7 @@
        const messageObj = {
          isUser,
          content: msg.content,
          content: msg.content || '',
          htmlContent: '',
          isTyping: false,
          chartOptions: null,
@@ -861,7 +1907,13 @@
          type: '',
          tableData: null,
          payloadTreeData: null,
          payloadHiddenData: null
          payloadHiddenData: null,
          purchaseAnalysisData: null,
          manufacturingData: null,
          salesData: null,
          purchaseData: null,
          purchaseIntentData: null,
          localUploadFiles: isUser ? mapHistoryFilePathsToSnapshots(msg.filePaths, uuid.value, idx) : []
        }
        messages.value.push(messageObj)
@@ -876,15 +1928,15 @@
          }
          // è§£æžåŽ†å²æ¶ˆæ¯ä¸­çš„ JSON
          const extracted = extractEmbeddedSuccessJson(msg.content)
          const extracted = extractEmbeddedSuccessJson(msg.content || '')
          if (extracted) {
            applyStructuredMessageData(messageObj, extracted.data, botMsgIndex)
          }
          updateOutputState(msg.content, botMsgIndex)
          messageObj.htmlContent = convertStreamOutput(msg.content, botMsgIndex)
          updateOutputState(msg.content || '', botMsgIndex)
          messageObj.htmlContent = convertStreamOutput(msg.content || '', botMsgIndex)
        } else {
          messageObj.htmlContent = convertTextToHtml(msg.content)
          messageObj.htmlContent = convertTextToHtml(msg.content || '')
        }
      })
      scrollToBottom()
@@ -919,15 +1971,16 @@
}
onMounted(() => {
  initUUID()
  // åˆå§‹æ¬¢è¿Ž
  if (messages.value.length === 0) {
    hello()
  if (props.autoOpen) {
    visible.value = true
  }
  initUUID()
  window.addEventListener('resize', handleWindowResize)
})
onUnmounted(() => {
  revokeMessageLocalFileSnapshots(messages.value)
  clearSelectedFiles()
  disposeCharts()
  window.removeEventListener('resize', handleWindowResize)
})
@@ -936,21 +1989,36 @@
  if (!prevKey || nextKey === prevKey) return
  abortCurrentRequest()
  revokeMessageLocalFileSnapshots(messages.value)
  disposeCharts()
  messages.value = []
  outputState.value = {}
  sessions.value = []
  showHistory.value = false
  selectedFiles.value = []
  uploadFileList.value = []
  clearSelectedFiles()
  inputMessage.value = ''
  quickPromptStart.value = 0
  initUUID()
  hello()
})
watch(() => props.defaultAssistant, (nextKey) => {
  if (!nextKey || nextKey === selectedAssistantKey.value) return
  if (!assistants.value.some(item => item.key === nextKey)) return
  selectedAssistantKey.value = nextKey
})
watch(() => props.autoOpen, (nextValue) => {
  if (nextValue) {
    visible.value = true
  }
})
const handleWindowResize = () => {
  windowWidth.value = window.innerWidth
}
const handleHeaderExtraAction = () => {
  emit('header-extra-action')
}
const toggleSidebar = () => {
@@ -961,10 +2029,12 @@
}
const handleClose = () => {
  if (hideTrigger.value) return
  visible.value = false
}
const handleManualClose = () => {
  if (hideTrigger.value) return
  if (isSending.value) {
    abortCurrentRequest()
  }
@@ -980,22 +2050,17 @@
  uuid.value = storedUUID
}
const hello = () => {
  sendRequest(currentAssistant.value.welcomeMessage || '你好')
}
const newChat = () => {
  revokeMessageLocalFileSnapshots(messages.value)
  disposeCharts()
  messages.value = []
  outputState.value = {}
  sessions.value = []
  showHistory.value = false
  selectedFiles.value = []
  uploadFileList.value = []
  clearSelectedFiles()
  quickPromptStart.value = 0
  localStorage.removeItem(currentAssistant.value.storageKey)
  initUUID()
  hello()
}
const handleNewChat = () => {
@@ -1066,7 +2131,7 @@
          const candidate = text.slice(i, j + 1)
          try {
            const parsed = JSON.parse(candidate)
            if (parsed?.success === true) {
            if (typeof parsed?.success === 'boolean') {
              return {
                data: parsed,
                startIdx: i,
@@ -1085,17 +2150,50 @@
}
const applyStructuredMessageData = (messageObj, parsedData, msgIndex, shouldRenderCharts = true) => {
  if (!messageObj || !parsedData?.success) return
  const isPurchaseIntentNotRecognized = String(parsedData?.type || '') === 'purchase_intent_not_recognized'
  if (!messageObj || (parsedData?.success !== true && !isPurchaseIntentNotRecognized)) return
  const previousManufacturingData = messageObj.manufacturingData
  messageObj.type = parsedData.type || ''
  messageObj.tableData = null
  messageObj.purchaseAnalysisData = null
  messageObj.manufacturingData = null
  messageObj.salesData = null
  messageObj.purchaseData = null
  messageObj.purchaseIntentData = null
  if (isPurchaseIntentNotRecognized) {
    messageObj.purchaseIntentData = normalizePurchaseIntentNotRecognizedData(parsedData)
    messageObj.chartOptions = null
    messageObj.chartRenderReady = false
    return
  }
  if (messageObj.type === 'todo_list' && parsedData.data) {
    messageObj.tableData = parsedData.data
  }
  const salesData = buildSalesStructuredData(parsedData)
  if (salesData) {
    messageObj.salesData = salesData
  }
  const manufacturingData = buildManufacturingStructuredData(parsedData, previousManufacturingData)
  if (manufacturingData) {
    messageObj.manufacturingData = manufacturingData
  }
  const purchaseData = buildPurchaseStructuredData(parsedData)
  if (purchaseData) {
    messageObj.purchaseData = purchaseData
  }
  if (parsedData.action === 'confirm_required' && parsedData.businessType) {
    messageObj.type = 'purchase_analysis_confirm'
    messageObj.purchaseAnalysisData = parsedData
    messageObj.manufacturingData = null
    messageObj.salesData = null
    messageObj.purchaseData = null
    if (!Array.isArray(messageObj.payloadTreeData) || !messageObj.payloadTreeData.length) {
      initializePurchasePayloadTree(messageObj, parsedData.payload || {})
    }
@@ -1135,6 +2233,27 @@
  }
  return null
}
const getStructuredFallbackText = (parsedData) => {
  if (!parsedData) return '正在为您展示分析结果...'
  if (parsedData.type === 'todo_list') return '已为您整理好相关数据。'
  if (parsedData.type === 'purchase_intent_not_recognized') return '未识别到可执行的采购查询条件,请补充查询条件后再试。'
  if (salesStructuredTypeSet.has(parsedData.type)) {
    if (parsedData.type === 'sales_customer_churn_risk') return '已为您生成客户流失风险分析。'
    if (parsedData.type === 'sales_collection_quote_strategy') return '已为您生成回款与报价策略建议。'
    if (parsedData.type === 'sales_dashboard') return '已为您生成销售指标统计。'
    return '已返回销售查询结果。'
  }
  if (manufacturingStructuredTypeSet.has(parsedData.type)) {
    if (parsedData.type === 'manufacturing_action_plan') return '已为您生成办理建议,请确认动作后执行。'
    if (parsedData.type === 'manufacturing_warning') return '已为您生成制造预警看板。'
    if (parsedData.type === 'manufacturing_analysis') return '已为您生成制造分析结果。'
    return '已返回制造查询结果。'
  }
  if (String(parsedData.type || '').startsWith('purchase_')) return '已返回采购查询结果。'
  if (parsedData.charts && Object.keys(parsedData.charts).length > 0) return '已为您生成分析图表。'
  return '正在为您展示分析结果...'
}
const buildPurchaseMaterialRankCharts = (parsedData) => {
@@ -1343,12 +2462,7 @@
  if (visibleValue === undefined || visibleValue === null) return clonePurchasePayloadValue(hiddenValue)
  if (Array.isArray(visibleValue) && Array.isArray(hiddenValue)) {
    const maxLength = Math.max(visibleValue.length, hiddenValue.length)
    const merged = []
    for (let i = 0; i < maxLength; i++) {
      merged[i] = mergePurchasePayloadWithHidden(visibleValue[i], hiddenValue[i])
    }
    return merged
    return visibleValue.map((item, index) => mergePurchasePayloadWithHidden(item, hiddenValue[index]))
  }
  if (
@@ -1667,6 +2781,76 @@
  '审批用户ID列表'
])
const purchaseIntegerFieldKeys = new Set([
  'id',
  'supplierId',
  'recorderId',
  'salesContractNoId',
  'salesLedgerId',
  'Type',
  'businessPersonId',
  'productId',
  'productModelId',
  'ticketRegistrationId',
  'type',
  'approvalStatus',
  'inventoryWarningQuantity'
])
const purchaseDecimalFieldKeys = new Set([
  'invoiceAmount',
  'contractAmount',
  'receiptPaymentAmount',
  'unReceiptPaymentAmount',
  'quantity',
  'taxRate',
  'taxInclusiveUnitPrice',
  'taxInclusiveTotalPrice',
  'taxExclusiveTotalPrice',
  'priceWithTax',
  'totalPriceWithTax'
])
const purchaseBooleanFieldKeys = new Set([
  'hasChildren',
  'isWhite',
  'isInspected',
  'isChecked'
])
const purchaseStringFieldKeys = new Set([
  'entryDateStart',
  'entryDateEnd',
  'purchaseContractNumber',
  'supplierName',
  'recorderName',
  'salesContractNo',
  'projectName',
  'entryDate',
  'executionDate',
  'remarks',
  'attachmentMaterials',
  'createdAt',
  'updatedAt',
  'phoneNumber',
  'invoiceNumber',
  'paymentMethod',
  'templateName',
  'productCategory',
  'specificationModel',
  'unit',
  'invoiceType'
])
const purchaseGenericArrayFieldKeys = new Set([
  'purchaseLedgers',
  'productData'
])
const purchaseStringArrayFieldKeys = new Set(['tempFileIds'])
const purchaseObjectArrayFieldKeys = new Set(['SalesLedgerFiles'])
const normalizePurchaseProductRecord = (record) => {
  if (!record || typeof record !== 'object' || Array.isArray(record)) return record
  return mapPayloadKeys(record, purchasePayloadFieldKeyMap)
@@ -1681,6 +2865,23 @@
    ''
}
const prunePurchaseProductRecord = (record) => {
  if (!record || typeof record !== 'object' || Array.isArray(record)) return null
  const normalizedRecord = normalizePurchaseProductRecord(record)
  const hasVisibleFieldValue = Object.entries(normalizedRecord).some(([key, value]) => {
    if (shouldHidePurchaseField(key)) return false
    return hasMeaningfulPayloadValue(value)
  })
  return hasVisibleFieldValue ? normalizedRecord : null
}
const normalizeAndFilterPurchaseProductData = (value) => {
  if (!Array.isArray(value)) return value
  return value
    .map(item => prunePurchaseProductRecord(item))
    .filter(Boolean)
}
const mergeLegacyProductDataIntoLedgers = (payload) => {
  if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return payload
  if (!Array.isArray(payload.purchaseLedgers) || !Array.isArray(payload.productData) || !payload.productData.length) {
@@ -1689,13 +2890,11 @@
  const ledgers = payload.purchaseLedgers.map(ledger => ({
    ...ledger,
    productData: Array.isArray(ledger.productData)
      ? ledger.productData.map(normalizePurchaseProductRecord)
      : []
    productData: normalizeAndFilterPurchaseProductData(ledger.productData) || []
  }))
  const unmatchedProducts = []
  payload.productData.map(normalizePurchaseProductRecord).forEach(product => {
  normalizeAndFilterPurchaseProductData(payload.productData).forEach(product => {
    const productMatchKey = getPurchaseProductMatchKey(product)
    const matchedLedger = ledgers.find(ledger => {
      const ledgerKeys = [
@@ -1734,9 +2933,7 @@
  if (!record || typeof record !== 'object' || Array.isArray(record)) return record
  const normalizedRecord = {
    ...record,
    productData: Array.isArray(record.productData)
      ? record.productData.map(normalizePurchaseProductRecord)
      : record.productData
    productData: normalizeAndFilterPurchaseProductData(record.productData)
  }
  return Object.entries(normalizedRecord).reduce((result, [key, value]) => {
    if (purchaseLedgerAllowedFieldKeys.has(key)) {
@@ -1746,12 +2943,199 @@
  }, {})
}
const normalizeAttachmentMaterialsValue = (value) => {
  if (value === null || value === undefined) return value
  if (typeof value === 'string') return value
  if (typeof value === 'number' || typeof value === 'boolean') return String(value)
  try {
    return JSON.stringify(value)
  } catch (err) {
    return String(value)
  }
}
const normalizePurchaseAttachmentMaterialsField = (value) => {
  if (Array.isArray(value)) {
    return value.map(item => normalizePurchaseAttachmentMaterialsField(item))
  }
  if (value && typeof value === 'object') {
    return Object.entries(value).reduce((result, [key, item]) => {
      if (key === 'attachmentMaterials') {
        result[key] = normalizeAttachmentMaterialsValue(item)
      } else {
        result[key] = normalizePurchaseAttachmentMaterialsField(item)
      }
      return result
    }, {})
  }
  return value
}
const normalizePurchaseNumericText = (text = '') => {
  return String(text)
    .replace(/[,\s,]/g, '')
    .replace(/[¥¥元%]/g, '')
}
const parsePurchaseNumberValue = (value) => {
  if (typeof value === 'number') {
    return Number.isFinite(value) ? value : null
  }
  if (typeof value === 'boolean') {
    return value ? 1 : 0
  }
  if (typeof value !== 'string') {
    return null
  }
  const text = normalizePurchaseNumericText(value.trim())
  if (!text) return null
  if (!/^[-+]?\d+(\.\d+)?$/.test(text)) return null
  const numberValue = Number(text)
  return Number.isFinite(numberValue) ? numberValue : null
}
const normalizePurchaseIntegerFieldValue = (value) => {
  if (value === null || value === undefined) return value
  if (value === '') return null
  const numberValue = parsePurchaseNumberValue(value)
  if (numberValue === null) return null
  return Math.trunc(numberValue)
}
const normalizePurchaseDecimalFieldValue = (value) => {
  if (value === null || value === undefined) return value
  if (value === '') return null
  const numberValue = parsePurchaseNumberValue(value)
  return numberValue === null ? null : numberValue
}
const normalizePurchaseBooleanFieldValue = (value) => {
  if (value === null || value === undefined) return value
  if (value === '') return null
  if (typeof value === 'boolean') return value
  if (typeof value === 'number') return value !== 0
  if (typeof value !== 'string') return null
  const text = value.trim().toLowerCase()
  if (!text) return null
  if (['true', '1', 'yes', 'y', '是', 'å·²', 'checked'].includes(text)) return true
  if (['false', '0', 'no', 'n', '否', '未', 'unchecked'].includes(text)) return false
  return null
}
const normalizePurchaseStringFieldValue = (value) => {
  if (value === null || value === undefined) return value
  if (typeof value === 'string') return value
  if (typeof value === 'number' || typeof value === 'boolean') return String(value)
  try {
    return JSON.stringify(value)
  } catch (err) {
    return String(value)
  }
}
const normalizePurchaseStringArrayFieldValue = (value) => {
  if (Array.isArray(value)) {
    return value
      .map(item => normalizePurchaseStringFieldValue(item))
      .filter(item => item !== null && item !== undefined && item !== '')
  }
  if (value === null || value === undefined || value === '') return []
  if (typeof value === 'string') {
    const text = value.trim()
    if (!text) return []
    if (/^\[.*\]$/.test(text)) {
      try {
        const parsedValue = JSON.parse(text)
        if (Array.isArray(parsedValue)) {
          return parsedValue
            .map(item => normalizePurchaseStringFieldValue(item))
            .filter(item => item !== null && item !== undefined && item !== '')
        }
      } catch (err) {
        // Keep as plain text when not valid JSON array.
      }
    }
    const splitValues = text
      .split(/[,\n,]/)
      .map(item => item.trim())
      .filter(Boolean)
    return splitValues.length > 1 ? splitValues : [text]
  }
  const normalizedValue = normalizePurchaseStringFieldValue(value)
  return normalizedValue === null || normalizedValue === undefined || normalizedValue === ''
    ? []
    : [normalizedValue]
}
const normalizePurchaseObjectArrayFieldValue = (value) => {
  if (Array.isArray(value)) {
    return value.filter(item => item && typeof item === 'object')
  }
  if (value && typeof value === 'object') {
    return [value]
  }
  return []
}
const normalizePurchaseValueByFieldKey = (fieldKey, value) => {
  if (fieldKey === 'attachmentMaterials') return normalizeAttachmentMaterialsValue(value)
  if (purchaseIntegerFieldKeys.has(fieldKey)) return normalizePurchaseIntegerFieldValue(value)
  if (purchaseDecimalFieldKeys.has(fieldKey)) return normalizePurchaseDecimalFieldValue(value)
  if (purchaseBooleanFieldKeys.has(fieldKey)) return normalizePurchaseBooleanFieldValue(value)
  if (purchaseStringArrayFieldKeys.has(fieldKey)) return normalizePurchaseStringArrayFieldValue(value)
  if (purchaseObjectArrayFieldKeys.has(fieldKey)) return normalizePurchaseObjectArrayFieldValue(value)
  if (purchaseStringFieldKeys.has(fieldKey)) return normalizePurchaseStringFieldValue(value)
  return value
}
const normalizePurchasePayloadFieldTypes = (value, fieldKey = '') => {
  if (purchaseGenericArrayFieldKeys.has(fieldKey)) {
    if (Array.isArray(value)) {
      return value.map(item => normalizePurchasePayloadFieldTypes(item))
    }
    if (value && typeof value === 'object') {
      return [normalizePurchasePayloadFieldTypes(value)]
    }
    return []
  }
  if (purchaseStringArrayFieldKeys.has(fieldKey)) {
    return normalizePurchaseStringArrayFieldValue(value)
  }
  if (purchaseObjectArrayFieldKeys.has(fieldKey)) {
    return normalizePurchaseObjectArrayFieldValue(value)
  }
  if (Array.isArray(value)) {
    return value.map(item => normalizePurchasePayloadFieldTypes(item))
  }
  if (value && typeof value === 'object') {
    return Object.entries(value).reduce((result, [key, item]) => {
      result[key] = normalizePurchasePayloadFieldTypes(item, key)
      return result
    }, {})
  }
  return normalizePurchaseValueByFieldKey(fieldKey, value)
}
const sanitizePurchasePayloadForSubmit = (payload, businessType) => {
  if (businessType !== 'purchase_ledger' || !payload || typeof payload !== 'object') return payload
  const sanitized = mergeLegacyProductDataIntoLedgers(Array.isArray(payload) ? [...payload] : { ...payload })
  let sanitized = mergeLegacyProductDataIntoLedgers(Array.isArray(payload) ? [...payload] : { ...payload })
  sanitized = normalizePurchaseAttachmentMaterialsField(sanitized)
  sanitized = normalizePurchasePayloadFieldTypes(sanitized)
  if (Array.isArray(sanitized.purchaseLedgers)) {
    sanitized.purchaseLedgers = sanitized.purchaseLedgers.map(filterPurchaseLedgerRecord)
  }
  if (Array.isArray(sanitized.productData)) {
    sanitized.productData = normalizeAndFilterPurchaseProductData(sanitized.productData)
  }
  if (Array.isArray(sanitized.productData) && !sanitized.productData.length) {
    delete sanitized.productData
  }
  purchaseApprovalFieldKeys.forEach(key => {
@@ -1954,16 +3338,20 @@
    return isLt10M
  })
  clearSelectedFiles()
  selectedFiles.value = validFiles
  uploadFileList.value = fileList.filter(item => item.raw && validFiles.includes(item.raw))
  selectedFileSnapshots.value = validFiles.map((rawFile, index) => createLocalFileSnapshot(rawFile, index))
}
const removeSelectedFile = (index) => {
  const [removedSnapshot] = selectedFileSnapshots.value.splice(index, 1)
  revokeLocalFileSnapshots(removedSnapshot ? [removedSnapshot] : [])
  selectedFiles.value.splice(index, 1)
  uploadFileList.value.splice(index, 1)
}
const analyzeFiles = async (files, message = '') => {
const analyzeFiles = async (files, message = '', localFileSnapshots = []) => {
  const uploadFiles = Array.isArray(files) ? files : [files].filter(Boolean)
  if (!uploadFiles.length) return
  if (isSending.value) return
@@ -1976,7 +3364,8 @@
    isUser: true,
    content: userMsg,
    htmlContent: convertTextToHtml(userMsg),
    isTyping: false
    isTyping: false,
    localUploadFiles: Array.isArray(localFileSnapshots) ? localFileSnapshots : []
  })
  const botMsgIndex = messages.value.length
@@ -1990,7 +3379,12 @@
    type: '',
    tableData: null,
    payloadTreeData: null,
    payloadHiddenData: null
    payloadHiddenData: null,
    purchaseAnalysisData: null,
    manufacturingData: null,
    salesData: null,
    purchaseData: null,
    purchaseIntentData: null
  })
  outputState.value[botMsgIndex] = {
@@ -2075,9 +3469,9 @@
  const msg = inputMessage.value?.trim() || ''
  if ((msg || selectedFiles.value.length) && !isSending.value) {
    if (selectedFiles.value.length) {
      analyzeFiles([...selectedFiles.value], msg)
      selectedFiles.value = []
      uploadFileList.value = []
      const localFileSnapshots = selectedFileSnapshots.value
      analyzeFiles([...selectedFiles.value], msg, localFileSnapshots)
      clearSelectedFiles({ releaseSnapshots: false })
    } else {
      sendRequest(msg)
    }
@@ -2113,7 +3507,12 @@
    type: '',
    tableData: null,
    payloadTreeData: null,
    payloadHiddenData: null
    payloadHiddenData: null,
    purchaseAnalysisData: null,
    manufacturingData: null,
    salesData: null,
    purchaseData: null,
    purchaseIntentData: null
  }
  messages.value.push(botMsg)
@@ -2145,28 +3544,6 @@
          const extracted = extractEmbeddedSuccessJson(fullText)
          if (extracted) {
            applyStructuredMessageData(currentMsg, extracted.data, botMsgIndex)
          } else {
            const extractJson = (text) => {
              const startIdx = text.indexOf('{"success": true')
              if (startIdx === -1) return null
              // ä»ŽåŽå¾€å‰æ‰¾æœ€åŽä¸€ä¸ª '}'
              const lastBraceIdx = text.lastIndexOf('}')
              if (lastBraceIdx === -1 || lastBraceIdx < startIdx) return null
              const potentialJson = text.substring(startIdx, lastBraceIdx + 1)
              try {
                return JSON.parse(potentialJson)
              } catch (err) {
                return null
              }
            }
            const parsedData = extractJson(fullText)
            if (parsedData) {
              applyStructuredMessageData(currentMsg, parsedData, botMsgIndex, true)
            }
          }
          updateOutputState(fullText, botMsgIndex)
@@ -2184,24 +3561,6 @@
    const extracted = extractEmbeddedSuccessJson(currentMsg.content)
    if (extracted) {
      applyStructuredMessageData(currentMsg, extracted.data, botMsgIndex)
    } else {
      const extractJson = (text) => {
        const startIdx = text.indexOf('{"success": true')
        if (startIdx === -1) return null
        const lastBraceIdx = text.lastIndexOf('}')
        if (lastBraceIdx === -1 || lastBraceIdx < startIdx) return null
        const potentialJson = text.substring(startIdx, lastBraceIdx + 1)
        try {
          return JSON.parse(potentialJson)
        } catch (err) {
          return null
        }
      }
      const finalParsed = extractJson(currentMsg.content)
      if (finalParsed) {
        applyStructuredMessageData(currentMsg, finalParsed, botMsgIndex)
      }
    }
  }).catch(err => {
    if (err.name === 'CanceledError' || err.name === 'AbortError') {
@@ -2279,13 +3638,7 @@
    }
    if (!display) {
      if (parsed.type === 'todo_list') {
        display = '已为您整理好相关数据。'
      } else if (parsed.charts && Object.keys(parsed.charts).length > 0) {
        display = '已为您生成分析图表。'
      } else {
        display = '正在为您展示分析结果...'
      }
      display = getStructuredFallbackText(parsed)
    }
  } else if (startIdx !== -1) {
    const lastBraceIdx = output.lastIndexOf('}')
@@ -2307,13 +3660,7 @@
        }
        if (!display) {
          if (parsed.type === 'todo_list') {
            display = '已为您整理好相关数据:'
          } else if (parsed.charts && Object.keys(parsed.charts).length > 0) {
            display = '已为您生成分析图表:'
          } else {
            display = '正在为您展示分析结果...'
          }
          display = getStructuredFallbackText(parsed)
        }
      } catch (e) {
        // è§£æžå¤±è´¥ï¼Œè¯´æ˜Ž JSON è¿˜åœ¨ä¼ è¾“中或格式不正确
@@ -2571,30 +3918,30 @@
.ai-chat-trigger {
  pointer-events: auto;
  position: fixed;
  right: 24px;
  bottom: 100px;
  width: 56px;
  height: 56px;
  right: 10px;
  bottom: 12px;
  width: 40px;
  height: 40px;
  background: $gradient-dark;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: $shadow-deep, 0 0 0 2px rgba(0, 85, 212, 0.3) inset, 0 0 30px rgba(0, 119, 232, 0.2);
  transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
  z-index: 2001;
  animation: triggerPulse 3s ease-in-out infinite;
  box-shadow: 0 8px 18px rgba(0, 68, 170, 0.32), 0 0 0 1px rgba(0, 136, 232, 0.32) inset;
  transition: transform 0.22s ease, box-shadow 0.22s ease, opacity 0.22s ease;
  z-index: 1020;
  opacity: 0.9;
  &::before {
    content: '';
    position: absolute;
    inset: -6px;
    inset: -4px;
    background: linear-gradient(135deg, rgba(0, 85, 212, 0.4), rgba(0, 136, 232, 0.3), rgba(90, 159, 224, 0.2));
    border-radius: 50%;
    z-index: -1;
    filter: blur(16px);
    animation: glowPulse 2s ease-in-out infinite alternate;
    filter: blur(10px);
    opacity: 0.35;
  }
  &::after {
@@ -2607,16 +3954,12 @@
  }
  &:hover {
    transform: scale(1.12) translateY(-4px);
    box-shadow: $shadow-deep, 0 0 0 3px rgba(0, 136, 232, 0.4) inset, 0 0 50px rgba(0, 136, 232, 0.3);
    &::before {
      animation: glowPulse 1s ease-in-out infinite alternate;
    }
    transform: scale(1.05) translateY(-1px);
    box-shadow: 0 10px 22px rgba(0, 68, 170, 0.38), 0 0 0 1px rgba(0, 136, 232, 0.42) inset;
    .trigger-icon {
      transform: rotate(-8deg) scale(1.05);
      filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.5));
      transform: scale(1.03);
      filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.42));
    }
  }
@@ -2659,8 +4002,9 @@
    height: 100%;
  }
  :deep(.el-drawer__header) {
    margin-bottom: 0;
    padding: 0;
    margin-bottom: 0 !important;
    padding: 0 !important;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    background: $gradient-dark;
    color: #fff;
  }
@@ -2671,7 +4015,7 @@
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 18px 20px;
  padding: 12px 18px;
  background: $gradient-dark;
  position: relative;
  overflow: hidden;
@@ -2803,6 +4147,15 @@
        opacity: 1;
      }
    }
    :deep(.header-action-btn--text) {
      width: auto !important;
      min-width: 104px;
      padding: 8px 14px !important;
      font-size: 14px;
      font-weight: 600;
      white-space: nowrap;
    }
  }
  .assistant-switcher {
@@ -2885,7 +4238,7 @@
    top: 0;
    left: 0;
    right: 0;
    height: 240px;
    height: 128px;
    background: linear-gradient(180deg, rgba(0, 85, 212, 0.06) 0%, transparent 100%);
    pointer-events: none;
  }
@@ -3125,6 +4478,87 @@
        border-radius: 2px;
      }
    }
    .message-local-file-list {
      margin-top: 8px;
      display: grid;
      gap: 8px;
      max-width: 100%;
    }
    .message-local-file-item {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 8px 10px;
      border-radius: 10px;
      border: 1px solid rgba(88, 117, 255, 0.2);
      background: rgba(255, 255, 255, 0.9);
      max-width: 100%;
      &.clickable {
        cursor: pointer;
        transition: all 0.2s ease;
        &:hover {
          border-color: rgba(44, 109, 255, 0.38);
          background: rgba(243, 247, 255, 0.96);
        }
      }
    }
    .message-local-file-thumb {
      width: 40px;
      height: 40px;
      border-radius: 6px;
      overflow: hidden;
      flex-shrink: 0;
      border: 1px solid rgba(124, 148, 255, 0.26);
      background: #f4f7ff;
      cursor: zoom-in;
      :deep(.el-image__inner) {
        width: 100%;
        height: 100%;
      }
    }
    .message-local-file-icon {
      font-size: 20px;
      color: $primary-blue;
      flex-shrink: 0;
    }
    .message-local-file-meta {
      min-width: 0;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }
    .message-local-file-name {
      font-size: 12px;
      color: #1f2a44;
      font-weight: 600;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      &.clickable {
        color: $primary-blue;
        cursor: pointer;
        &:hover {
          text-decoration: underline;
        }
      }
    }
    .message-local-file-size {
      font-size: 11px;
      color: #7f8ba1;
      line-height: 1.2;
    }
  }
  &.bot-message {
@@ -3243,6 +4677,297 @@
    --el-table-border-color: rgba(0, 122, 255, 0.08);
    --el-table-header-bg-color: $ice-white;
  }
}
.manufacturing-card {
  margin-top: 12px;
  width: 100%;
  background: #fff;
  border: 1px solid rgba(0, 85, 212, 0.12);
  border-radius: 12px;
  box-shadow: $shadow-card;
  padding: 14px;
}
.manufacturing-card__title {
  font-size: 14px;
  font-weight: 700;
  color: $deep-blue;
  margin-bottom: 10px;
}
.manufacturing-summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}
.manufacturing-summary-item {
  border-radius: 10px;
  padding: 10px 12px;
  border: 1px solid rgba(0, 85, 212, 0.08);
  background: linear-gradient(180deg, #f8fbff, #f1f7ff);
  min-height: 66px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 6px;
}
.manufacturing-summary-item--core {
  border-color: rgba(30, 91, 255, 0.24);
}
.manufacturing-summary-label {
  font-size: 12px;
  color: #4b5563;
}
.manufacturing-summary-value {
  font-size: 15px;
  color: #1f2937;
  line-height: 1.4;
  word-break: break-all;
}
.manufacturing-warning-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.manufacturing-warning-item {
  border-radius: 10px;
  border: 1px solid rgba(245, 158, 11, 0.22);
  background: linear-gradient(135deg, rgba(255, 247, 237, 0.9), rgba(255, 255, 255, 0.98));
  padding: 10px 12px;
}
.manufacturing-warning-item__head {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #92400e;
  font-size: 13px;
}
.manufacturing-warning-count {
  margin-left: auto;
  font-weight: 700;
  color: #c2410c;
}
.manufacturing-warning-detail {
  margin: 8px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: #7c2d12;
  word-break: break-all;
}
.manufacturing-table-wrapper {
  margin-top: 10px;
}
.manufacturing-action-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}
.manufacturing-action-card {
  border: 1px solid rgba(0, 85, 212, 0.1);
  border-radius: 10px;
  padding: 10px 12px;
  background: #f8fbff;
}
.manufacturing-action-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
  color: #1f2937;
  margin-bottom: 8px;
}
.manufacturing-action-card__meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 8px;
  font-size: 12px;
  color: #64748b;
  word-break: break-all;
}
.manufacturing-action-card__desc {
  margin: 0 0 8px;
  font-size: 12px;
  line-height: 1.6;
  color: #475467;
}
.manufacturing-required-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  font-size: 12px;
  color: #7c2d12;
}
.manufacturing-action-footer {
  margin-top: 8px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
}
.manufacturing-action-result {
  flex: 1;
  font-size: 12px;
  line-height: 1.5;
  &.success {
    color: #1f9d55;
  }
  &.error {
    color: #d93025;
  }
}
.sales-structured-card {
  margin-top: 12px;
  width: 100%;
  background: #fff;
  border: 1px solid rgba(31, 122, 114, 0.2);
  border-radius: 12px;
  box-shadow: $shadow-card;
  padding: 14px;
}
.sales-structured-card__title {
  font-size: 14px;
  font-weight: 700;
  color: #1f5ddf;
  margin-bottom: 10px;
}
.sales-summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}
.sales-summary-item {
  border-radius: 10px;
  padding: 10px 12px;
  border: 1px solid rgba(30, 91, 255, 0.12);
  background: linear-gradient(180deg, #f7fbff, #edf6ff);
  min-height: 66px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 6px;
}
.sales-summary-label {
  font-size: 12px;
  color: #4b5563;
}
.sales-summary-value {
  font-size: 15px;
  color: #1f2937;
  line-height: 1.4;
  word-break: break-all;
}
.sales-focus-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sales-focus-item {
  border-radius: 10px;
  border: 1px solid rgba(30, 91, 255, 0.14);
  background: #f8fbff;
  padding: 10px 12px;
}
.sales-focus-item--strategy {
  border-color: rgba(31, 122, 114, 0.22);
  background: linear-gradient(180deg, #f7fcfb, #edf9f6);
}
.sales-focus-item__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  font-size: 13px;
  color: #1f2937;
}
.sales-focus-tags {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.sales-focus-metrics {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12px;
  color: #475467;
}
.sales-focus-reasons {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.sales-strategy-line {
  margin: 8px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: #334155;
}
.sales-section-title {
  margin: 4px 0 8px;
  font-size: 13px;
  font-weight: 700;
  color: $deep-blue;
}
.purchase-intent-quick-prompt-wrap {
  margin-top: 12px;
}
.purchase-intent-quick-prompt-title {
  font-size: 12px;
  color: #4b5563;
}
.purchase-intent-quick-prompt-list {
  margin-top: 8px;
}
.purchase-confirm-card {
@@ -3537,6 +5262,28 @@
        font-size: 18px;
      }
      .selected-file-thumb {
        width: 30px;
        height: 30px;
        border-radius: 6px;
        overflow: hidden;
        border: 1px solid rgba(0, 85, 212, 0.2);
        flex-shrink: 0;
        cursor: zoom-in;
        :deep(.el-image__inner) {
          width: 100%;
          height: 100%;
        }
      }
      .selected-file-meta {
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 2px;
      }
      .file-name {
        font-size: 13px;
        color: $deep-blue;
@@ -3544,6 +5291,12 @@
        overflow: hidden;
        text-overflow: ellipsis;
        font-weight: 600;
      }
      .file-size {
        font-size: 11px;
        color: #5f86b4;
        line-height: 1.1;
      }
      .remove-file {
@@ -3703,75 +5456,59 @@
.chat-hero {
  display: grid;
  grid-template-columns: 164px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
  padding: 14px 18px 6px;
  grid-template-columns: 176px minmax(0, 1fr);
  gap: 14px;
  align-items: stretch;
  padding: 8px 18px 4px;
  &.compact {
    grid-template-columns: 122px minmax(0, 1fr);
    gap: 12px;
    padding: 8px 18px 2px;
    grid-template-columns: 132px minmax(0, 1fr);
    gap: 10px;
    padding: 4px 18px 2px;
  }
}
.assistant-stand {
  position: relative;
  min-height: 252px;
  min-height: 206px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  padding-top: 18px;
  padding-top: 8px;
  overflow: hidden;
  &.compact {
    min-height: 176px;
    padding-top: 8px;
    min-height: 160px;
    padding-top: 4px;
  }
  &.thinking {
    .assistant-halo {
      opacity: 1;
      transform: scale(1.08);
      filter: blur(8px);
      transform: scale(1.12);
      filter: blur(9px);
    }
    .assistant-scan-ring {
      opacity: 1;
      animation-duration: 1.6s;
      opacity: 0.95;
      animation-duration: 1.5s;
    }
    .assistant-orbit {
      opacity: 1;
      opacity: 0.76;
    }
    .assistant-bot {
      transform: translateY(-4px) scale(1.02);
    .assistant-model-shell {
      transform: translateY(-5px) scale(1.02);
    }
    .assistant-bot-head {
      box-shadow: 0 0 30px rgba(80, 157, 255, 0.36);
    .assistant-model-cut {
      animation-duration: 2.2s;
    }
    .assistant-bot-eye {
      animation: robotBlinkFast 1.1s infinite;
      box-shadow: 0 0 16px rgba(72, 186, 255, 0.95);
    }
    .assistant-bot-mouth {
      width: 28px;
      opacity: 1;
      animation: robotTalk 1.2s ease-in-out infinite;
    }
    .assistant-bot-core {
      animation: corePulse 1.4s ease-in-out infinite;
      box-shadow: 0 0 24px rgba(78, 120, 255, 0.26);
    }
    .assistant-bot-core-ring {
      animation: coreRotate 3s linear infinite;
    .assistant-model-img {
      filter: saturate(1.06) drop-shadow(0 18px 20px rgba(22, 48, 80, 0.22));
    }
    .assistant-status {
@@ -3785,219 +5522,174 @@
      animation: thinkingDot 1s ease-in-out infinite;
    }
    .assistant-base-lg {
      animation-duration: 1.8s;
    }
    .assistant-base-md {
      animation-duration: 1.5s;
    }
    .assistant-base-sm {
      box-shadow: 0 0 24px rgba(255, 93, 122, 0.48);
      box-shadow: 0 0 24px rgba(30, 91, 255, 0.36);
      animation-duration: 1.25s;
    }
  }
}
.assistant-halo {
  position: absolute;
  top: 22px;
  width: 130px;
  height: 130px;
  top: 24px;
  width: 146px;
  height: 146px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(46, 140, 224, 0.3) 0%, rgba(0, 85, 212, 0.18) 42%, rgba(113, 54, 244, 0.12) 60%, transparent 78%);
  background: radial-gradient(circle, rgba(31, 122, 114, 0.26) 0%, rgba(30, 91, 255, 0.2) 42%, rgba(109, 65, 237, 0.12) 66%, transparent 80%);
  filter: blur(6px);
  opacity: 0.82;
  opacity: 0.78;
  transition: all 0.35s ease;
}
.assistant-scan-ring {
  position: absolute;
  top: 40px;
  width: 132px;
  height: 132px;
  top: 44px;
  width: 136px;
  height: 136px;
  border-radius: 50%;
  border: 1px solid rgba(90, 159, 224, 0.22);
  border: 1px solid rgba(67, 145, 223, 0.24);
  box-shadow: inset 0 0 16px rgba(255, 255, 255, 0.25);
  opacity: 0.55;
  opacity: 0.52;
  animation: scanRing 4s linear infinite;
}
.assistant-orbit {
  position: absolute;
  top: 52px;
  width: 150px;
  height: 150px;
  width: 156px;
  height: 156px;
  border-radius: 50%;
  border: 1px dashed rgba(92, 135, 255, 0.22);
  opacity: 0.45;
  border: 1px dashed rgba(92, 135, 255, 0.24);
  opacity: 0.42;
}
.assistant-orbit-a {
  animation: orbitRotate 8s linear infinite;
  animation: orbitRotate 8.6s linear infinite;
}
.assistant-orbit-b {
  width: 118px;
  height: 118px;
  width: 124px;
  height: 124px;
  top: 68px;
  border-color: rgba(255, 108, 150, 0.22);
  animation: orbitRotateReverse 5.6s linear infinite;
  border-color: rgba(31, 122, 114, 0.24);
  animation: orbitRotateReverse 6.2s linear infinite;
}
.assistant-bot {
.assistant-model-shell {
  position: relative;
  z-index: 1;
  width: 148px;
  height: 178px;
  display: flex;
  flex-direction: column;
  align-items: center;
  align-items: flex-end;
  justify-content: center;
  margin-top: 12px;
  margin-top: 4px;
  transition: transform 0.35s ease;
}
.assistant-bot-antenna {
  position: absolute;
  top: -4px;
  width: 4px;
  height: 20px;
  border-radius: 999px;
  background: linear-gradient(180deg, #fefefe, #aac9ff);
  &::before {
    content: '';
    position: absolute;
    top: -6px;
    left: 50%;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    bottom: 2px;
    width: 164px;
    height: 42px;
    transform: translateX(-50%);
    background: linear-gradient(135deg, #54bfff, #7a41ff);
    box-shadow: 0 0 14px rgba(84, 191, 255, 0.65);
    border-radius: 50%;
    background: radial-gradient(
      ellipse at center,
      rgba(43, 126, 211, 0.32) 0%,
      rgba(43, 126, 211, 0.14) 46%,
      rgba(43, 126, 211, 0) 74%
    );
    filter: blur(2.6px);
    animation: baseGlow 4.6s ease-in-out infinite;
    z-index: 1;
  }
  &::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 10px;
    width: 138px;
    height: 28px;
    transform: translateX(-50%);
    border-radius: 50%;
    border: 1px solid rgba(36, 116, 198, 0.6);
    box-shadow:
      inset 0 0 0 1px rgba(255, 255, 255, 0.58),
      0 0 22px rgba(42, 116, 196, 0.24);
    animation: basePulse 3.2s ease-in-out infinite;
    z-index: 4;
  }
}
.assistant-bot-antenna-left {
  left: 36px;
  transform: rotate(-14deg);
}
.assistant-bot-antenna-right {
  right: 36px;
  transform: rotate(14deg);
}
.assistant-bot-head {
.assistant-model-cut {
  position: relative;
  width: 132px;
  height: 178px;
  z-index: 6;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  transform-origin: center 84%;
  animation: avatarFloat 3.2s ease-in-out infinite;
}
.assistant-model-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center bottom;
  display: block;
  filter: saturate(1.03) drop-shadow(0 14px 18px rgba(22, 49, 79, 0.2));
  transition: filter 0.35s ease;
}
.assistant-model-fallback {
  width: 92px;
  height: 78px;
  border-radius: 28px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, #e8f1ff 100%);
  border: 1px solid rgba(0, 85, 212, 0.14);
  box-shadow: 0 16px 32px rgba(0, 85, 212, 0.14);
  height: 92px;
  border-radius: 24px;
  color: #fff;
  background: linear-gradient(145deg, rgba(31, 122, 114, 0.9), rgba(30, 91, 255, 0.9));
  border: 1px solid rgba(255, 255, 255, 0.3);
  box-shadow: 0 12px 24px rgba(31, 85, 173, 0.22);
  display: flex;
  align-items: center;
  justify-content: center;
}
.assistant-bot-head-glow {
  position: absolute;
  inset: 10px 16px auto;
  height: 20px;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(0, 85, 212, 0.16), transparent);
}
.assistant-bot-eye {
  position: absolute;
  top: 30px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: radial-gradient(circle, #8ef0ff 0%, #56c0ff 42%, #2869ff 100%);
  box-shadow: 0 0 12px rgba(72, 186, 255, 0.72);
  animation: robotBlink 3.2s infinite;
}
.assistant-bot-eye-left {
  left: 22px;
}
.assistant-bot-eye-right {
  right: 22px;
}
.assistant-bot-mouth {
.assistant-base {
  position: absolute;
  left: 50%;
  bottom: 16px;
  width: 22px;
  height: 4px;
  bottom: 8px;
  transform: translateX(-50%);
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(72, 186, 255, 0.2), rgba(72, 186, 255, 0.9), rgba(72, 186, 255, 0.2));
}
.assistant-bot-neck {
  width: 16px;
  height: 10px;
  border-radius: 0 0 10px 10px;
  background: linear-gradient(180deg, #dceaff, #bdd5ff);
  margin-top: -2px;
}
.assistant-bot-body {
  position: relative;
  width: 104px;
  height: 92px;
  margin-top: 2px;
  border-radius: 28px 28px 34px 34px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.98) 0%, #e3eeff 100%);
  border: 1px solid rgba(0, 85, 212, 0.14);
  box-shadow: 0 18px 36px rgba(0, 85, 212, 0.16);
  display: flex;
  align-items: center;
  justify-content: center;
}
.assistant-bot-arm {
  position: absolute;
  top: 18px;
  width: 16px;
  height: 44px;
  border-radius: 999px;
  background: linear-gradient(180deg, #eff5ff, #c7dbff);
  border: 1px solid rgba(0, 85, 212, 0.12);
}
.assistant-bot-arm-left {
  left: -10px;
  transform: rotate(16deg);
}
.assistant-bot-arm-right {
  right: -10px;
  transform: rotate(-16deg);
}
.assistant-bot-core {
  position: relative;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: $primary-blue;
  background: radial-gradient(circle, rgba(255, 255, 255, 1) 0%, #dae8ff 55%, #adc7ff 100%);
}
.assistant-bot-core-ring {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid rgba(88, 135, 255, 0.3);
  border-top-color: rgba(255, 96, 139, 0.85);
  border-right-color: rgba(79, 145, 255, 0.9);
  border: 1px solid rgba(36, 116, 198, 0.28);
  background: radial-gradient(
    ellipse at center,
    rgba(255, 255, 255, 0.94) 0%,
    rgba(81, 164, 233, 0.16) 58%,
    rgba(30, 91, 255, 0.06) 100%
  );
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2);
}
.assistant-status {
  position: relative;
  z-index: 1;
  margin-top: 14px;
  padding: 6px 12px;
  margin-top: 7px;
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-size: 11px;
  font-weight: 600;
  color: $deep-blue;
  background: rgba(255, 255, 255, 0.95);
@@ -4017,81 +5709,25 @@
}
.assistant-base {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  border-radius: 50%;
  border: 2px solid rgba(255, 93, 122, 0.22);
  background: radial-gradient(circle, rgba(255, 255, 255, 0.9) 0%, rgba(255, 111, 145, 0.1) 70%, transparent 100%);
}
.assistant-base-lg {
  width: 118px;
  height: 30px;
  pointer-events: none;
}
.assistant-base-md {
  bottom: 6px;
  width: 88px;
  height: 20px;
  border-color: rgba(255, 93, 122, 0.34);
  bottom: 15px;
  width: 104px;
  height: 22px;
  border-color: rgba(36, 116, 198, 0.48);
  animation: basePulse 2.8s ease-in-out infinite;
}
.assistant-base-sm {
  bottom: 11px;
  width: 54px;
  height: 10px;
  background: linear-gradient(90deg, rgba(255, 93, 122, 0.95), rgba(255, 173, 188, 0.9));
  bottom: 20px;
  width: 68px;
  height: 14px;
  background: linear-gradient(90deg, rgba(31, 122, 114, 0.82), rgba(45, 124, 255, 0.9));
  border: none;
  box-shadow: 0 0 18px rgba(255, 93, 122, 0.38);
}
@keyframes robotBlink {
  0%, 44%, 48%, 100% {
    transform: scaleY(1);
  }
  46% {
    transform: scaleY(0.14);
  }
}
@keyframes robotBlinkFast {
  0%, 100% {
    transform: scaleY(1);
  }
  50% {
    transform: scaleY(0.3);
  }
}
@keyframes robotTalk {
  0%, 100% {
    transform: translateX(-50%) scaleX(1);
  }
  50% {
    transform: translateX(-50%) scaleX(1.35);
  }
}
@keyframes corePulse {
  0%, 100% {
    transform: scale(1);
    filter: brightness(1);
  }
  50% {
    transform: scale(1.08);
    filter: brightness(1.08);
  }
}
@keyframes coreRotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
  box-shadow: 0 0 18px rgba(45, 124, 255, 0.34);
  animation: basePulse 2.2s ease-in-out infinite;
}
@keyframes orbitRotate {
@@ -4132,9 +5768,85 @@
  }
}
.assistant-base-lg {
  width: 142px;
  height: 32px;
  animation: basePulse 3.4s ease-in-out infinite;
  &::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 130px;
    height: 130px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: conic-gradient(
      from 180deg,
      transparent 0deg,
      rgba(36, 116, 198, 0.65) 48deg,
      transparent 114deg,
      rgba(36, 116, 198, 0.55) 212deg,
      transparent 286deg,
      rgba(31, 122, 114, 0.45) 334deg,
      transparent 360deg
    );
    -webkit-mask: radial-gradient(circle, transparent 61%, #000 62%, #000 68%, transparent 70%);
    mask: radial-gradient(circle, transparent 61%, #000 62%, #000 68%, transparent 70%);
    opacity: 0.62;
    animation: baseSpin 9s linear infinite;
  }
}
@keyframes avatarFloat {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-7px);
  }
}
@keyframes basePulse {
  0%,
  100% {
    transform: translateX(-50%) scale(1);
    opacity: 0.88;
  }
  50% {
    transform: translateX(-50%) scale(1.05);
    opacity: 0.98;
  }
}
@keyframes baseSpin {
  from {
    transform: translate(-50%, -50%) rotate(0deg);
  }
  to {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}
@keyframes baseGlow {
  0%,
  100% {
    transform: translateX(-50%) scaleX(1);
    opacity: 0.82;
  }
  50% {
    transform: translateX(-50%) scaleX(1.06);
    opacity: 0.96;
  }
}
.welcome-card {
  position: relative;
  padding: 14px 14px 12px;
  align-self: stretch;
  min-height: 206px;
  padding: 9px 10px 8px;
  border-radius: 16px;
  background:
    linear-gradient(#fff, #fff) padding-box,
@@ -4143,7 +5855,8 @@
  box-shadow: 0 16px 36px rgba(0, 85, 212, 0.12);
  &.compact {
    padding: 10px 12px;
    min-height: 160px;
    padding: 8px 9px 7px;
    border-radius: 12px;
    box-shadow: 0 8px 16px rgba(0, 85, 212, 0.07);
@@ -4152,8 +5865,8 @@
    }
    .welcome-title {
      font-size: 17px;
      line-height: 1.3;
      font-size: 16px;
      line-height: 1.25;
      br {
        display: none;
@@ -4161,65 +5874,69 @@
    }
    .welcome-desc {
      margin-top: 6px;
      font-size: 12px;
      line-height: 1.55;
      margin-top: 4px;
      font-size: 11px;
      line-height: 1.5;
    }
    .quick-prompt-list {
      margin-top: 10px;
      gap: 6px;
      margin-top: 8px;
      gap: 5px;
    }
    .quick-prompt-btn {
      padding: 8px 10px;
      font-size: 12px;
      padding: 7px 9px;
      font-size: 11px;
      border-radius: 7px;
    }
    .more-prompts-btn {
      margin-top: 8px;
      font-size: 12px;
      margin-top: 6px;
      font-size: 11px;
    }
  }
}
.welcome-eyebrow {
  font-size: 11px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 2px;
  color: rgba(0, 85, 212, 0.58);
  margin-bottom: 8px;
  margin-bottom: 5px;
}
.welcome-title {
  margin: 0;
  font-size: 26px;
  line-height: 1.2;
  font-size: 20px;
  line-height: 1.15;
  font-weight: 800;
  color: #172033;
  br {
    display: none;
  }
}
.welcome-desc {
  margin: 10px 0 0;
  font-size: 13px;
  line-height: 1.7;
  margin: 5px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: #5f6980;
}
.quick-prompt-list {
  display: grid;
  gap: 8px;
  margin-top: 14px;
  gap: 6px;
  margin-top: 8px;
}
.quick-prompt-btn {
  width: 100%;
  border: none;
  border-radius: 10px;
  padding: 11px 14px;
  border-radius: 9px;
  padding: 7px 10px;
  text-align: left;
  font-size: 13px;
  font-size: 12px;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
@@ -4267,14 +5984,14 @@
}
.more-prompts-btn {
  margin-top: 10px;
  padding: 0 12px;
  height: 32px;
  margin-top: 6px;
  padding: 0 10px;
  height: 26px;
  border: 1px solid rgba(208, 65, 81, 0.12);
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(255, 241, 245, 0.96));
  color: #d04151;
  font-size: 13px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
@@ -4289,21 +6006,6 @@
    border-color: transparent;
    color: #fff;
    box-shadow: 0 14px 24px rgba(138, 61, 246, 0.18);
  }
}
.hero-dot-grid {
  display: grid;
  grid-template-columns: repeat(14, 1fr);
  gap: 7px;
  padding: 0 18px 14px;
  span {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    border-radius: 2px;
    background: linear-gradient(135deg, rgba(255, 110, 138, 0.95), rgba(255, 190, 201, 0.55));
  }
}
@@ -4399,12 +6101,6 @@
  .welcome-title {
    font-size: 21px;
  }
  .hero-dot-grid {
    grid-template-columns: repeat(12, 1fr);
    gap: 6px;
    padding: 0 14px 12px;
  }
  .message-list {
src/components/Breadcrumb/index.vue
@@ -86,9 +86,10 @@
<style lang='scss' scoped>
.app-breadcrumb.el-breadcrumb {
  display: inline-block;
  display: inline-flex;
  align-items: center;
  font-size: 14px;
  line-height: 56px;
  line-height: 1;
  margin-left: 8px;
  :deep(.el-breadcrumb__inner) {
src/components/Dialog/FileList.vue
@@ -36,9 +36,16 @@
        <el-table-column v-if="showActions"
                         fixed="right"
                         label="操作"
                         :width="120"
                         :width="150"
                         align="center">
          <template #default="scope">
            <el-button link
                       type="primary"
                       size="small"
                       class="download-link"
                       @click="previewFile(scope.row.previewURL)">
              é¢„览
            </el-button>
            <el-button link
                       type="primary"
                       size="small"
@@ -58,9 +65,11 @@
      </el-table>
    </div>
  </el-dialog>
  <filePreview ref="filePreviewRef" />
</template>
<script setup>
import { ElMessage } from 'element-plus'
  import { ref, computed, getCurrentInstance, onMounted, watch } from "vue";
  import AttachmentUpload from "@/components/AttachmentUpload/file/index.vue";
  import {
@@ -68,6 +77,8 @@
    deleteAttachment,
    createAttachment,
  } from "@/api/basicData/storageAttachment.js";
  import filePreview from '@/components/filePreview/index.vue'
  const filePreviewRef = ref()
  const props = defineProps({
    visible: {
@@ -122,6 +133,15 @@
    isShow.value = false;
  };
  // é¢„览文件
  const previewFile = (url) => {
    if (url) {
      filePreviewRef.value.open(url)
    } else {
      ElMessage.warning('文件地址无效,无法预览')
    }
  }
  const handleUpload = () => {
    uploadDialogVisible.value = true;
  };
@@ -129,22 +149,23 @@
  const saveUpload = async () => {
    // æ£€æŸ¥æ˜¯å¦æœ‰æ–°ä¸Šä¼ çš„æ–‡ä»¶
    if (newFileList.value.length > 0) {
      try {
        await createAttachment({
          application: "file",
          recordType: props.recordType,
          recordId: props.recordId,
          storageBlobDTOs: [...newFileList.value, ...tableData.value],
        });
        newFileList.value = [];
        // åˆ·æ–°åˆ—表
        setList();
      } catch (error) {
        proxy?.$modal?.msgError("上传失败");
      }
      createAttachment({
        application: "file",
        recordType: props.recordType,
        recordId: props.recordId,
        storageBlobDTOs: [...newFileList.value, ...tableData.value],
      }).then((res) => {
        if (res && res.code === 200) {
          proxy?.$modal?.msgSuccess("上传成功");
          newFileList.value = [];
          // åˆ·æ–°åˆ—表
          setList();
        }
      }).finally(() => {
        uploadDialogVisible.value = false;
      })
    }
    uploadDialogVisible.value = false;
  };
  }
  const closeUpload = () => {
    newFileList.value = [];
@@ -152,13 +173,12 @@
  };
  const handleDelete = async (row, index) => {
    try {
      await deleteAttachment([row.storageAttachmentId]);
      proxy?.$modal?.msgSuccess("删除成功");
      setList();
    } catch (error) {
      proxy?.$modal?.msgError("删除失败");
    }
    deleteAttachment([row.storageAttachmentId]).then((res) => {
      if (res && res.code === 200) {
        proxy?.$modal?.msgSuccess("删除成功");
        setList();
      }
    })
  };
  const setList = () => {
@@ -166,9 +186,7 @@
      recordType: props.recordType,
      recordId: props.recordId,
    }).then(res => {
      if (res && res.data) {
        tableData.value = res.data || [];
      }
      tableData.value = (res && res.data) || [];
    });
  };
src/components/Hamburger/index.vue
@@ -1,8 +1,8 @@
<template>
  <div style="padding: 0 15px;" @click="toggleClick">
    <svg
      :class="{'is-active':isActive}"
      class="hamburger"
<template>
  <div class="hamburger-wrap" @click="toggleClick">
    <svg
      :class="{'is-active':isActive}"
      class="hamburger"
      viewBox="0 0 1024 1024"
      xmlns="http://www.w3.org/2000/svg"
      width="64"
@@ -28,15 +28,23 @@
}
</script>
<style scoped>
.hamburger {
  display: inline-block;
  vertical-align: middle;
  width: 20px;
  height: 20px;
}
.hamburger.is-active {
  transform: rotate(180deg);
}
<style scoped>
.hamburger-wrap {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hamburger {
  display: inline-block;
  vertical-align: middle;
  width: 22px;
  height: 22px;
}
.hamburger.is-active {
  transform: rotate(180deg);
}
</style>
src/components/HeaderSearch/index.vue
@@ -1,13 +1,13 @@
<template>
  <div class="header-search">
    <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
    <el-dialog
      v-model="show"
      width="600"
      @close="close"
      :show-close="false"
      append-to-body
    >
    <el-dialog
      v-model="show"
      width="600"
      @close="close"
      :show-close="true"
      append-to-body
    >
      <el-input
        v-model="search"
        ref="headerSearchSelectRef"
@@ -40,28 +40,51 @@
  </div>
</template>
<script setup>
import Fuse from 'fuse.js'
import { getNormalPath } from '@/utils/ruoyi'
import { isHttp } from '@/utils/validate'
import usePermissionStore from '@/store/modules/permission'
const search = ref('')
const options = ref([])
const searchPool = ref([])
const show = ref(false)
<script setup>
import Fuse from 'fuse.js'
import { getNormalPath } from '@/utils/ruoyi'
import { isHttp } from '@/utils/validate'
import usePermissionStore from '@/store/modules/permission'
const props = defineProps({
  keyword: {
    type: String,
    default: ''
  }
})
const search = ref('')
const options = ref([])
const searchPool = ref([])
const show = ref(false)
const fuse = ref(undefined)
const headerSearchSelectRef = ref(null)
const router = useRouter()
const routes = computed(() => usePermissionStore().defaultRoutes)
function click() {
  show.value = !show.value
  if (show.value) {
    headerSearchSelectRef.value && headerSearchSelectRef.value.focus()
    options.value = searchPool.value
  }
}
function click() {
  show.value = !show.value
  if (show.value) {
    syncSearchFromKeyword()
    nextTick(() => {
      headerSearchSelectRef.value && headerSearchSelectRef.value.focus()
    })
  }
}
function syncSearchFromKeyword() {
  search.value = props.keyword?.trim?.() ?? ''
  querySearch(search.value)
}
function open(keyword = props.keyword) {
  show.value = true
  search.value = keyword?.trim?.() ?? ''
  querySearch(search.value)
  nextTick(() => {
    headerSearchSelectRef.value && headerSearchSelectRef.value.focus()
  })
}
function close() {
  headerSearchSelectRef.value && headerSearchSelectRef.value.blur()
@@ -160,10 +183,14 @@
  searchPool.value = generateRoutes(routes.value)
})
watch(searchPool, (list) => {
  initFuse(list)
})
</script>
watch(searchPool, (list) => {
  initFuse(list)
})
defineExpose({
  open
})
</script>
<style lang='scss' scoped>
.header-search {
src/components/ProcessParamListDialog.vue
@@ -130,6 +130,7 @@
            </el-form-item>
            <el-form-item label="标准值">
              <el-input v-model="selectedParam.standardValue"
                        @input="val => onStandardValueInput(val, selectedParam)"
                        placeholder="请输入默认值" />
            </el-form-item>
            <el-form-item label="是否必填">
@@ -144,7 +145,8 @@
        </div>
      </div>
      <template #footer>
        <el-button type="primary" @click="handleParamSelectSubmit">确定</el-button>
        <el-button type="primary"
                   @click="handleParamSelectSubmit">确定</el-button>
        <el-button @click="selectParamDialogVisible = false">取消</el-button>
      </template>
    </el-dialog>
@@ -174,11 +176,13 @@
        <el-form-item label="标准值"
                      prop="standardValue">
          <el-input v-model="editParamForm.standardValue"
                    @input="val => onStandardValueInput(val, editParamForm)"
                    placeholder="请输入标准值" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="handleEditParamSubmit">确定</el-button>
        <el-button type="primary"
                   @click="handleEditParamSubmit">确定</el-button>
        <el-button @click="editParamDialogVisible = false">取消</el-button>
      </template>
    </el-dialog>
@@ -266,8 +270,32 @@
    paramFormat: "",
    unit: "",
  });
  const onStandardValueInput = (val, target) => {
    const data = target.value || target;
    const type = data.paramType || data.parameterType;
    if (type === 1) {
      // æ•°å€¼æ ¼å¼ï¼šä¸èƒ½è¾“入中文或英文字符
      data.standardValue = val.replace(/[a-zA-Z\u4e00-\u9fa5]/g, "");
    }
  };
  const editParamRules = ref({
    // standardValue: [{ required: true, message: "请输入标准值", trigger: "blur" }],
    standardValue: [
      {
        validator: (rule, value, callback) => {
          const type =
            editParamForm.value.paramType || editParamForm.value.parameterType;
          if (type === 1 && value) {
            if (/[a-zA-Z\u4e00-\u9fa5]/.test(value)) {
              return callback(new Error("数值格式不能包含中英文字符"));
            }
          }
          callback();
        },
        trigger: "blur",
      },
    ],
  });
  const editParamFormRef = ref(null);
src/components/PurchaseAIChatSidebar/index.vue
@@ -3,24 +3,8 @@
</template>
<script setup>
import { ShoppingCart } from '@element-plus/icons-vue'
import AIChatSidebar from '@/components/AIChatSidebar/index.vue'
import { purchaseAssistant } from '@/components/AIChatSidebar/assistants'
const assistants = [
  {
    key: 'purchase',
    label: '采购助理',
    title: '采购智能助理',
    tooltip: '采购智能助理',
    icon: ShoppingCart,
    apiBase: '/purchase-ai',
    storageKey: 'purchase_ai_chat_uuid',
    placeholder: '请输入采购问题... (Enter å‘送, Shift+Enter æ¢è¡Œ)',
    welcomeMessage: '你好',
    allowFileUpload: true,
    allowMultipleFileUpload: true,
    fileAnalyzeUrl: '/purchase-ai/analyze-files',
    emptySessionText: '暂无采购会话'
  }
]
const assistants = [purchaseAssistant]
</script>
src/components/filePreview/index.vue
@@ -78,9 +78,9 @@
  transformData: (workbookData) => workbookData,
});
// è®¡ç®—属性 - åˆ¤æ–­æ–‡ä»¶ç±»åž‹
// è®¡ç®—属性 - åˆ¤æ–­æ–‡ä»¶ç±»åž‹ï¼ˆæ”¯æŒURL带查询参数)
const isImage = computed(() => {
  const state = /\.(jpg|jpeg|png|gif)$/i.test(fileUrl.value);
  const state = /\.(jpg|jpeg|png|gif)(\?.*)?$/i.test(fileUrl.value);
  if (state) {
    imgUrl.value = fileUrl.value.replaceAll('word', 'img');
  }
@@ -89,23 +89,23 @@
const isPdf = computed(() => {
  console.log(fileUrl.value)
  return /\.pdf$/i.test(fileUrl.value);
  return /\.pdf(\?.*)?$/i.test(fileUrl.value);
});
const isDoc = computed(() => {
  return /\.(doc|docx)$/i.test(fileUrl.value);
  return /\.(doc|docx)(\?.*)?$/i.test(fileUrl.value);
});
const isXls = computed(() => {
  const state = /\.(xls|xlsx)$/i.test(fileUrl.value);
  const state = /\.(xls|xlsx)(\?.*)?$/i.test(fileUrl.value);
  if (state) {
    options.value.xls = /\.(xls)$/i.test(fileUrl.value);
    options.value.xls = /\.(xls)(\?.*)?$/i.test(fileUrl.value);
  }
  return state;
});
const isZipOrRar = computed(() => {
  return /\.(zip|rar)$/i.test(fileUrl.value);
  return /\.(zip|rar)(\?.*)?$/i.test(fileUrl.value);
});
const isSupported = computed(() => {
@@ -164,7 +164,7 @@
};
const open = (url) => {
  fileUrl.value = window.location.protocol+'//'+window.location.host+ url;
  fileUrl.value = url;
  dialogVisible.value = true;
};
const handleClose = () => {
src/layout/components/AppMain.vue
@@ -37,30 +37,29 @@
</script>
<style lang="scss" scoped>
.app-main {
  /* 50= navbar  50  */
  min-height: calc(100vh - 50px);
  width: 100%;
  position: relative;
  overflow: hidden;
  background: transparent;
}
.route-view-wrapper {
  width: 100%;
  height: 100%;
  padding: 120px 16px 24px 0;
}
.fixed-header + .app-main {
  padding-top: 0;
}
.hasTagsView {
  .app-main {
    /* 84 = navbar + tags-view = 50 + 34 */
    min-height: calc(100vh - 84px);
  }
.app-main {
  min-height: calc(100vh - var(--topbar-height));
  width: 100%;
  position: relative;
  overflow: visible;
  background: transparent;
}
.route-view-wrapper {
  width: 100%;
  height: 100%;
  padding: var(--content-gap);
  padding-top: 0;
}
.fixed-header + .app-main {
  padding-top: 0;
}
.hasTagsView {
  .app-main {
    min-height: calc(100vh - var(--topbar-height) - var(--tagsbar-height));
  }
  .fixed-header + .app-main {
    padding-top: 0;
src/layout/components/Navbar.vue
@@ -1,13 +1,35 @@
<template>
  <div class="navbar">
    <div>
      <hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container"
        @toggleClick="toggleSideBar" />
      <breadcrumb v-if="!settingsStore.topNav" id="breadcrumb-container" class="breadcrumb-container" />
    <div class="left-zone">
      <hamburger
        id="hamburger-container"
        :is-active="appStore.sidebar.opened"
        class="hamburger-container"
        @toggleClick="toggleSideBar"
      />
      <breadcrumb
        v-if="!settingsStore.topNav"
        id="breadcrumb-container"
        class="breadcrumb-container"
      />
    </div>
    <!--    <top-nav v-if="settingsStore.topNav" id="topmenu-container" class="topmenu-container" />-->
    <div class="center-zone">
      <el-icon class="search-icon" @click="openHeaderSearch"><Search /></el-icon>
      <el-input
        v-model="topSearchKeyword"
        placeholder="搜索菜单 / åŠŸèƒ½ / æ•°æ®"
        clearable
        @keyup.enter="openHeaderSearch"
      />
      <header-search
        ref="headerSearchRef"
        :keyword="topSearchKeyword"
        class="search-popup-trigger"
      />
    </div>
    <div class="right-menu">
      <!-- æ¶ˆæ¯é€šçŸ¥ -->
      <el-popover
        v-model:visible="notificationVisible"
        :width="500"
@@ -19,20 +41,26 @@
        <template #reference>
          <div class="notification-container right-menu-item hover-effect">
            <el-badge :value="unreadCount" :hidden="unreadCount === 0" class="notification-badge">
              <el-icon :size="20" style="cursor: pointer;">
              <el-icon :size="18">
                <Bell />
              </el-icon>
            </el-badge>
          </div>
        </template>
        <NotificationCenter
          @unreadCountChange="handleUnreadCountChange"
          ref="notificationCenterRef"
        />
        <NotificationCenter @unreadCountChange="handleUnreadCountChange" ref="notificationCenterRef" />
      </el-popover>
      <div class="right-menu-item hover-effect screenfull-container">
        <screenfull />
      </div>
      <div class="avatar-container">
        <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
          <div class="avatar-wrapper">
            <div class="user-summary">
              <div class="user-name">{{ userStore.nickName || userStore.name || "管理员" }}</div>
              <div class="user-role">{{ userStore.roleName || "系统用户" }}</div>
            </div>
            <img :src="userStore.avatar" class="user-avatar" />
            <el-icon><caret-bottom /></el-icon>
          </div>
@@ -56,261 +84,299 @@
</template>
<script setup>
import { ElMessageBox } from 'element-plus'
import { Bell } from '@element-plus/icons-vue'
import Breadcrumb from '@/components/Breadcrumb'
import TopNav from '@/components/TopNav'
import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect'
import HeaderSearch from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc'
import NotificationCenter from './NotificationCenter/index.vue'
import useAppStore from '@/store/modules/app'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
import { ElMessageBox } from "element-plus";
import { Bell, Search } from "@element-plus/icons-vue";
import Breadcrumb from "@/components/Breadcrumb";
import Hamburger from "@/components/Hamburger";
import Screenfull from "@/components/Screenfull";
import HeaderSearch from "@/components/HeaderSearch";
import NotificationCenter from "./NotificationCenter/index.vue";
import useAppStore from "@/store/modules/app";
import useUserStore from "@/store/modules/user";
import useSettingsStore from "@/store/modules/settings";
const appStore = useAppStore()
const userStore = useUserStore()
const settingsStore = useSettingsStore()
const notificationVisible = ref(false)
const notificationCenterRef = ref(null)
const unreadCount = ref(0)
const appStore = useAppStore();
const userStore = useUserStore();
const settingsStore = useSettingsStore();
const topSearchKeyword = ref("");
const headerSearchRef = ref(null);
const notificationVisible = ref(false);
const notificationCenterRef = ref(null);
const unreadCount = ref(0);
function toggleSideBar() {
  appStore.toggleSideBar()
  appStore.toggleSideBar();
}
// const redirect = ref(undefined)
// watch(route, (newRoute) => {
//   redirect.value = newRoute.query && newRoute.query.redirect
// }, { immediate: true })
function openHeaderSearch() {
  headerSearchRef.value?.open(topSearchKeyword.value);
}
function handleCommand(command) {
  switch (command) {
    case "setLayout":
      setLayout()
      break
      setLayout();
      break;
    case "logout":
      logout()
      break
      logout();
      break;
    default:
      break
      break;
  }
}
function logout() {
  ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    userStore.logOut().then(() => {
      location.href = '/index'
  ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      userStore.logOut().then(() => {
        location.href = "/index";
      });
    })
  }).catch(() => { })
    .catch(() => {});
}
const emits = defineEmits(['setLayout'])
const emits = defineEmits(["setLayout"]);
function setLayout() {
  emits('setLayout')
  emits("setLayout");
}
function toggleTheme() {
  settingsStore.toggleTheme()
}
// æ¶ˆæ¯é€šçŸ¥ç›¸å…³
function handleUnreadCountChange(count) {
  unreadCount.value = count
  unreadCount.value = count;
}
// ç»„件挂载时加载未读数量和定时刷新
let unreadCountTimer = null
let unreadCountTimer = null;
onMounted(() => {
  // å»¶è¿ŸåŠ è½½ï¼Œç¡®ä¿ç»„ä»¶å·²æ¸²æŸ“
  nextTick(() => {
    if (notificationCenterRef.value) {
      notificationCenterRef.value.loadUnreadCount()
      notificationCenterRef.value.loadUnreadCount();
    }
  })
  // å®šæ—¶åˆ·æ–°æœªè¯»æ•°é‡ï¼ˆæ¯30秒)
  });
  unreadCountTimer = setInterval(() => {
    if (notificationCenterRef.value) {
      notificationCenterRef.value.loadUnreadCount()
      notificationCenterRef.value.loadUnreadCount();
    }
  }, 30000)
})
  }, 30000);
});
// ç›‘听 popover æ˜¾ç¤ºçŠ¶æ€ï¼Œæ‰“å¼€æ—¶åŠ è½½æ¶ˆæ¯åˆ—è¡¨
watch(notificationVisible, (val) => {
  if (val && notificationCenterRef.value) {
    nextTick(() => {
      notificationCenterRef.value.loadMessages()
    })
      notificationCenterRef.value.loadMessages();
    });
  }
})
});
onUnmounted(() => {
  if (unreadCountTimer) {
    clearInterval(unreadCountTimer)
    clearInterval(unreadCountTimer);
  }
})
});
</script>
<style lang='scss' scoped>
.navbar {
  height: 56px;
  overflow: hidden;
  position: relative;
  background: var(--navbar-bg);
  border: 1px solid rgba(216, 225, 219, 0.9);
  border-radius: 22px;
  backdrop-filter: blur(18px);
  box-shadow: var(--shadow-sm);
  padding: 0 18px;
<style lang="scss" scoped>
.navbar {
  height: var(--topbar-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  background: rgba(255, 255, 255, 0.86);
  border: 1px solid rgba(148, 163, 184, 0.18);
  border-radius: var(--content-radius);
  backdrop-filter: blur(16px);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
  padding: 0 18px;
}
  .hamburger-container {
    line-height: 52px;
    height: 100%;
    float: left;
    cursor: pointer;
    transition: background 0.3s;
    -webkit-tap-highlight-color: transparent;
.left-zone {
  flex: 0 1 420px;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
}
    &:hover {
      background: var(--navbar-hover);
    }
  }
.hamburger-container {
  line-height: 36px;
  height: 36px;
  width: 36px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--navbar-text);
  .breadcrumb-container {
    float: left;
  }
  .topmenu-container {
    position: absolute;
    left: 50px;
  }
  .errLog-container {
    display: inline-block;
    vertical-align: top;
  }
  .right-menu {
    float: right;
    height: 100%;
    align-items: center;
    display: flex;
    &:focus {
      outline: none;
    }
    .right-menu-item {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 0 8px;
      height: 100%;
      font-size: 18px;
      color: var(--navbar-text);
      border-radius: 14px;
      &.hover-effect {
        cursor: pointer;
        transition: background 0.3s;
        &:hover {
          background: var(--navbar-hover);
        }
      }
      &.theme-switch-wrapper {
        display: flex;
        align-items: center;
        svg {
          transition: transform 0.3s;
          &:hover {
            transform: scale(1.15);
          }
        }
      }
    }
    .notification-container {
      margin-right: 12px;
      display: flex;
      align-items: center;
      cursor: pointer;
      .notification-badge {
        :deep(.el-badge__content) {
          border: none;
        }
      }
    }
    .avatar-container {
      margin-right: 4px;
      height: 100%;
      display: flex;
      align-items: center;
      :deep(.el-dropdown) {
        height: 100%;
        display: flex;
        align-items: center;
      }
      .avatar-wrapper {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        padding: 6px 10px 6px 6px;
        height: 44px;
        border-radius: 999px;
        background: rgba(247, 250, 248, 0.92);
        border: 1px solid var(--surface-border);
        .user-avatar {
          cursor: pointer;
          width: 34px;
          height: 34px;
          border-radius: 50px;
        }
        i {
          cursor: pointer;
          position: static;
          font-size: 12px;
        }
      }
    }
  &:hover {
    background: var(--navbar-hover);
  }
}
.breadcrumb-container {
  min-width: 0;
}
.center-zone {
  width: clamp(360px, 34vw, 560px);
  min-width: 320px;
  height: 38px;
  border-radius: 999px;
  border: 1px solid rgba(148, 163, 184, 0.24);
  background: rgba(248, 251, 255, 0.92);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 8px;
}
.search-icon {
  color: #5b86c9;
  cursor: pointer;
}
.center-zone :deep(.el-input__wrapper) {
  border: 0;
  box-shadow: none !important;
  background: transparent;
  padding: 0;
}
.center-zone :deep(.el-input__inner) {
  color: #334155;
  font-size: 13px;
}
.search-popup-trigger :deep(.search-icon) {
  color: #5b86c9;
  font-size: 16px;
  cursor: pointer;
}
.right-menu {
  height: 100%;
  align-items: center;
  display: flex;
  gap: 14px;
}
.right-menu-item {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--navbar-text);
  border-radius: 8px;
}
.hover-effect {
  cursor: pointer;
  transition: background 0.2s;
  &:hover {
    background: var(--navbar-hover);
  }
}
.notification-container,
.screenfull-container {
  width: 36px;
  height: 36px;
}
.notification-badge :deep(.el-badge__content) {
  border: none;
}
.screenfull-container :deep(.svg-icon) {
  width: 16px;
  height: 16px;
  color: var(--navbar-text);
}
.avatar-container {
  height: 100%;
  display: flex;
  align-items: center;
}
.avatar-container :deep(.el-dropdown) {
  height: 100%;
  display: flex;
  align-items: center;
}
.avatar-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 10px 4px 8px;
  height: 44px;
  border-radius: 22px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(148, 163, 184, 0.22);
}
.user-summary {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
}
.user-name {
  color: var(--text-primary);
  font-size: 13px;
  line-height: 1;
}
.user-role {
  color: var(--text-tertiary);
  font-size: 11px;
  line-height: 1;
}
.user-avatar {
  cursor: pointer;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(148, 163, 184, 0.3);
}
@media (max-width: 1200px) {
  .center-zone {
    display: none;
  }
  .user-summary {
    display: none;
  }
}
</style>
<style lang="scss">
.notification-popover {
  padding: 0 !important;
  border-radius: 20px !important;
  border: 1px solid var(--surface-border) !important;
  box-shadow: var(--shadow-md) !important;
.notification-popover {
  padding: 0 !important;
  border-radius: 16px !important;
  border: 1px solid rgba(148, 163, 184, 0.22) !important;
  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.12) !important;
  background: rgba(255, 255, 255, 0.94) !important;
  backdrop-filter: blur(16px);
  .el-popover__title {
    display: none;
  }
  .el-popover__body {
    padding: 0 !important;
  }
}
.el-badge__content.is-fixed{
  top: 12px;
.el-badge__content.is-fixed {
  top: 8px;
}
</style>
src/layout/components/NotificationCenter/index.vue
@@ -255,6 +255,7 @@
    flex-direction: column;
    width: 500px;
    padding: 16px;
    background: rgba(255, 255, 255, 0.92);
  }
  .popover-header {
@@ -264,12 +265,12 @@
    width: 100%;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid #f0f0f0;
    border-bottom: 1px solid var(--surface-border);
    .popover-title {
      font-size: 18px;
      font-weight: 500;
      color: #303133;
      color: var(--text-primary);
    }
  }
@@ -315,11 +316,11 @@
    .notification-item {
      display: flex;
      padding: 12px 0;
      border-bottom: 1px solid #f0f0f0;
      border-bottom: 1px solid rgba(148, 163, 184, 0.18);
      transition: background-color 0.3s;
      &:hover {
        background-color: #f5f7fa;
        background-color: #f8fbff;
      }
      &.read {
@@ -333,7 +334,7 @@
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: #f0f9ff;
        background-color: rgba(59, 130, 246, 0.12);
        border-radius: 50%;
        margin-right: 12px;
      }
@@ -345,13 +346,13 @@
        .notification-title {
          font-size: 14px;
          font-weight: 500;
          color: #303133;
          color: var(--text-primary);
          margin-bottom: 8px;
        }
        .notification-detail {
          font-size: 13px;
          color: #606266;
          color: var(--text-secondary);
          line-height: 1.5;
          margin-bottom: 8px;
          word-break: break-all;
@@ -359,7 +360,7 @@
        .notification-time {
          font-size: 12px;
          color: #909399;
          color: var(--text-tertiary);
        }
      }
@@ -375,7 +376,7 @@
  .pagination-wrapper {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid #f0f0f0;
    border-top: 1px solid var(--surface-border);
    display: flex;
    justify-content: center;
    padding-left: 0;
src/layout/components/Sidebar/Logo.vue
@@ -4,7 +4,7 @@
      <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
        <img :src="faviconUrl" class="sidebar-logo sidebar-favicon" alt="站点图标" />
      </router-link>
      <router-link v-else key="expand" class="sidebar-logo-link" to="/">
      <router-link v-else key="expand" class="sidebar-logo-link" :style="expandLogoLinkStyle" to="/">
        <img v-if="logoUrl" :src="logoUrl" class="sidebar-logo" @error="handleImageError" alt="公司Logo" />
        <h1 v-if="!logoUrl" class="sidebar-title">{{ title }}</h1>
      </router-link>
@@ -35,6 +35,14 @@
})
const logoUrl = ref('')
const expandLogoLinkStyle = computed(() => {
  if (!logoUrl.value) {
    return { '--logo-bg-image': 'none' }
  }
  const escaped = String(logoUrl.value).replace(/"/g, '\\"')
  return { '--logo-bg-image': `url("${escaped}")` }
})
const updateLogoUrl = () => {
  if (!cleanFactoryName.value) {
@@ -82,32 +90,63 @@
.sidebar-logo-container {
  position: relative;
  width: 100% !important;
  height: 56px !important;
  line-height: 56px;
  background: rgba(255, 255, 255, 0.78);
  border: 1px solid var(--surface-border);
  border-radius: 22px;
  text-align: center;
  height: 78px !important;
  line-height: 78px;
  background: transparent;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  text-align: left;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  box-shadow: none;
  backdrop-filter: none;
  transition: all 0.3s ease;
  .sidebar-logo-link {
    position: relative;
    isolation: isolate;
    height: 100%;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 18px 0 14px;
    padding: 0;
    &::before {
      content: "";
      position: absolute;
      inset: 0;
      background-image: var(--logo-bg-image);
      background-size: cover;
      background-position: center;
      opacity: 0.26;
      filter: blur(8px) saturate(0.9);
      transform: scale(1.06);
      pointer-events: none;
      z-index: 0;
    }
    &::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, rgba(16, 49, 89, 0.18), rgba(16, 49, 89, 0.08));
      pointer-events: none;
      z-index: 0;
    }
  }
  .sidebar-logo {
    width: auto;
    max-width: 250px;
    max-height: 50px;
    height: auto;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    padding: 6px 10px;
    vertical-align: middle;
    object-fit: contain;
    object-position: center;
    filter: none;
    display: block;
    position: relative;
    z-index: 1;
  }
  .sidebar-title {
@@ -119,23 +158,40 @@
    font-size: 14px;
    font-family: "Segoe UI", "PingFang SC", sans-serif;
    vertical-align: middle;
    position: relative;
    z-index: 1;
  }
  &.collapse {
    .sidebar-logo-link {
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      &::before,
      &::after {
        display: none;
      }
    }
    .sidebar-logo {
      max-width: 30px;
      max-height: 30px;
      width: calc(100% - 8px);
      height: calc(100% - 8px);
      max-width: none;
      max-height: none;
      padding: 4px;
      margin: 0 auto;
      filter: none;
      object-fit: contain;
      object-position: center;
    }
    .sidebar-favicon {
      width: 24px;
      height: 24px;
      max-width: 24px;
      max-height: 24px;
      width: calc(100% - 8px);
      height: calc(100% - 8px);
      max-width: none;
      max-height: none;
    }
  }
}
src/layout/components/Sidebar/SidebarItem.vue
@@ -1,17 +1,19 @@
<template>
  <div v-if="!item.hidden">
  <div v-if="!item.hidden" class="sidebar-item-wrapper">
    <template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
          <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"/>
          <template #title><span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span></template>
          <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" class="menu-icon"/>
          <template #title>
            <span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span>
          </template>
        </el-menu-item>
      </app-link>
    </template>
    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
      <template v-if="item.meta" #title>
        <svg-icon :icon-class="item.meta && item.meta.icon" />
        <svg-icon :icon-class="item.meta && item.meta.icon" class="menu-icon" />
        <span class="menu-title" :title="hasTitle(item.meta.title)">{{ item.meta.title }}</span>
      </template>
@@ -98,3 +100,59 @@
  }
}
</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;
  }
  :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; }
  }
}
</style>
src/layout/components/Sidebar/index.vue
@@ -1,142 +1,166 @@
<template>
  <div :class="{ 'has-logo': showLogo }"
       class="sidebar-container">
    <logo v-if="showLogo"
          :collapse="isCollapse" />
  <div :class="{ 'has-logo': showLogo }" class="sidebar-container">
    <logo v-if="showLogo" :collapse="isCollapse" />
    <el-scrollbar wrap-class="scrollbar-wrapper">
      <el-menu :default-active="activeMenu"
               :collapse="isCollapse"
               :background-color="getMenuBackground"
               :text-color="getMenuTextColor"
               :unique-opened="true"
               :active-text-color="theme"
               :collapse-transition="false"
               mode="vertical"
               :class="sideTheme">
        <sidebar-item v-for="(route, index) in sidebarRouters"
                      :key="route.path + index"
                      :item="route"
                      :base-path="route.path" />
      <el-menu
        :default-active="activeMenu"
        :collapse="isCollapse"
        :background-color="getMenuBackground"
        :text-color="getMenuTextColor"
        :unique-opened="true"
        :active-text-color="theme"
        :collapse-transition="false"
        mode="vertical"
        :class="sideTheme"
      >
        <sidebar-item
          v-for="(route, index) in sidebarRouters"
          :key="route.path + index"
          :item="route"
          :base-path="route.path"
        />
      </el-menu>
    </el-scrollbar>
  </div>
</template>
<script setup>
  import Logo from "./Logo";
  import SidebarItem from "./SidebarItem";
  import variables from "@/assets/styles/variables.module.scss";
  import useAppStore from "@/store/modules/app";
  import useSettingsStore from "@/store/modules/settings";
  import usePermissionStore from "@/store/modules/permission";
import Logo from "./Logo";
import SidebarItem from "./SidebarItem";
import useAppStore from "@/store/modules/app";
import useSettingsStore from "@/store/modules/settings";
import usePermissionStore from "@/store/modules/permission";
  const route = useRoute();
  const appStore = useAppStore();
  const settingsStore = useSettingsStore();
  const permissionStore = usePermissionStore();
const route = useRoute();
const appStore = useAppStore();
const settingsStore = useSettingsStore();
const permissionStore = usePermissionStore();
  const sidebarRouters = computed(() => permissionStore.sidebarRouters);
  const showLogo = computed(() => settingsStore.sidebarLogo);
  const sideTheme = computed(() => settingsStore.sideTheme);
  const theme = computed(() => settingsStore.theme);
  const isCollapse = computed(() => !appStore.sidebar.opened);
const sidebarRouters = computed(() => permissionStore.sidebarRouters);
const showLogo = computed(() => settingsStore.sidebarLogo);
const sideTheme = computed(() => settingsStore.sideTheme);
const theme = computed(() => settingsStore.theme);
const isCollapse = computed(() => !appStore.sidebar.opened);
  const getMenuBackground = computed(() => "var(--sidebar-bg)");
const getMenuBackground = computed(() => "var(--sidebar-bg)");
  const getMenuTextColor = computed(() => {
    if (settingsStore.isDark) {
      return "var(--sidebar-text)";
    }
    return sideTheme.value === "theme-dark"
      ? variables.menuText
      : variables.menuLightText;
  });
const getMenuTextColor = computed(() => "var(--sidebar-text)");
  const activeMenu = computed(() => {
    const { meta, path } = route;
    if (meta.activeMenu) {
      return meta.activeMenu;
    }
    return path;
  });
const activeMenu = computed(() => {
  const { meta, path } = route;
  if (meta.activeMenu) return meta.activeMenu;
  return path;
});
</script>
<style lang="scss" scoped>
  .sidebar-container {
    background-color: v-bind(getMenuBackground);
    border-radius: 22px;
    overflow: hidden;
.sidebar-container {
  background: transparent;
  border-radius: 0;
  overflow: hidden;
    .scrollbar-wrapper {
      background-color: v-bind(getMenuBackground);
  .scrollbar-wrapper {
    background: transparent;
  }
  .el-menu {
    border: none !important;
    height: 100%;
    width: 100% !important;
    border-radius: 0;
    background: transparent !important;
    .el-menu-item,
    .el-sub-menu__title {
      margin-bottom: 8px;
      border-radius: 14px;
      color: v-bind(getMenuTextColor);
      font-size: 14px;
      letter-spacing: 0;
      transition:
        transform 0.18s ease,
        background 0.2s ease,
        box-shadow 0.2s ease,
        color 0.2s ease;
      border: none !important;
      display: flex;
      align-items: center;
      &:hover {
        background: linear-gradient(128deg, rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.28), rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.08)) !important;
        transform: translate3d(2px, 0, 0);
      }
    }
    .el-menu {
      border: none;
      height: 100%;
      width: 100% !important;
      border-radius: 22px;
    .el-menu-item {
      color: var(--sidebar-text);
      .el-menu-item,
      .el-sub-menu__title {
        margin-bottom: 6px;
      &.is-active {
        background: var(--menu-active-bg, linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3))) !important;
        color: var(--menu-active-text) !important;
        font-weight: 500;
        border-radius: 14px;
        color: v-bind(getMenuTextColor);
        box-shadow: var(--menu-active-glow, 0 10px 24px rgba(var(--el-color-primary-rgb, 37, 99, 235), 0.34));
        &:hover {
          background-color: var(--menu-hover, rgba(0, 0, 0, 0.06)) !important;
          border-radius: 14px;
        .svg-icon {
          color: var(--menu-active-text) !important;
        }
      }
    }
      .el-menu-item {
        &.is-active {
          color: v-bind(theme);
          background-color: var(--menu-active-bg, rgba(0, 0, 0, 0.06)) !important;
          font-weight: 600;
        }
      }
    .el-sub-menu__title {
      color: v-bind(getMenuTextColor);
    }
      .el-sub-menu__title {
        color: v-bind(getMenuTextColor);
      }
    :deep(.el-sub-menu__icon-arrow) {
      display: inline-flex !important;
      align-items: center;
      justify-content: center;
      width: 14px;
      height: 14px;
      margin-top: -7px;
      right: 14px;
      font-size: 14px !important;
      color: currentColor !important;
      opacity: 0.7;
      transition: transform 0.2s ease, opacity 0.2s ease;
    }
      :deep(.el-sub-menu.is-active > .el-sub-menu__title) {
        color: v-bind(theme) !important;
        font-weight: 600;
        background-color: var(--menu-active-bg, rgba(0, 0, 0, 0.06)) !important;
        border-radius: 14px;
        margin: 0 10px 6px !important;
        // width: calc(100% - 20px) !important;
        padding-left: 10px !important;
        padding-right: 10px !important;
        box-sizing: border-box;
        overflow: hidden;
        background-clip: padding-box;
      }
    :deep(.el-sub-menu.is-opened .el-sub-menu__icon-arrow) {
      transform: rotate(180deg);
    }
      :deep(.el-menu-item.is-active) {
        margin: 0 10px 6px !important;
        width: calc(100% - 20px) !important;
        padding-left: 10px !important;
        padding-right: 10px !important;
        box-sizing: border-box;
        overflow: hidden;
        background-clip: padding-box;
        border-radius: 14px;
      }
    :deep(.el-sub-menu.is-active > .el-sub-menu__title) {
      color: var(--menu-active-text) !important;
      font-weight: 500;
      border-radius: 12px;
      margin: 0 12px 6px !important;
      padding-left: 14px !important;
      padding-right: 34px !important;
      box-sizing: border-box;
      overflow: hidden;
      background-clip: padding-box;
      background: var(--menu-active-bg) !important;
      box-shadow: var(--menu-active-glow);
      border: none !important;
    }
      :deep(.el-sub-menu.is-active > .el-sub-menu__title .menu-title),
      :deep(.el-sub-menu.is-active > .el-sub-menu__title .svg-icon),
      :deep(.el-menu-item.is-active .menu-title),
      :deep(.el-menu-item.is-active .svg-icon) {
        color: v-bind(theme) !important;
      }
    :deep(.el-menu-item.is-active) {
      margin: 0 12px 6px !important;
      width: calc(100% - 24px) !important;
      padding-left: 14px !important;
      padding-right: 34px !important;
      box-sizing: border-box;
      overflow: hidden;
      background-clip: padding-box;
      border-radius: 12px;
    }
      :deep(.el-sub-menu__title:hover),
      :deep(.el-menu-item:hover) {
        border-radius: 14px;
      }
    :deep(.el-sub-menu.is-active > .el-sub-menu__title .menu-title),
    :deep(.el-sub-menu.is-active > .el-sub-menu__title .svg-icon),
    :deep(.el-menu-item.is-active .menu-title) {
      color: var(--menu-active-text) !important;
    }
  }
}
</style>
src/layout/components/TagsView/ScrollPane.vue
@@ -100,8 +100,8 @@
  :deep(.el-scrollbar__bar) {
    bottom: 0px;
  }
  :deep(.el-scrollbar__wrap) {
    height: 42px;
  }
}
</style>
  :deep(.el-scrollbar__wrap) {
    height: var(--tagsbar-height);
  }
}
</style>
src/layout/components/TagsView/index.vue
@@ -259,20 +259,20 @@
<style lang="scss" scoped>
.tags-view-container {
  height: 42px;
  height: var(--tagsbar-height);
  width: 100%;
  margin-top: 10px;
  padding: 4px 10px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(216, 225, 219, 0.92);
  border-radius: 20px;
  backdrop-filter: blur(18px);
  box-shadow: var(--shadow-sm);
  margin-top: 0;
  padding: 0 2px;
  background: transparent;
  border: none;
  border-radius: 0;
  backdrop-filter: none;
  box-shadow: none;
  .tags-view-wrapper {
    display: flex;
    align-items: center;
    min-height: 42px;
    min-height: var(--tagsbar-height);
    .tags-view-item {
      display: inline-flex;
@@ -280,29 +280,29 @@
      justify-content: center;
      position: relative;
      cursor: pointer;
      height: 34px;
      height: 30px;
      line-height: 1;
      color: var(--tags-item-text, #4E5463);
      background: var(--tags-item-bg, #E5E7EA);
      border: 1px solid var(--tags-item-border, #d8dce5);
      border-radius: 999px;
      padding: 0 16px;
      padding: 0 14px;
      font-size: 12px;
      margin-right: 8px;
      margin-right: 6px;
      flex-shrink: 0;
      gap: 6px;
      transition: all 0.24s ease;
      &:hover {
        background: var(--tags-item-hover, #eee);
        border-color: rgba(31, 122, 114, 0.18);
        border-color: rgba(96, 165, 250, 0.36);
      }
      &.active {
        background-color: #FFFFFF !important;
        color: var(--el-color-primary);
        box-shadow: 0 10px 24px rgba(31, 122, 114, 0.12);
        border-color: rgba(31, 122, 114, 0.2) !important;
        background-image: linear-gradient(132deg, rgba(47, 128, 255, 0.95), rgba(56, 189, 248, 0.9));
        color: #fff;
        box-shadow: 0 10px 20px rgba(37, 99, 235, 0.22);
        border-color: rgba(147, 197, 253, 0.72) !important;
      }
    }
  }
src/layout/index.vue
@@ -7,21 +7,22 @@
         @click="handleClickOutside" />
    <sidebar v-if="!sidebar.hide"
             class="sidebar-container" />
    <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }"
         class="main-container">
      <div :class="{ 'fixed-header': fixedHeader }">
    <div :class="{ hasTagsView: showTagsView, sidebarHide: sidebar.hide }"
         class="main-container main-layout">
      <div :class="{ 'fixed-header': fixedHeader, 'with-tags': showTagsView }">
        <navbar @setLayout="setLayout" />
        <tags-view v-if="needTagsView" />
        <tags-view v-if="showTagsView" />
      </div>
      <app-main />
      <settings ref="settingRef" />
    </div>
    <AIChatSidebar v-if="aiEnabled" />
    <AIChatSidebar v-if="showGlobalAiChat" />
  </div>
</template>
<script setup>
  import { useWindowSize } from "@vueuse/core";
  import { useRoute } from "vue-router";
  import Sidebar from "./components/Sidebar/index.vue";
  import { AppMain, Navbar, Settings, TagsView } from "./components";
  import AIChatSidebar from "@/components/AIChatSidebar/index.vue";
@@ -30,16 +31,24 @@
  import useAppStore from "@/store/modules/app";
  import useUserStore from "@/store/modules/user";
  import useSettingsStore from "@/store/modules/settings";
  import useTagsViewStore from "@/store/modules/tagsView";
  const settingsStore = useSettingsStore();
  const tagsViewStore = useTagsViewStore();
  const userStore = useUserStore();
  const route = useRoute();
  const theme = computed(() => settingsStore.theme);
  const sideTheme = computed(() => settingsStore.sideTheme);
  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 fixedHeader = computed(() => settingsStore.fixedHeader);
  const aiEnabled = computed(() => Number(userStore.aiEnabled) === 1);
  const showGlobalAiChat = computed(() => {
    const isIndustrialBrainRoute = String(route.path || "").startsWith("/ai-industrial-brain");
    return !isIndustrialBrainRoute && aiEnabled.value;
  });
  const classObj = computed(() => ({
    hideSidebar: !sidebar.value.opened,
@@ -81,19 +90,16 @@
<style lang="scss" scoped>
  @import "@/assets/styles/mixin.scss";
  @import "@/assets/styles/variables.module.scss";
  .app-wrapper {
    @include clearfix;
    position: relative;
    height: 100%;
    min-height: 100%;
    width: 100%;
    background: radial-gradient(
        circle at top,
        rgba(223, 232, 226, 0.95),
        transparent 32%
      ),
      linear-gradient(180deg, #f7faf8 0%, var(--app-bg) 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%),
      linear-gradient(165deg, #f3f7fc 0%, #eef5ff 56%, #f8fbff 100%);
    &.mobile.openSidebar {
      position: fixed;
@@ -102,8 +108,7 @@
  }
  .drawer-bg {
    background: #000;
    opacity: 0.3;
    background: rgba(15, 23, 42, 0.22);
    width: 100%;
    top: 0;
    height: 100%;
@@ -111,26 +116,46 @@
    z-index: 999;
  }
  .fixed-header {
    position: fixed;
    top: 0px;
    padding-top: 12px;
    right: 16px;
    z-index: 9;
    width: calc(100% - #{$base-sidebar-width} - 32px);
    transition: width 0.28s, right 0.28s;
    padding-bottom: 8px;
    background-color: #f3f6f4;
  }
  .hideSidebar .fixed-header {
    width: calc(100% - 100px);
  .main-layout {
    min-height: 100vh;
    margin-left: var(--sidebar-width);
    transition: margin-left 0.25s ease;
    display: flex;
    flex-direction: column;
  }
  .sidebarHide .fixed-header {
    width: calc(100% - 32px);
  .fixed-header {
    position: sticky;
    top: 0;
    z-index: var(--layout-header-z);
    width: 100%;
    padding: 8px var(--content-gap) 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: transparent;
    backdrop-filter: none;
  }
  .fixed-header.with-tags {
    padding-bottom: 6px;
  }
  .hideSidebar .fixed-header {
    width: 100%;
  }
  .hideSidebar .main-layout {
    margin-left: var(--sidebar-collapsed-width);
  }
  .mobile .fixed-header {
    width: 100%;
    padding: 8px 10px 0;
  }
  .mobile .main-layout,
  .sidebarHide.main-layout {
    margin-left: 0;
  }
</style>
src/plugins/download.js
@@ -82,6 +82,16 @@
  saveAs(text, name, opts) {
    saveAs(text, name, opts);
  },
  byUrl(url, filename) {
    // å°†URL中的preview替换成download
    const downloadUrl = url.replace(/preview/g, 'download')
    const link = document.createElement('a')
    link.href = downloadUrl
    link.download = filename || ''
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  },
  async printErrMsg(data) {
    const resText = await data.text();
    const rspObj = JSON.parse(resText);
src/router/index.js
@@ -47,20 +47,6 @@
    component: () => import("@/views/register"),
    hidden: true,
  },
  // ç³»ç»Ÿæž¶æž„图
  // {
  //   path: "/system-architecture",
  //   component: Layout,
  //   redirect: "/system-architecture/index",
  //   children: [
  //     {
  //       path: "index",
  //       component: () => import("@/views/systemArchitecture/index.vue"),
  //       name: "SystemArchitecture",
  //       meta: { title: "系统架构图", icon: "tree" },
  //     },
  //   ],
  // },
  {
    path: "/:pathMatch(.*)*",
    component: () => import("@/views/error/404"),
@@ -85,6 +71,32 @@
      },
    ],
  },
  // ç³»ç»Ÿæž¶æž„图
  {
    path: "/system-architecture",
    component: Layout,
    redirect: "/system-architecture/index",
    children: [
      {
        path: "index",
        component: () => import("@/views/systemArchitecture/index.vue"),
        name: "SystemArchitecture",
        meta: { title: "系统架构图", icon: "tree" },
      },
    ],
  },
  {
    path: "/ai-industrial-brain",
    component: Layout,
    children: [
      {
        path: "index",
        component: () => import("@/views/aiIndustrialBrain/index.vue"),
        name: "AiIndustrialBrain",
        meta: { title: "AI工业大脑", icon: "skill" },
      },
    ],
  },
  {
    path: "/user",
    component: Layout,
@@ -105,20 +117,6 @@
    hidden: true,
    name: "DeviceInfo",
    meta: { title: "设备信息", icon: "monitor" },
  },
  // æ·»åŠ é¡¹ç›®è¯¦æƒ…é¡µé¢è·¯ç”±é…ç½®
  {
    path: "/oaSystem/projectManagement/projectDetail",
    component: Layout,
    hidden: true,
    children: [
      {
        path: ":projectId",
        component: () => import("@/views/oaSystem/projectManagement/projectDetail.vue"),
        name: "ProjectDetail",
        meta: { title: "项目详情", activeMenu: "/oaSystem/projectManagement" },
      },
    ],
  },
  {
    path: "/projectManagement/Management/detail",
@@ -143,12 +141,6 @@
  //   meta: { title: "财务管理", icon: "money" },
  //   children: [
  //     {
  //       path: "general-ledger",
  //       component: () => import("@/views/financialManagement/generalLedger/index.vue"),
  //       name: "GeneralLedger",
  //       meta: { title: "总帐科目" },
  //     },
  //     {
  //       path: "sales-out",
  //       component: () => import("@/views/financialManagement/receivable/salesOut.vue"),
  //       name: "SalesOut",
@@ -160,12 +152,7 @@
  //       name: "SalesReturn",
  //       meta: { title: "销售退货" },
  //     },
  //     {
  //       path: "receivable-reconciliation",
  //       component: () => import("@/views/financialManagement/receivable/reconciliation.vue"),
  //       name: "ReceivableReconciliation",
  //       meta: { title: "应收对账" },
  //     },
  //
  //     {
  //       path: "invoice-apply",
  //       component: () => import("@/views/financialManagement/receivable/invoiceApply.vue"),
@@ -185,16 +172,22 @@
  //       meta: { title: "收款单" },
  //     },
  //     {
  //       path: "receivable-reconciliation",
  //       component: () => import("@/views/financialManagement/receivable/reconciliation.vue"),
  //       name: "ReceivableReconciliation",
  //       meta: { title: "应收对账" },
  //     },
  //     {
  //       path: "purchase-in",
  //       component: () => import("@/views/financialManagement/payable/purchaseIn.vue"),
  //       name: "PurchaseIn",
  //       meta: { title: "采购入库" },
  //     },
  //     {
  //       path: "payable-reconciliation",
  //       component: () => import("@/views/financialManagement/payable/reconciliation.vue"),
  //       name: "PayableReconciliation",
  //       meta: { title: "应付对账" },
  //       path: "purchase-return",
  //       component: () => import("@/views/financialManagement/payable/purchaseReturn.vue"),
  //       name: "PurchaseReturn",
  //       meta: { title: "采购退货" },
  //     },
  //     {
  //       path: "input-invoice",
@@ -208,11 +201,18 @@
  //       name: "PaymentApply",
  //       meta: { title: "付款申请" },
  //     },
  //
  //     {
  //       path: "payment",
  //       component: () => import("@/views/financialManagement/payable/payment.vue"),
  //       name: "Payment",
  //       meta: { title: "付款单" },
  //     },
  //     {
  //       path: "payable-reconciliation",
  //       component: () => import("@/views/financialManagement/payable/reconciliation.vue"),
  //       name: "PayableReconciliation",
  //       meta: { title: "应付对账" },
  //     },
  //     {
  //       path: "fixed-assets",
@@ -227,6 +227,12 @@
  //       meta: { title: "无形资产" },
  //     },
  //     {
  //       path: "general-ledger",
  //       component: () => import("@/views/financialManagement/generalLedger/index.vue"),
  //       name: "GeneralLedger",
  //       meta: { title: "总帐科目" },
  //     },
  //     {
  //       path: "voucher",
  //       component: () => import("@/views/financialManagement/voucher/index.vue"),
  //       name: "Voucher",
src/settings.js
@@ -6,7 +6,7 @@
  /**
   * ä¾§è¾¹æ ä¸»é¢˜ æ·±è‰²ä¸»é¢˜theme-dark,浅色主题theme-light
   */
  sideTheme: 'theme-light',
  sideTheme: 'theme-dark',
  /**
   * æ˜¯å¦ç³»ç»Ÿå¸ƒå±€é…ç½®
   */
@@ -39,7 +39,7 @@
  /**
   * ä¸»é¢˜æ¨¡å¼ auto跟随系统,light浅色,dark深色
   */
  darkMode: "auto",
  darkMode: "light",
  /**
   * @type {string | array} 'production' | ['production', 'development']
src/store/modules/permission.js
@@ -44,17 +44,18 @@
            const defaultData = JSON.parse(JSON.stringify(rawRoutes))
            const sidebarRoutes = filterAsyncRouter(sdata)
            const rewriteRoutes = filterAsyncRouter(rdata, false, true)
            const defaultRoutes = filterAsyncRouter(defaultData)
            const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
            asyncRoutes.forEach(route => { router.addRoute(route) })
            this.setRoutes(rewriteRoutes)
            // å°†è´¢åŠ¡ç®¡ç†è·¯ç”±åˆå¹¶åˆ°ä¾§è¾¹æ 
            this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
            this.setDefaultRoutes(sidebarRoutes)
            this.setTopbarRoutes(defaultRoutes)
            resolve(rewriteRoutes)
          })
        })
            const defaultRoutes = filterAsyncRouter(defaultData)
            const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
            asyncRoutes.forEach(route => { router.addRoute(route) })
            this.setRoutes(rewriteRoutes)
            const constantSidebarRoutes = filterAiFeatureRoutes(constantRoutes, aiEnabled)
            // å°†è´¢åŠ¡ç®¡ç†è·¯ç”±åˆå¹¶åˆ°ä¾§è¾¹æ 
            this.setSidebarRouters(constantSidebarRoutes.concat(sidebarRoutes))
            this.setDefaultRoutes(sidebarRoutes)
            this.setTopbarRoutes(defaultRoutes)
            resolve(rewriteRoutes)
          })
        })
      }
    }
  })
@@ -118,7 +119,7 @@
  })
}
function filterChildren(childrenMap, lastRouter = false) {
function filterChildren(childrenMap, lastRouter = false) {
  var children = []
  childrenMap.forEach(el => {
    el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path
@@ -128,11 +129,11 @@
      children.push(el)
    }
  })
  return children
}
// åŠ¨æ€è·¯ç”±éåŽ†ï¼ŒéªŒè¯æ˜¯å¦å…·å¤‡æƒé™
export function filterDynamicRoutes(routes) {
  return children
}
// åŠ¨æ€è·¯ç”±éåŽ†ï¼ŒéªŒè¯æ˜¯å¦å…·å¤‡æƒé™
export function filterDynamicRoutes(routes) {
  const res = []
  routes.forEach(route => {
    if (route.permissions) {
src/store/modules/user.js
@@ -7,14 +7,14 @@
const useUserStore = defineStore(
  'user',
  {
    state: () => ({
      token: getToken(),
      id: '',
      name: '',
      avatar: '',
      roles: [],
      permissions: [],
      aiEnabled: 0
    state: () => ({
      token: getToken(),
      id: '',
      name: '',
      avatar: '',
      roles: [],
      permissions: [],
      aiEnabled: 0
    }),
    actions: {
      // ç™»å½•
@@ -25,8 +25,13 @@
        const uuid = userInfo.uuid
        return new Promise((resolve, reject) => {
          login(username, password, code, uuid).then(res => {
            setToken(res.token)
            this.token = res.token
            const token = res?.token || res?.data?.token
            if (!token) {
              reject(new Error('未获取到登录令牌'))
              return
            }
            setToken(token)
            this.token = token
            resolve()
          }).catch(error => {
            reject(error)
@@ -47,7 +52,8 @@
      getInfo() {
        return new Promise((resolve, reject) => {
          getInfo().then(res => {
            const user = res.user
            res  = res.data
            const user = res.user || {}
            let avatar = user.avatar || ""
            avatar = import.meta.env.VITE_APP_BASE_API + '/profile/' + avatar
            if (res.roles && res.roles.length > 0) { // éªŒè¯è¿”回的roles是否是一个非空数组
@@ -56,34 +62,34 @@
            } else {
              this.roles = ['ROLE_DEFAULT']
            }
            this.id = user.userId
            this.name = user.userName
            this.id = user.userId || ''
            this.name = user.userName || ''
            this.avatar = avatar
            this.currentFactoryName = user.currentFactoryName
            this.nickName = user.nickName
            this.roleName = user.roles[0].roleName
            this.currentDeptId = user.tenantId
            this.currentLoginTime = this.getCurrentTime()
            this.aiEnabled = Number(res.aiEnabled) === 1 ? 1 : 0
            resolve(res)
          }).catch(error => {
            reject(error)
          })
        })
            this.currentFactoryName = user.currentFactoryName || ''
            this.nickName = user.nickName || ''
            this.roleName = Array.isArray(user.roles) && user.roles.length > 0 ? (user.roles[0].roleName || '') : ''
            this.currentDeptId = user.tenantId || ''
            this.currentLoginTime = this.getCurrentTime()
            this.aiEnabled = Number(res.aiEnabled) === 1 ? 1 : 0
            resolve(res)
          }).catch(error => {
            reject(error)
          })
        })
      },
      // é€€å‡ºç³»ç»Ÿ
      logOut() {
        return new Promise((resolve, reject) => {
          logout(this.token).then(() => {
            this.token = ''
            this.roles = []
            this.permissions = []
            this.aiEnabled = 0
            removeToken()
            resolve()
          }).catch(error => {
            reject(error)
          })
            this.token = ''
            this.roles = []
            this.permissions = []
            this.aiEnabled = 0
            removeToken()
            resolve()
          }).catch(error => {
            reject(error)
          })
        })
      },
      // ç™»å½•校验
@@ -104,8 +110,13 @@
        const password = userInfo.password
        return new Promise((resolve, reject) => {
          loginCheckFactory(username, password).then(res => {
            setToken(res.token)
            this.token = res.token
            const token = res?.token || res?.data?.token
            if (!token) {
              reject(new Error('未获取到登录令牌'))
              return
            }
            setToken(token)
            this.token = token
            resolve()
          }).catch(error => {
            reject(error)
@@ -116,10 +127,15 @@
        return new Promise((resolve, reject) => {
          tideLogin(code)
              .then((res) => {
                setToken(res.token);
                this.token = res.token
                const token = res?.token || res?.data?.token
                if (!token) {
                  reject(new Error('未获取到登录令牌'))
                  return
                }
                setToken(token);
                this.token = token
                Vue.prototype.uploadHeader = {
                  Authorization: "Bearer " + res.token,
                  Authorization: "Bearer " + token,
                };
                resolve();
              })
src/utils/request.js
@@ -21,11 +21,12 @@
})
// request拦截器
service.interceptors.request.use(config => {
service.interceptors.request.use(config => {
  config.headers = config.headers || {}
  // æ˜¯å¦éœ€è¦è®¾ç½® token
  const isToken = (config.headers || {}).isToken === false
  const isToken = config.headers.isToken === false
  // æ˜¯å¦éœ€è¦é˜²æ­¢æ•°æ®é‡å¤æäº¤
  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  const isRepeatSubmit = config.headers.repeatSubmit === false
  if (getToken() && !isToken) {
    config.headers['Authorization'] = 'Bearer ' + getToken() // è®©æ¯ä¸ªè¯·æ±‚携带自定义token è¯·æ ¹æ®å®žé™…情况自行修改
  }
@@ -66,23 +67,27 @@
    }
  }
  return config
}, error => {
    console.log(error)
    Promise.reject(error)
})
}, error => {
    console.log(error)
    return Promise.reject(error)
})
// å“åº”拦截器
service.interceptors.response.use(res => {
    // æœªè®¾ç½®çŠ¶æ€ç åˆ™é»˜è®¤æˆåŠŸçŠ¶æ€
    const code = res.data.code || 200
    const code = res.data.code || 200
    const handleAuthError = (res.config && res.config.headers && res.config.headers.handleAuthError) !== false
    // èŽ·å–é”™è¯¯ä¿¡æ¯
    const msg = errorCode[code] || res.data.msg || errorCode['default']
    // äºŒè¿›åˆ¶æ•°æ®åˆ™ç›´æŽ¥è¿”回
    if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {
      return res.data
    }
    if (code === 401) {
      if (!isRelogin.show) {
    if (code === 401) {
      if (!handleAuthError) {
        return Promise.reject(new Error(msg))
      }
      if (!isRelogin.show) {
        isRelogin.show = true
        ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
          isRelogin.show = false
src/utils/theme.js
@@ -1,29 +1,44 @@
// å¤„理主题样式
export function handleThemeStyle(theme) {
    document.documentElement.style.setProperty('--el-color-primary', theme)
    const primary = normalizeHex(theme)
    const [r, g, b] = hexToRgb(primary)
    const light2 = getLightColor(primary, 0.2)
    const light3 = getLightColor(primary, 0.3)
    const light5 = getLightColor(primary, 0.5)
    document.documentElement.style.setProperty('--el-color-primary', primary)
    document.documentElement.style.setProperty('--el-color-primary-rgb', `${r}, ${g}, ${b}`)
    for (let i = 1; i <= 9; i++) {
        document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(theme, i / 10)}`)
        document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, `${getLightColor(primary, i / 10)}`)
    }
    for (let i = 1; i <= 9; i++) {
        document.documentElement.style.setProperty(`--el-color-primary-dark-${i}`, `${getDarkColor(theme, i / 10)}`)
        document.documentElement.style.setProperty(`--el-color-primary-dark-${i}`, `${getDarkColor(primary, i / 10)}`)
    }
    // ç³»ç»Ÿä¸»é¢˜è”动到侧边栏选中态与高亮
    document.documentElement.style.setProperty('--menu-active-bg', `linear-gradient(135deg, ${primary} 0%, ${light3} 100%)`)
    document.documentElement.style.setProperty('--menu-active-glow', `0 10px 24px rgba(${r}, ${g}, ${b}, 0.32)`)
    document.documentElement.style.setProperty('--menu-hover', `rgba(${r}, ${g}, ${b}, 0.2)`)
    document.documentElement.style.setProperty('--accent-primary', primary)
    document.documentElement.style.setProperty('--accent-light', light2)
    document.documentElement.style.setProperty('--accent-lighter', light5)
}
// hex颜色转rgb颜色
export function hexToRgb(str) {
    str = str.replace('#', '')
    let hexs = str.match(/../g)
    str = normalizeHex(str).replace('#', '')
    const hexs = str.match(/../g) || ['40', '9e', 'ff']
    for (let i = 0; i < 3; i++) {
        hexs[i] = parseInt(hexs[i], 16)
    }
    return hexs
}
// rgb颜色转Hex颜色
// rgb颜色转hex颜色
export function rgbToHex(r, g, b) {
    let hexs = [r.toString(16), g.toString(16), b.toString(16)]
    const hexs = [r.toString(16), g.toString(16), b.toString(16)]
    for (let i = 0; i < 3; i++) {
        if (hexs[i].length == 1) {
        if (hexs[i].length === 1) {
            hexs[i] = `0${hexs[i]}`
        }
    }
@@ -32,7 +47,7 @@
// å˜æµ…颜色值
export function getLightColor(color, level) {
    let rgb = hexToRgb(color)
    const rgb = hexToRgb(color)
    for (let i = 0; i < 3; i++) {
        rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i])
    }
@@ -41,9 +56,19 @@
// å˜æ·±é¢œè‰²å€¼
export function getDarkColor(color, level) {
    let rgb = hexToRgb(color)
    const rgb = hexToRgb(color)
    for (let i = 0; i < 3; i++) {
        rgb[i] = Math.floor(rgb[i] * (1 - level))
    }
    return rgbToHex(rgb[0], rgb[1], rgb[2])
}
function normalizeHex(color) {
    if (!color || typeof color !== 'string') return '#409eff'
    let value = color.trim().replace('#', '')
    if (value.length === 3) {
        value = value.split('').map((s) => s + s).join('')
    }
    if (!/^[0-9a-fA-F]{6}$/.test(value)) return '#409eff'
    return `#${value.toLowerCase()}`
}
src/views/aiIndustrialBrain/MAINTAIN_RULES.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
# AI工业大脑维护规则
1. å½“ `src/views/aiIndustrialBrain/index.vue` æ–°å¢žæ™ºèƒ½ä½“(`agents`)逻辑时,必须同步确认弹窗助手可用性。
2. å¼¹çª—助手由 `src/components/AIChatSidebar/assistants/index.js` çš„ `assistantRegistry` ç»Ÿä¸€æ³¨å†Œã€‚
3. æ–°å¢žæ™ºèƒ½ä½“çš„ `key` è‹¥è¦åœ¨å¼¹çª—中可用,必须在 `assistantRegistry` ä¸­æä¾›åŒåé…ç½®ã€‚
4. æœªåœ¨ `assistantRegistry` æ³¨å†Œçš„æ™ºèƒ½ä½“会在弹窗中显示为 `pending`(开发中)态。
src/views/aiIndustrialBrain/components/AiAssistantWorkspace.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,198 @@
<template>
  <transition name="fade">
    <section v-if="visible" class="assistant-workspace">
      <div class="assistant-workspace__panel">
        <button
          v-if="assistantMode === 'pending'"
          type="button"
          class="workspace-back-btn"
          @click="$emit('close')"
        >
          <el-icon><ArrowLeftBold /></el-icon>
          <span>返回工业大屏</span>
        </button>
        <div class="assistant-workspace__body">
          <AIChatSidebar
            v-if="assistantMode !== 'pending'"
            :key="assistantMode"
            class="workspace-chat"
            :assistants="resolvedAssistants"
            :default-assistant="assistantMode"
            :hide-trigger="true"
            :auto-open="true"
            drawer-size="100%"
            drawer-direction="ttb"
            header-extra-action-text="返回工业大屏"
            @header-extra-action="$emit('close')"
          />
          <div v-else class="workspace-pending">
            <div class="workspace-pending__content">
              <h3>{{ agentTitle }}</h3>
              <p>正在开发,敬请期待......</p>
            </div>
          </div>
        </div>
      </div>
    </section>
  </transition>
</template>
<script setup>
import { computed } from "vue";
import { ArrowLeftBold } from "@element-plus/icons-vue";
import AIChatSidebar from "@/components/AIChatSidebar/index.vue";
import { assistantRegistry } from "@/components/AIChatSidebar/assistants";
const props = defineProps({
  visible: {
    type: Boolean,
    default: false,
  },
  agent: {
    type: Object,
    default: () => ({}),
  },
});
defineEmits(["close"]);
const agentKey = computed(() => String(props.agent?.key || ""));
const agentTitle = computed(() => String(props.agent?.name || "AI助手"));
/**
 * ç»´æŠ¤è§„则:
 * AI工业大脑新增智能体时,若希望右侧弹窗可用,需保证智能体 key åœ¨ assistantRegistry ä¸­æœ‰åŒåé…ç½®ã€‚
 * æœªé…ç½®æ—¶ä¼šè¿›å…¥ pending(开发中)态,作为显式提醒。
 */
const resolvedAssistant = computed(() => assistantRegistry[agentKey.value] || null);
const assistantMode = computed(() => {
  return resolvedAssistant.value ? agentKey.value : "pending";
});
const resolvedAssistants = computed(() => (resolvedAssistant.value ? [resolvedAssistant.value] : []));
</script>
<style scoped>
.assistant-workspace {
  position: fixed;
  inset: 0;
  z-index: 2100;
  padding: 12px;
  background: rgba(33, 49, 63, 0.24);
  backdrop-filter: blur(2px);
}
.assistant-workspace__panel {
  position: relative;
  height: 100%;
  border-radius: 22px;
  border: 1px solid var(--surface-border);
  background: linear-gradient(180deg, #f9fcfb 0%, #f0f5f2 100%);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.assistant-workspace__body {
  height: 100%;
  min-height: 100%;
}
.workspace-back-btn {
  position: absolute;
  top: 16px;
  right: 20px;
  z-index: 5;
  height: 36px;
  padding: 0 14px;
  border: 1px solid rgba(38, 112, 183, 0.3);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.92);
  color: #25528f;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}
.workspace-back-btn:hover {
  border-color: rgba(31, 122, 114, 0.45);
  color: #1f5ddf;
  box-shadow: 0 8px 16px rgba(31, 122, 114, 0.14);
  transform: translateY(-1px);
}
.workspace-chat {
  width: 100%;
  height: 100%;
}
.workspace-chat :deep(.ai-chat-sidebar-wrapper) {
  height: 100%;
}
.workspace-chat :deep(.ai-chat-drawer) {
  height: 100%;
}
.workspace-chat :deep(.el-drawer) {
  height: 100% !important;
  width: 100% !important;
}
.workspace-pending {
  height: 100%;
  display: grid;
  place-items: center;
  padding: 20px;
  color: var(--text-secondary);
}
.workspace-pending__content {
  display: grid;
  gap: 12px;
  text-align: center;
}
.workspace-pending__content h3 {
  margin: 0;
  font-size: 36px;
  color: var(--text-primary);
}
.workspace-pending__content p {
  margin: 0;
  font-size: 24px;
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
@media (max-width: 1600px) {
  .workspace-back-btn {
    top: 12px;
    right: 14px;
    height: 32px;
    padding: 0 12px;
    font-size: 13px;
  }
  .workspace-pending__content h3 {
    font-size: 30px;
  }
  .workspace-pending__content p {
    font-size: 20px;
  }
}
</style>
src/views/aiIndustrialBrain/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1500 @@
<template>
  <div ref="screenRef" class="ai-brain-screen">
    <section class="brain-stage">
      <header class="brain-head">
        <div class="head-date">
          <p>{{ weekLabel }}</p>
          <p>{{ dateLabel }}</p>
        </div>
        <div class="head-title">
          <span>AI工业大脑</span>
        </div>
        <div class="head-actions">
          <button type="button" class="head-back-btn" @click="goBack">
            <el-icon><ArrowLeftBold /></el-icon>
            <span>返回</span>
          </button>
        </div>
      </header>
      <section class="brain-intro">
        <h2>工业AI数字员工,赋能智造新纪元</h2>
        <p>六大AI助手协同企业管理、销售、采购、生产、财务及数据全链路</p>
        <div class="intro-sign">阿里云 Ã— åƒé—®å¤§æ¨¡åž‹ Ã— æ™ºèƒ½ä½“AI</div>
      </section>
      <section class="carousel-area">
        <button type="button" class="nav-btn nav-btn--left" @click="prevCard">
          <el-icon><ArrowLeftBold /></el-icon>
        </button>
        <div class="carousel-track">
          <article
            v-for="card in visibleCards"
            :key="card.agent.key"
            class="agent-card"
            :class="{ 'agent-card--active': card.offset === 0 }"
            :style="getCardStyle(card.offset)"
            @click="openAssistant(card.realIndex)"
          >
            <div class="agent-card__head" :class="{ 'agent-card__head--active': card.offset === 0 }">
              {{ card.agent.name }}
            </div>
            <div class="agent-card__body" :class="{ 'agent-card__body--active': card.offset === 0 }">
              <div class="avatar-shell" :class="{ 'avatar-shell--active': card.offset === 0 }">
                <div class="avatar-base"></div>
                <div class="avatar-cut">
                  <img v-if="card.agent.avatar" class="avatar-cut__img" :src="card.agent.avatar" :alt="card.agent.name" />
                </div>
              </div>
              <div v-if="card.offset === 0" class="highlight-list">
                <div
                  v-for="highlight in card.agent.highlights"
                  :key="highlight"
                  class="highlight-item"
                >
                  {{ highlight }}
                </div>
              </div>
            </div>
          </article>
        </div>
        <button type="button" class="nav-btn nav-btn--right" @click="nextCard">
          <el-icon><ArrowRightBold /></el-icon>
        </button>
      </section>
      <section class="brain-footer">
        <div class="footer-grid-overlay"></div>
        <div class="footer-metrics">
          <article class="footer-metric">
            <span class="footer-metric__label">在线智能体</span>
            <strong class="footer-metric__value">{{ agents.length }}个</strong>
            <small class="footer-metric__hint">全链路协同运行</small>
          </article>
          <article class="footer-metric footer-metric--focus">
            <span class="footer-metric__label">当前焦点</span>
            <strong class="footer-metric__value">{{ getFooterAgentName(focusAgent.name) }}</strong>
            <small class="footer-metric__hint">{{ focusAgent.highlights?.[0] || "智能分析联动" }}</small>
          </article>
          <article class="footer-metric footer-metric--period">
            <span class="footer-metric__label">轮播周期</span>
            <strong class="footer-metric__value">{{ carouselSecondsText }}</strong>
            <div class="footer-period-control">
              <button type="button" class="period-btn" @click="adjustCarouselSeconds(-0.5)">-</button>
              <input
                v-model.number="carouselSeconds"
                class="period-input"
                type="number"
                min="2"
                max="12"
                step="0.5"
              />
              <span class="period-unit">s</span>
              <button type="button" class="period-btn" @click="adjustCarouselSeconds(0.5)">+</button>
            </div>
            <input
              v-model.number="carouselSeconds"
              class="footer-period-slider"
              type="range"
              min="2"
              max="12"
              step="0.5"
            />
            <small class="footer-metric__hint">可手动设置 2.0s - 12.0s</small>
          </article>
        </div>
        <div class="footer-rail">
          <div class="footer-rail__line">
            <span class="footer-rail__flow"></span>
          </div>
          <div class="footer-rail__nodes">
            <button
              v-for="node in footerNodes"
              :key="node.key"
              type="button"
              class="footer-node"
              :class="{ 'footer-node--active': node.index === carouselIndex }"
              @click="openAssistant(node.index)"
            >
              <span class="footer-node__dot"></span>
              <span class="footer-node__name">{{ getFooterAgentName(node.name) }}</span>
            </button>
          </div>
        </div>
      </section>
    </section>
    <AiAssistantWorkspace
      :visible="fullscreenVisible"
      :agent="currentAgent"
      @close="closeFullscreen"
    />
  </div>
</template>
<script setup>
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRouter } from "vue-router";
import { ArrowLeftBold, ArrowRightBold } from "@element-plus/icons-vue";
import AiAssistantWorkspace from "./components/AiAssistantWorkspace.vue";
import todoAvatar from "@/assets/AI/待办助手.png";
import salesAvatar from "@/assets/AI/销售助手.png";
import purchaseAvatar from "@/assets/AI/采购助手.png";
import productionAvatar from "@/assets/AI/生产助手.png";
import financeAvatar from "@/assets/AI/财务助手.png";
const router = useRouter();
// ç»´æŠ¤çº¦å®šè§ï¼šsrc/views/aiIndustrialBrain/MAINTAIN_RULES.md
const agents = [
  {
    key: "general",
    name: "AI待办助手",
    highlights: ["跨模块流程诊断", "经营风险智能提醒"],
  },
  {
    key: "sales",
    name: "AI销售助手",
    highlights: ["客户流失风险分析", "回款与报价策略建议"],
  },
  {
    key: "purchase",
    name: "AI采购助手",
    highlights: ["供应链指标分析", "采购订单智能生成"],
  },
  {
    key: "production",
    name: "AI生产助手",
    highlights: ["工序瓶颈定位", "产能与报废智能预警"],
  },
  {
    key: "finance",
    name: "AI财务助手",
    highlights: ["现金流压力预判", "费用结构智能分析"],
  },
];
const avatarByAgentKey = {
  general: todoAvatar,
  sales: salesAvatar,
  purchase: purchaseAvatar,
  production: productionAvatar,
  finance: financeAvatar,
};
for (let i = agents.length - 1; i >= 0; i -= 1) {
  const agent = agents[i];
  const avatar = avatarByAgentKey[agent.key];
  if (!avatar) {
    agents.splice(i, 1);
    continue;
  }
  agent.avatar = avatar;
}
const carouselIndex = ref(Math.min(2, Math.max(agents.length - 1, 0)));
const fullscreenVisible = ref(false);
const screenRef = ref(null);
const carouselIntervalMs = ref(4500);
let carouselTimer = null;
const fallbackAgent = {
  key: "fallback",
  name: "AI助手",
  avatar: "",
  highlights: [],
};
const currentAgent = computed(() => agents[carouselIndex.value] || agents[0] || fallbackAgent);
const focusAgent = computed(() => currentAgent.value || fallbackAgent);
const footerNodes = computed(() =>
  agents.map((agent, index) => ({
    key: agent.key,
    name: agent.name,
    index,
  }))
);
const carouselSeconds = computed({
  get: () => Number((carouselIntervalMs.value / 1000).toFixed(1)),
  set: (value) => {
    const next = Number(value);
    if (!Number.isFinite(next)) return;
    const clamped = Math.max(2, Math.min(12, Math.round(next * 2) / 2));
    carouselIntervalMs.value = Math.round(clamped * 1000);
  },
});
const carouselSecondsText = computed(() => `${carouselSeconds.value.toFixed(1)}s`);
const weekLabel = computed(() => {
  const weekMap = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
  return weekMap[new Date().getDay()];
});
const dateLabel = computed(() => {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, "0");
  const day = String(now.getDate()).padStart(2, "0");
  return `${year}å¹´${month}月${day}日`;
});
const visibleCards = computed(() => {
  const total = agents.length;
  return agents
    .map((agent, index) => {
      let offset = index - carouselIndex.value;
      if (offset > total / 2) offset -= total;
      if (offset < -total / 2) offset += total;
      return { agent, offset, realIndex: index };
    })
    .filter((item) => Math.abs(item.offset) <= 2)
    .sort((a, b) => a.offset - b.offset);
});
function getCardStyle(offset) {
  const distance = Math.abs(offset);
  const scale = distance === 0 ? 1 : distance === 1 ? 0.88 : 0.78;
  const opacity = distance === 0 ? 1 : distance === 1 ? 0.92 : 0.76;
  return {
    transform: `translateX(${offset * 340}px) scale(${scale})`,
    zIndex: String(50 - distance),
    opacity,
  };
}
function getFooterAgentName(name) {
  return String(name || "AI助手").replace(/^AI/, "");
}
function adjustCarouselSeconds(delta) {
  carouselSeconds.value = carouselSeconds.value + delta;
}
function prevCard() {
  const total = agents.length;
  if (!total) return;
  carouselIndex.value = (carouselIndex.value - 1 + total) % total;
}
function nextCard() {
  const total = agents.length;
  if (!total) return;
  carouselIndex.value = (carouselIndex.value + 1) % total;
}
async function enterBrowserFullscreen() {
  if (document.fullscreenElement) return;
  const target = screenRef.value || document.documentElement;
  if (!target || typeof target.requestFullscreen !== "function") return;
  try {
    await target.requestFullscreen();
  } catch (error) {
    // Ignore: browser may block fullscreen when there is no direct user activation.
  }
}
async function exitBrowserFullscreen() {
  if (!document.fullscreenElement || typeof document.exitFullscreen !== "function") return;
  try {
    await document.exitFullscreen();
  } catch (error) {
    // Ignore fullscreen exit failures.
  }
}
function goBack() {
  closeFullscreen();
  exitBrowserFullscreen();
  if (window.history.length > 1) {
    router.back();
    return;
  }
  router.push("/index");
}
function openAssistant(index) {
  if (!agents.length) return;
  carouselIndex.value = index;
  fullscreenVisible.value = true;
}
function closeFullscreen() {
  fullscreenVisible.value = false;
}
function startCarousel() {
  stopCarousel();
  if (fullscreenVisible.value) return;
  carouselTimer = window.setInterval(() => {
    nextCard();
  }, carouselIntervalMs.value);
}
function stopCarousel() {
  if (carouselTimer) {
    window.clearInterval(carouselTimer);
    carouselTimer = null;
  }
}
function handleEscClose(event) {
  if (event.key === "Escape" && fullscreenVisible.value) {
    closeFullscreen();
  }
}
watch(
  () => fullscreenVisible.value,
  (opened) => {
    if (opened) {
      stopCarousel();
    } else {
      startCarousel();
    }
  }
);
watch(
  () => carouselIntervalMs.value,
  () => {
    if (!fullscreenVisible.value) {
      startCarousel();
    }
  }
);
onMounted(() => {
  startCarousel();
  window.addEventListener("keydown", handleEscClose);
  window.requestAnimationFrame(() => {
    enterBrowserFullscreen();
  });
});
onBeforeUnmount(() => {
  stopCarousel();
  window.removeEventListener("keydown", handleEscClose);
  exitBrowserFullscreen();
});
</script>
<style scoped>
.ai-brain-screen {
  position: fixed;
  inset: 0;
  z-index: 1900;
  padding: 10px;
  overflow: hidden;
  background: var(--app-bg);
}
.brain-stage {
  position: relative;
  height: 100%;
  min-height: 100%;
  border-radius: 22px;
  border: 1px solid var(--surface-border);
  background:
    radial-gradient(circle at 14% 8%, rgba(31, 122, 114, 0.14), transparent 40%),
    radial-gradient(circle at 86% 12%, rgba(30, 91, 255, 0.1), transparent 42%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.95), rgba(245, 249, 247, 0.94)),
    repeating-linear-gradient(
      135deg,
      rgba(255, 255, 255, 0.05) 0,
      rgba(255, 255, 255, 0.05) 14px,
      rgba(31, 122, 114, 0.03) 14px,
      rgba(31, 122, 114, 0.03) 28px
    );
  box-shadow: var(--shadow-sm);
}
.brain-head {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 180px;
  align-items: center;
  padding: 12px 18px 0;
}
.head-date {
  color: var(--text-secondary);
  font-size: 24px;
  font-weight: 600;
}
.head-date p {
  margin: 0;
  line-height: 1.2;
}
.head-title {
  justify-self: center;
  width: min(760px, 95%);
  height: 68px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0 0 46px 46px;
  color: #fff;
  font-size: 42px;
  font-style: italic;
  font-weight: 700;
  letter-spacing: 1px;
  background: linear-gradient(135deg, #1f7a72 0%, #1e5bff 100%);
  box-shadow: 0 16px 30px rgba(31, 122, 114, 0.24);
}
.head-actions {
  justify-self: end;
}
.head-back-btn {
  height: 40px;
  padding: 0 14px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: none;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 600;
  color: var(--colorPrimary);
  background: var(--surface-base);
  box-shadow: 0 8px 18px rgba(31, 49, 38, 0.12);
  cursor: pointer;
}
.brain-intro {
  text-align: center;
  margin-top: 34px;
}
.brain-intro h2 {
  margin: 0;
  font-size: 44px;
  font-style: italic;
  font-weight: 700;
  color: var(--text-primary);
}
.brain-intro p {
  margin: 12px 0 10px;
  font-size: 28px;
  color: var(--text-secondary);
}
.intro-sign {
  display: inline-block;
  padding: 6px 18px;
  border-radius: 999px;
  font-size: 24px;
  font-weight: 700;
  color: #1e5bff;
  background: rgba(255, 255, 255, 0.82);
  border: 1px solid rgba(30, 91, 255, 0.18);
}
.carousel-area {
  position: relative;
  margin-top: 34px;
  padding: 0 72px 12px;
}
.carousel-track {
  position: relative;
  height: 500px;
  overflow: hidden;
}
.brain-footer {
  position: relative;
  margin: 0 72px;
  height: clamp(226px, 25vh,0);
  border-radius: 18px;
  border: 1px solid rgba(31, 122, 114, 0.28);
  background:
    linear-gradient(120deg, rgba(31, 122, 114, 0.14), rgba(30, 91, 255, 0.14)),
    linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(236, 244, 249, 0.9));
  box-shadow:
    0 16px 34px rgba(31, 81, 131, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.72);
  overflow: hidden;
}
.brain-footer::before {
  content: "";
  position: absolute;
  left: -22%;
  bottom: -120%;
  width: 52%;
  height: 260%;
  background: radial-gradient(ellipse at center, rgba(30, 91, 255, 0.2) 0%, rgba(30, 91, 255, 0) 72%);
  pointer-events: none;
}
.brain-footer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(110deg, transparent 12%, rgba(255, 255, 255, 0.24) 38%, transparent 64%);
  transform: translateX(-120%);
  animation: footerSweep 5.8s linear infinite;
  pointer-events: none;
}
.footer-grid-overlay {
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(
      90deg,
      rgba(31, 122, 114, 0.07) 0,
      rgba(31, 122, 114, 0.07) 1px,
      transparent 1px,
      transparent 36px
    ),
    repeating-linear-gradient(
      0deg,
      rgba(30, 91, 255, 0.06) 0,
      rgba(30, 91, 255, 0.06) 1px,
      transparent 1px,
      transparent 28px
    );
  opacity: 0.72;
  pointer-events: none;
}
.footer-metrics {
  position: relative;
  z-index: 2;
  padding: 14px 20px 72px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
.footer-metric {
  min-height: 76px;
  border-radius: 12px;
  padding: 10px 14px;
  border: 1px solid rgba(37, 124, 188, 0.2);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(245, 250, 255, 0.82));
  box-shadow: 0 10px 18px rgba(29, 83, 134, 0.08);
  display: grid;
  grid-template-rows: auto auto 1fr;
  gap: 4px;
}
.footer-metric--focus {
  border-color: rgba(38, 122, 194, 0.34);
  box-shadow:
    0 12px 22px rgba(30, 91, 255, 0.12),
    inset 0 0 0 1px rgba(85, 148, 232, 0.2);
}
.footer-metric__label {
  font-size: 14px;
  color: rgba(38, 72, 108, 0.88);
  font-weight: 600;
}
.footer-metric__value {
  font-size: 30px;
  line-height: 1;
  font-style: italic;
  font-weight: 700;
  color: #1f5ddf;
  text-shadow: 0 3px 10px rgba(30, 91, 255, 0.18);
}
.footer-metric__hint {
  margin-top: auto;
  font-size: 13px;
  color: rgba(52, 89, 128, 0.82);
}
.footer-metric--period .footer-metric__hint {
  margin-top: 0;
  line-height: 1.25;
}
.footer-metric--period {
  min-height: 122px;
  grid-template-rows: auto auto auto auto auto;
  gap: 6px;
}
.footer-period-control {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.period-btn {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid rgba(38, 112, 183, 0.28);
  background: rgba(255, 255, 255, 0.9);
  color: #2054c9;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}
.period-input {
  width: 56px;
  height: 24px;
  border-radius: 8px;
  border: 1px solid rgba(38, 112, 183, 0.24);
  background: rgba(255, 255, 255, 0.94);
  color: #1f5ddf;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  padding: 0 4px;
}
.period-unit {
  font-size: 12px;
  font-weight: 600;
  color: rgba(40, 80, 117, 0.86);
}
.footer-period-slider {
  width: min(250px, 100%);
  height: 3px;
  accent-color: #2a6ded;
  cursor: pointer;
}
.footer-rail {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 18px;
  z-index: 2;
}
.footer-rail__line {
  position: relative;
  height: 2px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(31, 122, 114, 0.12), rgba(30, 91, 255, 0.6), rgba(31, 122, 114, 0.12));
  overflow: hidden;
}
.footer-rail__flow {
  position: absolute;
  top: -1px;
  left: -18%;
  width: 22%;
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(31, 122, 114, 0), rgba(59, 146, 244, 0.92), rgba(30, 91, 255, 0));
  filter: blur(0.2px);
  animation: railFlow 3.1s ease-in-out infinite;
}
.footer-rail__nodes {
  margin-top: 12px;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
}
.footer-node {
  height: 34px;
  border: 1px solid rgba(38, 112, 183, 0.18);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.76);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: rgba(40, 80, 117, 0.92);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.26s ease;
}
.footer-node:hover {
  transform: translateY(-1px);
  border-color: rgba(31, 122, 114, 0.34);
  box-shadow: 0 8px 14px rgba(31, 122, 114, 0.14);
}
.footer-node--active {
  color: #fff;
  border-color: transparent;
  background: linear-gradient(135deg, rgba(31, 122, 114, 0.94), rgba(30, 91, 255, 0.94));
  box-shadow: 0 10px 18px rgba(30, 91, 255, 0.28);
}
.footer-node__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(30, 91, 255, 0.72);
  box-shadow: 0 0 10px rgba(30, 91, 255, 0.52);
}
.footer-node--active .footer-node__dot {
  background: #fff;
  box-shadow: 0 0 12px rgba(255, 255, 255, 0.72);
  animation: nodePulse 1.4s ease-in-out infinite;
}
.agent-card {
  position: absolute;
  left: 50%;
  top: 0;
  width: 460px;
  margin-left: -230px;
  cursor: pointer;
  transform-origin: center bottom;
  transition: transform 0.35s ease, opacity 0.35s ease;
}
.agent-card__head {
  height: 56px;
  border-radius: 12px 12px 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  color: #fff;
  font-weight: 700;
  background: linear-gradient(135deg, #1f7a72 0%, #1e5bff 100%);
}
.agent-card__head--active {
  box-shadow:
    0 12px 22px rgba(30, 91, 255, 0.26),
    inset 0 0 0 1px rgba(255, 255, 255, 0.28);
  position: relative;
}
.agent-card__head--active::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 6px;
  height: 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.96), rgba(255, 255, 255, 0.22));
}
.agent-card__body {
  position: relative;
  height: 430px;
  border: 1px solid var(--surface-border-strong);
  border-top: none;
  border-radius: 0 0 20px 20px;
  background: rgba(255, 255, 255, 0.96);
  overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  isolation: isolate;
  box-shadow: 0 12px 24px rgba(31, 49, 38, 0.1);
}
.agent-card__body--active {
  background: linear-gradient(180deg, rgba(248, 252, 251, 0.96), rgba(225, 241, 250, 0.9));
  border-color: rgba(31, 122, 114, 0.35);
}
.agent-card__body--active::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(108deg, transparent 28%, rgba(255, 255, 255, 0.34) 50%, transparent 72%);
  transform: translateX(-125%);
  animation: bodySweep 3.6s linear infinite;
  pointer-events: none;
  z-index: 1;
}
.avatar-shell {
  position: relative;
  width: 248px;
  height: 430px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  --base-core: rgba(53, 143, 222, 0.4);
  --base-ring: rgba(39, 122, 201, 0.62);
  --base-glow: rgba(46, 133, 214, 0.28);
}
.avatar-shell::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -10px;
  width: 268px;
  height: 58px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(
    ellipse at center,
    rgba(55, 140, 219, 0.22) 0%,
    rgba(55, 140, 219, 0.11) 46%,
    rgba(55, 140, 219, 0) 74%
  );
  filter: blur(2.4px);
  animation: baseGlow 4.6s ease-in-out infinite;
  z-index: 1;
  pointer-events: none;
}
.avatar-shell::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 248px;
  height: 46px;
  transform: translateX(-50%);
  border-radius: 50%;
  border: 2px solid var(--base-ring);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.64),
    0 0 24px var(--base-glow);
  animation: basePulse 3.1s ease-in-out infinite;
  z-index: 4;
}
.avatar-base {
  position: absolute;
  left: 50%;
  bottom: 2px;
  width: 224px;
  height: 38px;
  transform: translateX(-50%);
  z-index: 2;
  pointer-events: none;
}
.avatar-base::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(
      ellipse at center,
      rgba(255, 255, 255, 0.96) 0%,
      rgba(255, 255, 255, 0.92) 36%,
      var(--base-core) 68%,
      rgba(38, 118, 195, 0.08) 100%
    );
  box-shadow:
    0 0 30px var(--base-core),
    0 0 10px rgba(255, 255, 255, 0.34) inset;
  z-index: 3;
}
.avatar-base::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 194px;
  height: 194px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background:
    conic-gradient(
      from 180deg,
      transparent 0deg,
      var(--base-ring) 48deg,
      transparent 112deg,
      var(--base-ring) 208deg,
      transparent 284deg,
      rgba(33, 114, 191, 0.48) 332deg,
      transparent 360deg
    );
  -webkit-mask: radial-gradient(circle, transparent 61%, #000 62%, #000 68%, transparent 70%);
  mask: radial-gradient(circle, transparent 61%, #000 62%, #000 68%, transparent 70%);
  opacity: 0.62;
  animation: baseRotate 10.5s linear infinite;
  z-index: 2;
}
.avatar-shell--active {
  --base-core: rgba(50, 141, 217, 0.52);
  --base-ring: rgba(42, 127, 205, 0.76);
  --base-glow: rgba(38, 130, 211, 0.38);
}
.avatar-cut {
  position: relative;
  width: 220px;
  height: 430px;
  z-index: 6;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  filter: saturate(1.04) drop-shadow(0 14px 18px rgba(24, 44, 66, 0.14));
  transform-origin: center 82%;
  animation: avatarFloat 3.2s ease-in-out infinite;
}
.avatar-cut__img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center bottom;
  display: block;
}
.agent-card--active .avatar-cut {
  animation-duration: 2.6s;
}
.highlight-list {
  position: absolute;
  right: 10px;
  top: 14px;
  display: grid;
  gap: 8px;
  width: 220px;
  z-index: 16;
}
.highlight-item {
  border-radius: 10px;
  padding: 8px 10px;
  font-size: 18px;
  line-height: 1.4;
  color: #fff;
  background: rgba(33, 49, 63, 0.92);
  box-shadow: 0 8px 16px rgba(21, 30, 40, 0.22);
}
.agent-card--active .highlight-item {
  background: rgba(31, 122, 114, 0.9);
}
.nav-btn {
  position: absolute;
  top: 212px;
  z-index: 80;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: none;
  font-size: 30px;
  color: var(--colorPrimary);
  background: var(--surface-base);
  box-shadow: 0 10px 20px rgba(31, 49, 38, 0.16);
  cursor: pointer;
}
.nav-btn--left {
  left: 14px;
}
.nav-btn--right {
  right: 14px;
}
.ai-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 2100;
  padding: 12px;
  background: rgba(33, 49, 63, 0.24);
  backdrop-filter: blur(2px);
}
.ai-panel {
  height: 100%;
  border-radius: 22px;
  border: 1px solid var(--surface-border);
  background: linear-gradient(180deg, #f9fcfb 0%, #f0f5f2 100%);
  display: grid;
  grid-template-rows: 62px minmax(0, 1fr) 110px;
  box-shadow: var(--shadow-md);
}
.ai-panel__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
}
.ai-brand {
  font-size: 34px;
  color: var(--text-primary);
  font-weight: 700;
}
.ai-close {
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: transparent;
  font-size: 30px;
  color: var(--text-secondary);
  cursor: pointer;
}
.ai-panel__center {
  padding: 8px 20px 10px;
  display: grid;
  grid-template-rows: 120px 290px minmax(0, 1fr);
  gap: 10px;
  min-height: 0;
}
.welcome-card {
  border-radius: 14px;
  background: linear-gradient(135deg, rgba(232, 244, 242, 0.95), rgba(230, 237, 250, 0.9));
  padding: 16px 18px;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  border: 1px solid var(--surface-border);
}
.welcome-card__text h3 {
  margin: 0;
  font-size: 28px;
  color: var(--text-primary);
}
.welcome-card__text p {
  margin: 8px 0 0;
  font-size: 20px;
  color: var(--text-secondary);
}
.mini-avatar {
  width: 120px;
  height: 120px;
  border-radius: 14px;
  border: 1px solid var(--surface-border);
  background-color: #fff;
  background-clip: border-box;
  overflow: hidden;
}
.mini-avatar__img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center bottom;
  display: block;
}
.recommend-card {
  border-radius: 14px;
  border: 1px solid var(--surface-border);
  background: rgba(255, 255, 255, 0.86);
  padding: 12px 14px;
}
.recommend-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  color: var(--text-primary);
  font-size: 24px;
  font-weight: 700;
}
.refresh-btn {
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 18px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}
.recommend-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 18px;
}
.recommend-item {
  border: 1px solid var(--surface-border);
  border-radius: 8px;
  text-align: left;
  padding: 8px 10px;
  font-size: 18px;
  color: var(--text-secondary);
  background: #fff;
  cursor: pointer;
}
.recommend-item:hover {
  background: rgba(31, 122, 114, 0.08);
  color: var(--colorPrimary);
}
.chat-card {
  border-radius: 14px;
  border: 1px solid var(--surface-border);
  background: #fff;
  min-height: 0;
  overflow: hidden;
}
.chat-empty {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
  font-size: 18px;
}
.chat-messages {
  height: 100%;
  overflow-y: auto;
  padding: 14px;
  display: grid;
  gap: 10px;
}
.chat-row {
  display: flex;
}
.chat-row--assistant {
  justify-content: flex-start;
}
.chat-row--user {
  justify-content: flex-end;
}
.chat-bubble {
  max-width: 72%;
  border-radius: 12px;
  padding: 10px 12px;
  font-size: 18px;
  line-height: 1.5;
  white-space: pre-wrap;
  color: var(--text-primary);
  background: var(--surface-soft);
  border: 1px solid var(--surface-border);
}
.chat-row--user .chat-bubble {
  color: #fff;
  background: linear-gradient(135deg, #1f7a72 0%, #1e5bff 100%);
  border: none;
}
.ai-panel__input {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 130px;
  gap: 12px;
  padding: 14px 20px 18px;
}
.ask-input :deep(.el-input__wrapper) {
  height: 74px;
  border-radius: 18px;
  box-shadow: 0 0 0 1px var(--surface-border) inset;
  background: #fff;
}
.ask-input :deep(.el-input__inner) {
  font-size: 20px;
}
.send-btn {
  align-self: center;
  height: 56px;
  font-size: 20px;
  min-width: 98px;
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
@keyframes avatarFloat {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-8px);
  }
}
@keyframes basePulse {
  0%,
  100% {
    transform: translateX(-50%) scale(1);
    opacity: 0.88;
  }
  50% {
    transform: translateX(-50%) scale(1.045);
    opacity: 0.95;
  }
}
@keyframes baseRotate {
  from {
    transform: translate(-50%, -50%) rotate(0deg);
  }
  to {
    transform: translate(-50%, -50%) rotate(360deg);
  }
}
@keyframes baseGlow {
  0%,
  100% {
    transform: translateX(-50%) scaleX(1);
    opacity: 0.84;
  }
  50% {
    transform: translateX(-50%) scaleX(1.06);
    opacity: 0.96;
  }
}
@keyframes bodySweep {
  0% {
    transform: translateX(-125%);
  }
  100% {
    transform: translateX(135%);
  }
}
@keyframes footerSweep {
  0% {
    transform: translateX(-120%);
  }
  100% {
    transform: translateX(140%);
  }
}
@keyframes railFlow {
  0% {
    transform: translateX(0);
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  80% {
    opacity: 1;
  }
  100% {
    transform: translateX(520%);
    opacity: 0;
  }
}
@keyframes nodePulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.25);
  }
}
@media (max-width: 1600px) {
  .head-title {
    font-size: 34px;
    height: 60px;
  }
  .brain-intro h2 {
    font-size: 36px;
  }
  .brain-intro p {
    font-size: 22px;
  }
  .intro-sign {
    font-size: 20px;
  }
  .agent-card {
    width: 380px;
    margin-left: -190px;
  }
  .agent-card__head {
    font-size: 24px;
    height: 54px;
  }
  .agent-card__body {
    height: 390px;
  }
  .highlight-list {
    width: 184px;
  }
  .highlight-item {
    font-size: 15px;
  }
  .avatar-shell {
    width: 220px;
    height: 390px;
  }
  .avatar-cut {
    width: 202px;
    height: 390px;
  }
  .avatar-base {
    width: 194px;
    height: 34px;
  }
  .avatar-base::after {
    width: 164px;
    height: 164px;
  }
  .avatar-shell::before {
    width: 236px;
    height: 48px;
    bottom: -9px;
  }
  .avatar-shell::after {
    width: 220px;
    height: 40px;
    bottom: 0;
  }
  .brain-footer {
    margin: 0 52px;
    height: clamp(210px, 23vh, 264px);
  }
  .footer-metrics {
    padding: 12px 14px 66px;
    gap: 8px;
  }
  .footer-metric {
    min-height: 66px;
    padding: 8px 10px;
  }
  .footer-metric--period {
    min-height: 108px;
    gap: 4px;
  }
  .footer-metric__label {
    font-size: 12px;
  }
  .footer-metric__value {
    font-size: 24px;
  }
  .footer-metric__hint {
    font-size: 11px;
  }
  .footer-period-control {
    gap: 6px;
  }
  .period-btn {
    width: 20px;
    height: 20px;
    font-size: 12px;
  }
  .period-input {
    width: 50px;
    height: 22px;
    font-size: 12px;
  }
  .footer-period-slider {
    width: 100%;
  }
  .footer-rail {
    left: 14px;
    right: 14px;
    bottom: 14px;
  }
  .footer-rail__nodes {
    margin-top: 10px;
    gap: 6px;
  }
  .footer-node {
    height: 30px;
    font-size: 12px;
    gap: 6px;
  }
  .footer-node__dot {
    width: 7px;
    height: 7px;
  }
  .ai-brand {
    font-size: 28px;
  }
  .welcome-card__text h3,
  .recommend-card__head {
    font-size: 22px;
  }
  .welcome-card__text p,
  .recommend-item,
  .chat-bubble,
  .refresh-btn,
  .chat-empty,
  .ask-input :deep(.el-input__inner),
  .send-btn {
    font-size: 16px;
  }
}
</style>
src/views/basicData/customerFile/index.vue
@@ -27,6 +27,9 @@
      <div>
        <el-button type="primary"
                   @click="openForm('add')">新增客户</el-button>
        <el-button type="primary"
                   plain
                   @click="back">流入公海</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="info"
                   plain
@@ -619,7 +622,7 @@
    addReturnVisit,
    getReturnVisit,
  } from "@/api/basicData/customerFile.js";
  import {listCustomer, getCustomer, addCustomer, updateCustomer, delCustomer} from "@/api/basicData/customer.js";
  import {listCustomer, getCustomer, addCustomer, updateCustomer, delCustomer, backCustomer} from "@/api/basicData/customer.js";
  import { ElMessageBox } from "element-plus";
  import { userListNoPage } from "@/api/system/user.js";
  import useUserStore from "@/store/modules/user";
@@ -1126,6 +1129,36 @@
      });
  };
  const back = () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    const ids = selectedRows.value.map(item => item.id);
    ElMessageBox.confirm("选中的客户将流入公海,是否确认?", "流入公海提示", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        tableLoading.value = true;
        return Promise.all(ids.map(id => backCustomer(id)))
          .then(() => {
            proxy.$modal.msgSuccess("流入公海成功");
            selectedRows.value = [];
            getList();
          })
          .finally(() => {
            tableLoading.value = false;
          });
      })
      .catch(error => {
        if (error === "cancel" || error === "close") {
          proxy.$modal.msg("已取消");
        }
      });
  };
  // æ‰“开回访提醒弹窗
  const openReminderDialog = row => {
    currentCustomerId.value = row.id;
@@ -1413,7 +1446,7 @@
  const downloadAttachment = row => {
    if (row.url) {
      // proxy.download(row.url, {}, row.name);
      proxy.$download.name(row.url);
            proxy.$download.byUrl(row.url, row.originalFilename);
    } else {
      proxy.$modal.msgError("下载链接不存在");
    }
src/views/basicData/customerFileOpenSea/index.vue
@@ -1651,7 +1651,7 @@
  const downloadAttachment = row => {
    if (row.url) {
      // proxy.download(row.url, {}, row.name);
      proxy.$download.name(row.url);
            proxy.$download.byUrl(row.url, row.originalFilename);
    } else {
      proxy.$modal.msgError("下载链接不存在");
    }
src/views/basicData/product/index.vue
@@ -5,7 +5,7 @@
        <el-input v-model="search"
                  style="width: 210px"
                  placeholder="输入关键字进行搜索"
                  @change="searchFilter"
                  @input="debouncedSearch"
                  @clear="searchFilter"
                  clearable
                  prefix-icon="Search" />
@@ -43,12 +43,12 @@
                <el-button type="primary"
                           link
                           :disabled="isTopLevelNode(data, node)"
                           @click="openProDia('edit', data)">
                           @click="openProDia('edit', data, node)">
                  ç¼–辑
                </el-button>
                <el-button type="primary"
                           link
                           @click="openProDia('add', data)">
                           @click="openProDia('add', data, node)">
                  æ·»åŠ äº§å“
                </el-button>
                <el-button v-if="!node.childNodes.length"
@@ -285,6 +285,8 @@
  const search = ref("");
  const currentId = ref("");
  const currentParentId = ref("");
  /** äº§å“å¼¹çª—:add å­˜çˆ¶èŠ‚ç‚¹ id;edit å­˜å½“前节点 id ä¸Ž parentId(不依赖树选中项) */
  const productDialogTarget = ref(null);
  const operationType = ref("");
  const treeLoad = ref(false);
  const list = ref([]);
@@ -388,17 +390,28 @@
    return [null, undefined, "", 0, "0"].includes(data?.parentId);
  };
  // æ‰“开产品弹框
  const openProDia = (type, data) => {
    if (data && type === "edit" && isTopLevelNode(data)) {
  const openProDia = (type, data, node) => {
    if (data && type === "edit" && isTopLevelNode(data, node)) {
      proxy.$modal.msgWarning("一级节点不能编辑或删除");
      return;
    }
    operationType.value = type;
    productDia.value = true;
    form.value.productName = "";
    if (type === "edit") {
      form.value.productName = data.productName;
    productDialogTarget.value = null;
    if (type === "add" && data) {
      productDialogTarget.value = { parentId: data.id };
    } else if (type === "edit" && data) {
      let parentId = data.parentId;
      if (
        [null, undefined, ""].includes(parentId) &&
        node?.parent?.data?.id != null
      ) {
        parentId = node.parent.data.id;
      }
      productDialogTarget.value = { id: data.id, parentId };
    }
    productDia.value = true;
    form.value.productName =
      type === "edit" && data ? data.productName : "";
  };
  // æ‰“开规格型号弹框
  const openModelDia = (type, data) => {
@@ -417,14 +430,16 @@
    proxy.$refs.formRef.validate(valid => {
      if (valid) {
        if (operationType.value === "add") {
          form.value.parentId = currentId.value;
          form.value.parentId =
            productDialogTarget.value?.parentId ?? currentId.value;
          form.value.id = "";
        } else if (operationType.value === "addOne") {
          form.value.id = "";
          form.value.parentId = "";
        } else {
          form.value.id = currentId.value;
          form.value.parentId = "";
          form.value.id =
            productDialogTarget.value?.id ?? currentId.value;
          form.value.parentId = productDialogTarget.value?.parentId ?? "";
        }
        addOrEditProduct(form.value).then(res => {
          proxy.$modal.msgSuccess("提交成功");
@@ -437,6 +452,7 @@
  // å…³é—­äº§å“å¼¹æ¡†
  const closeProDia = () => {
    proxy.$refs.formRef.resetFields();
    productDialogTarget.value = null;
    productDia.value = false;
  };
@@ -549,40 +565,31 @@
        proxy.$modal.msg("已取消");
      });
  };
  // è°ƒç”¨tree过滤方法 ä¸­æ–‡è‹±è¿‡æ»¤
  const filterNode = (value, data, node) => {
    if (!value) {
      //如果数据为空,则返回true,显示所有的数据项
      return true;
    }
    // æŸ¥è¯¢åˆ—表是否有匹配数据,将值小写,匹配英文数据
    let val = value.toLowerCase();
    return chooseNode(val, data, node); // è°ƒç”¨è¿‡æ»¤äºŒå±‚方法
  const debounce = (fn, delay = 300) => {
    let timer;
    return (...args) => {
      clearTimeout(timer);
      timer = setTimeout(() => fn(...args), delay);
    };
  };
  // è¿‡æ»¤çˆ¶èŠ‚ç‚¹ / å­èŠ‚ç‚¹ (如果输入的参数是父节点且能匹配,则返回该节点以及其下的所有子节点;如果参数是子节点,则返回该节点的父节点。name是中文字符,enName是英文字符.
  const chooseNode = (value, data, node) => {
    if (data.label.indexOf(value) !== -1) {
  const debouncedSearch = debounce(() => {
    searchFilter();
  }, 300);
  const filterNode = (value, data) => {
    if (!value) return true;
    return chooseNode(value.toLowerCase(), data);
  };
  const chooseNode = (value, data) => {
    const label = (data.label || '').toLowerCase();
    if (label.indexOf(value) !== -1) {
      return true;
    }
    const level = node.level;
    // å¦‚果传入的节点本身就是一级节点就不用校验了
    if (level === 1) {
      return false;
    if (data.children && data.children.length > 0) {
      return data.children.some(child => chooseNode(value, child));
    }
    // å…ˆå–当前节点的父节点
    let parentData = node.parent;
    // éåŽ†å½“å‰èŠ‚ç‚¹çš„çˆ¶èŠ‚ç‚¹
    let index = 0;
    while (index < level - 1) {
      // å¦‚果匹配到直接返回,此处name值是中文字符,enName是英文字符。判断匹配中英文过滤
      if (parentData.data.label.indexOf(value) !== -1) {
        return true;
      }
      // å¦åˆ™çš„话再往上一层做匹配
      parentData = parentData.parent;
      index++;
    }
    // æ²¡åŒ¹é…åˆ°è¿”回false
    return false;
  };
  getProductTreeList();
src/views/basicData/supplierManage/components/BlacklistTab.vue
@@ -231,7 +231,10 @@
        </div>
      </template>
    </el-dialog>
    <files-dia ref="filesDia"></files-dia>
    <FileList v-if="fileListDialogVisible"
              v-model:visible="fileListDialogVisible"
              record-type="supplier_manage"
              :record-id="recordId" />
  </div>
</template>
@@ -249,7 +252,9 @@
} from "@/api/basicData/supplierManageFile.js";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth.js";
import FilesDia from "../filesDia.vue";
const FileList = defineAsyncComponent(() =>
    import("@/components/Dialog/FileList.vue")
);
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
@@ -327,7 +332,7 @@
        name: "资质文件",
        type: "text",
        clickFun: (row) => {
          openFilesFormDia(row)
          openFileDialog(row)
        }
      }
    ],
@@ -342,7 +347,8 @@
  size: 100,
  total: 0,
});
const filesDia = ref()
const fileListDialogVisible = ref(false);
const recordId = ref();
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
@@ -567,10 +573,9 @@
  return `${year}-${month}-${day}`;
}
// æ‰“开附件弹框
const openFilesFormDia = (row) => {
  nextTick(() => {
    filesDia.value?.openDialog(row)
  })
const openFileDialog = async row => {
  recordId.value = row.id;
  fileListDialogVisible.value = true;
};
onMounted(() => {
src/views/basicData/supplierManage/components/HomeTab.vue
@@ -237,7 +237,10 @@
        </div>
      </template>
    </el-dialog>
    <files-dia ref="filesDia"></files-dia>
    <FileList v-if="fileListDialogVisible"
              v-model:visible="fileListDialogVisible"
              record-type="supplier_manage"
              :record-id="recordId" />
  </div>
</template>
@@ -255,7 +258,9 @@
} from "@/api/basicData/supplierManageFile.js";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth.js";
import FilesDia from "../filesDia.vue";
const FileList = defineAsyncComponent(() =>
    import("@/components/Dialog/FileList.vue")
);
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
@@ -333,7 +338,7 @@
        name: "资质文件",
        type: "text",
        clickFun: (row) => {
          openFilesFormDia(row)
          openFileDialog(row)
        }
      }
    ],
@@ -343,12 +348,13 @@
const selectedRows = ref([]);
const userList = ref([]);
const tableLoading = ref(false);
const fileListDialogVisible = ref(false);
const recordId = ref();
const page = reactive({
  current: 1,
  size: 100,
  total: 0,
});
const filesDia = ref()
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
@@ -573,10 +579,9 @@
  return `${year}-${month}-${day}`;
}
// æ‰“开附件弹框
const openFilesFormDia = (row) => {
  nextTick(() => {
    filesDia.value?.openDialog(row)
  })
const openFileDialog = async row => {
  recordId.value = row.id;
  fileListDialogVisible.value = true;
};
onMounted(() => {
src/views/basicData/supplierManage/filesDia.vue
@@ -164,7 +164,7 @@
}
// ä¸‹è½½é™„ä»¶
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
    proxy.$download.byUrl(row.url, row.originalFilename);
}
// åˆ é™¤
const handleDelete = () => {
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -1,85 +1,103 @@
<template>
  <div>
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'approval' ? '审批' : '详情'"
      width="700px"
      @close="closeDia"
    >
            <el-form :model="form" label-width="140px" label-position="top" ref="formRef">
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="流程编号:" prop="approveId">
                            <el-input v-model="form.approveId" placeholder="自动编号" clearable disabled/>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="申请部门:">
                            <el-select
                                disabled
                                v-model="form.approveDeptId"
                                placeholder="选择部门"
                            >
                                <el-option
                                    v-for="user in productOptions"
                                    :key="user.deptId"
                                    :label="user.deptName"
                                    :value="user.deptId"
                                />
                            </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row v-if="!isQuotationApproval && !isPurchaseApproval">
                    <el-col :span="24">
                        <el-form-item :label="props.approveType == 5 ? '采购合同号:' : '审批事由:'" prop="approveReason">
                            <el-input v-model="form.approveReason" placeholder="请输入" clearable type="textarea" disabled/>
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
    <el-dialog v-model="dialogFormVisible"
               :title="operationType === 'approval' ? '审批' : '详情'"
               width="700px"
               @close="closeDia">
      <el-form :model="form"
               label-width="140px"
               label-position="top"
               ref="formRef">
        <el-row>
          <el-col :span="24">
            <el-form-item label="流程编号:"
                          prop="approveId">
              <el-input v-model="form.approveId"
                        placeholder="自动编号"
                        clearable
                        disabled />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="申请部门:">
              <el-select disabled
                         v-model="form.approveDeptId"
                         placeholder="选择部门">
                <el-option v-for="user in productOptions"
                           :key="user.deptId"
                           :label="user.deptName"
                           :value="user.deptId" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="!isQuotationApproval && !isPurchaseApproval">
          <el-col :span="24">
            <el-form-item :label="props.approveType == 5 ? '采购合同号:' : '审批事由:'"
                          prop="approveReason">
              <el-input v-model="form.approveReason"
                        placeholder="请输入"
                        clearable
                        type="textarea"
                        disabled />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <!-- æŠ¥ä»·å®¡æ‰¹ï¼šå±•示报价详情(复用销售报价"查看详情对话框"内容结构) -->
      <div v-if="isQuotationApproval" style="margin: 10px 0 18px;">
      <div v-if="isQuotationApproval"
           style="margin: 10px 0 18px;">
        <el-divider content-position="left">报价详情</el-divider>
        <el-skeleton :loading="quotationLoading" animated>
        <el-skeleton :loading="quotationLoading"
                     animated>
          <template #template>
            <el-skeleton-item variant="h3" style="width: 30%" />
            <el-skeleton-item variant="text" style="width: 100%" />
            <el-skeleton-item variant="text" style="width: 100%" />
            <el-skeleton-item variant="h3"
                              style="width: 30%" />
            <el-skeleton-item variant="text"
                              style="width: 100%" />
            <el-skeleton-item variant="text"
                              style="width: 100%" />
          </template>
          <template #default>
            <el-empty v-if="!currentQuotation || !currentQuotation.quotationNo" description="未查询到对应报价详情" />
            <el-empty v-if="!currentQuotation || !currentQuotation.quotationNo"
                      description="未查询到对应报价详情" />
            <template v-else>
              <el-descriptions :column="2" border>
              <el-descriptions :column="2"
                               border>
                <el-descriptions-item label="报价单号">{{ currentQuotation.quotationNo }}</el-descriptions-item>
                <el-descriptions-item label="客户名称">{{ currentQuotation.customer }}</el-descriptions-item>
                <el-descriptions-item label="业务员">{{ currentQuotation.salesperson }}</el-descriptions-item>
                <el-descriptions-item label="报价日期">{{ currentQuotation.quotationDate }}</el-descriptions-item>
                <el-descriptions-item label="有效期至">{{ currentQuotation.validDate }}</el-descriptions-item>
                <el-descriptions-item label="付款方式">{{ currentQuotation.paymentMethod }}</el-descriptions-item>
                <el-descriptions-item label="报价总额" :span="2">
                <el-descriptions-item label="报价总额"
                                      :span="2">
                  <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
                    Â¥{{ Number(currentQuotation.totalAmount ?? 0).toFixed(2) }}
                  </span>
                </el-descriptions-item>
              </el-descriptions>
              <div style="margin-top: 20px;">
                <h4>产品明细</h4>
                <el-table :data="currentQuotation.products || []" border style="width: 100%">
                  <el-table-column prop="product" label="产品名称" />
                  <el-table-column prop="specification" label="规格型号" />
                  <el-table-column prop="unit" label="单位" />
                  <el-table-column prop="unitPrice" label="单价">
                <el-table :data="currentQuotation.products || []"
                          border
                          style="width: 100%">
                  <el-table-column prop="product"
                                   label="产品名称" />
                  <el-table-column prop="specification"
                                   label="规格型号" />
                  <el-table-column prop="unit"
                                   label="单位" />
                  <el-table-column prop="unitPrice"
                                   label="单价">
                    <template #default="scope">Â¥{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                </el-table>
              </div>
              <div v-if="currentQuotation.remark" style="margin-top: 20px;">
              <div v-if="currentQuotation.remark"
                   style="margin-top: 20px;">
                <h4>备注</h4>
                <p>{{ currentQuotation.remark }}</p>
              </div>
@@ -87,20 +105,26 @@
          </template>
        </el-skeleton>
      </div>
      <!-- é‡‡è´­å®¡æ‰¹ï¼šå±•示采购详情 -->
      <div v-if="isPurchaseApproval" style="margin: 10px 0 18px;">
      <div v-if="isPurchaseApproval"
           style="margin: 10px 0 18px;">
        <el-divider content-position="left">采购详情</el-divider>
        <el-skeleton :loading="purchaseLoading" animated>
        <el-skeleton :loading="purchaseLoading"
                     animated>
          <template #template>
            <el-skeleton-item variant="h3" style="width: 30%" />
            <el-skeleton-item variant="text" style="width: 100%" />
            <el-skeleton-item variant="text" style="width: 100%" />
            <el-skeleton-item variant="h3"
                              style="width: 30%" />
            <el-skeleton-item variant="text"
                              style="width: 100%" />
            <el-skeleton-item variant="text"
                              style="width: 100%" />
          </template>
          <template #default>
            <el-empty v-if="!currentPurchase || !currentPurchase.purchaseContractNumber" description="未查询到对应采购详情" />
            <el-empty v-if="!currentPurchase || !currentPurchase.purchaseContractNumber"
                      description="未查询到对应采购详情" />
            <template v-else>
              <el-descriptions :column="2" border>
              <el-descriptions :column="2"
                               border>
                <el-descriptions-item label="采购合同号">{{ currentPurchase.purchaseContractNumber }}</el-descriptions-item>
                <el-descriptions-item label="供应商名称">{{ currentPurchase.supplierName }}</el-descriptions-item>
                <el-descriptions-item label="项目名称">{{ currentPurchase.projectName }}</el-descriptions-item>
@@ -108,24 +132,32 @@
                <el-descriptions-item label="签订日期">{{ currentPurchase.executionDate }}</el-descriptions-item>
                <el-descriptions-item label="录入日期">{{ currentPurchase.entryDate }}</el-descriptions-item>
                <el-descriptions-item label="付款方式">{{ currentPurchase.paymentMethod }}</el-descriptions-item>
                <el-descriptions-item label="合同金额" :span="2">
                <el-descriptions-item label="合同金额"
                                      :span="2">
                  <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
                    Â¥{{ Number(currentPurchase.contractAmount ?? 0).toFixed(2) }}
                  </span>
                </el-descriptions-item>
              </el-descriptions>
              <div style="margin-top: 20px;">
                <h4>产品明细</h4>
                <el-table :data="currentPurchase.productData || []" border style="width: 100%">
                  <el-table-column prop="productCategory" label="产品名称" />
                  <el-table-column prop="specificationModel" label="规格型号" />
                  <el-table-column prop="unit" label="单位" />
                  <el-table-column prop="quantity" label="数量" />
                  <el-table-column prop="taxInclusiveUnitPrice" label="含税单价">
                <el-table :data="currentPurchase.productData || []"
                          border
                          style="width: 100%">
                  <el-table-column prop="productCategory"
                                   label="产品名称" />
                  <el-table-column prop="specificationModel"
                                   label="规格型号" />
                  <el-table-column prop="unit"
                                   label="单位" />
                  <el-table-column prop="quantity"
                                   label="数量" />
                  <el-table-column prop="taxInclusiveUnitPrice"
                                   label="含税单价">
                    <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                  <el-table-column prop="taxInclusiveTotalPrice" label="含税总价">
                  <el-table-column prop="taxInclusiveTotalPrice"
                                   label="含税总价">
                    <template #default="scope">Â¥{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template>
                  </el-table-column>
                </el-table>
@@ -134,52 +166,138 @@
          </template>
        </el-skeleton>
      </div>
      <el-form :model="{ activities }" ref="formRef" label-position="top">
        <el-steps :active="getActiveStep()" finish-status="success" process-status="process" align-center direction="vertical">
          <el-step
            v-for="(activity, index) in activities"
            :key="index"
                        finish-status="success"
            :title="getNodeTitle(index, activities.length)"
            :description="activity.approveNodeUser"
            :icon="getNodeIcon(activity, index)"
          >
                        <template #icon>
                            <el-icon v-if="activity.approveNodeStatus === 2" color="red" :size="22"><WarningFilled /></el-icon>
                            <el-icon v-else-if="activity.isShen" color="#1890ff" :size="22"><Edit /></el-icon>
                            <el-icon v-else-if="activity.approveNodeStatus === 1" color="#67C23A" :size="26"><Check /></el-icon>
                            <el-icon v-else color="#C0C4CC" :size="22"><MoreFilled /></el-icon>
                        </template>
      <!-- å‘货审批:展示发货详情 -->
      <div v-if="isDeliveryApproval"
           style="margin: 10px 0 18px;">
        <el-divider content-position="left">发货详情</el-divider>
        <el-skeleton :loading="deliveryLoading"
                     animated>
          <template #template>
            <el-skeleton-item variant="h3"
                              style="width: 30%" />
            <el-skeleton-item variant="text"
                              style="width: 100%" />
            <el-skeleton-item variant="text"
                              style="width: 100%" />
          </template>
          <template #default>
            <el-empty v-if="!currentDelivery || !currentDelivery.shippingInfo"
                      description="未查询到对应发货详情" />
            <template v-else>
              <el-descriptions :column="2"
                               border>
                <el-descriptions-item label="销售订单">{{ currentDelivery.shippingInfo.salesContractNo || '--' }}</el-descriptions-item>
                <el-descriptions-item label="发货订单号">{{ currentDelivery.shippingInfo.shippingNo || '--' }}</el-descriptions-item>
                <el-descriptions-item label="客户名称">{{ currentDelivery.shippingInfo.customerName || '--' }}</el-descriptions-item>
                <el-descriptions-item label="发货类型">{{ currentDelivery.shippingInfo.type || '--' }}</el-descriptions-item>
                <el-descriptions-item label="发货日期">{{ currentDelivery.shippingInfo.shippingDate || '--' }}</el-descriptions-item>
                <el-descriptions-item label="审核状态">{{ currentDelivery.shippingInfo.status || '--' }}</el-descriptions-item>
                <el-descriptions-item label="发货车牌号">{{ currentDelivery.shippingInfo.shippingCarNumber || '--' }}</el-descriptions-item>
                <el-descriptions-item label="快递公司">{{ currentDelivery.shippingInfo.expressCompany || '--' }}</el-descriptions-item>
                <el-descriptions-item label="快递单号"
                                      :span="2">{{ currentDelivery.shippingInfo.expressNumber || '--' }}</el-descriptions-item>
              </el-descriptions>
              <div style="margin-top: 20px;">
                <h4>产品明细</h4>
                <el-table :data="deliveryProductList"
                          border
                          size="small"
                          style="width: 100%">
                  <el-table-column prop="batchNo"
                                   label="批号"
                                   show-overflow-tooltip />
                  <el-table-column prop="productName"
                                   label="产品名称"
                                   show-overflow-tooltip />
                  <el-table-column prop="specificationModel"
                                   label="规格型号"
                                   show-overflow-tooltip />
                  <el-table-column prop="deliveryQuantity"
                                   label="发货数量"
                                   align="center" />
                </el-table>
              </div>
              <div v-if="currentDelivery.shippingInfo.storageBlobVOs && currentDelivery.shippingInfo.storageBlobVOs.length"
                   style="margin-top: 20px;">
                <h4>发货图片</h4>
                <ImagePreview :file-list="currentDelivery.shippingInfo.storageBlobVOs" />
              </div>
            </template>
          </template>
        </el-skeleton>
      </div>
      <el-form :model="{ activities }"
               ref="formRef"
               label-position="top">
        <el-steps :active="getActiveStep()"
                  finish-status="success"
                  process-status="process"
                  align-center
                  direction="vertical">
          <el-step v-for="(activity, index) in activities"
                   :key="index"
                   finish-status="success"
                   :title="getNodeTitle(index, activities.length)"
                   :description="activity.approveNodeUser"
                   :icon="getNodeIcon(activity, index)">
            <template #icon>
              <el-icon v-if="activity.approveNodeStatus === 2"
                       color="red"
                       :size="22">
                <WarningFilled />
              </el-icon>
              <el-icon v-else-if="activity.isShen"
                       color="#1890ff"
                       :size="22">
                <Edit />
              </el-icon>
              <el-icon v-else-if="activity.approveNodeStatus === 1"
                       color="#67C23A"
                       :size="26">
                <Check />
              </el-icon>
              <el-icon v-else
                       color="#C0C4CC"
                       :size="22">
                <MoreFilled />
              </el-icon>
            </template>
            <template #title>
              <span style="color: #000000">{{ getNodeTitle(index, activities.length) }}</span>
            </template>
            <template #description>
              <div class="node-user">
                <div class="avatar-wrapper">
                  <img :src="userStore.avatar" class="user-avatar" alt=""/>
                  <img :src="userStore.avatar"
                       class="user-avatar"
                       alt="" />
                </div>
                <span style="color: #000000">{{ activity.approveNodeUser }}-{{activity.isApproval}}</span>
              </div>
              <div v-if="!activity.isShen" class="node-reason">
              <div v-if="!activity.isShen"
                   class="node-reason">
                <span>审批意见:</span>{{ activity.approveNodeReason }}
              </div>
              <div v-else-if="activity.isShen">
                <el-form-item
                  :prop="'activities.' + index + '.approveNodeReason'"
                  :rules="[{ required: true, message: '审批意见不能为空', trigger: 'blur' }]"
                >
                  <el-input v-model="activity.approveNodeReason" clearable type="textarea" :disabled="operationType === 'view'"></el-input>
                <el-form-item :prop="'activities.' + index + '.approveNodeReason'"
                              :rules="[{ required: true, message: '审批意见不能为空', trigger: 'blur' }]">
                  <el-input v-model="activity.approveNodeReason"
                            clearable
                            type="textarea"
                            :disabled="operationType === 'view'"></el-input>
                </el-form-item>
              </div>
            </template>
          </el-step>
        </el-steps>
      </el-form>
      <template #footer v-if="operationType === 'approval'">
      <template #footer
                v-if="operationType === 'approval'">
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm(2)">不通过</el-button>
          <el-button type="primary" @click="submitForm(1)">通过</el-button>
          <el-button type="primary"
                     @click="submitForm(2)">不通过</el-button>
          <el-button type="primary"
                     @click="submitForm(1)">通过</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
@@ -188,221 +306,329 @@
</template>
<script setup>
import { computed, getCurrentInstance, nextTick, reactive, ref, toRefs } from "vue";
import {
    approveProcessDetails,
    getDept,
    updateApproveNode
} from "@/api/collaborativeApproval/approvalProcess.js";
import useUserStore from "@/store/modules/user.js";
import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js";
const emit = defineEmits(['close'])
const { proxy } = getCurrentInstance()
  import {
    computed,
    getCurrentInstance,
    nextTick,
    reactive,
    ref,
    toRefs,
  } from "vue";
  import {
    approveProcessDetails,
    getDept,
    updateApproveNode,
  } from "@/api/collaborativeApproval/approvalProcess.js";
  import useUserStore from "@/store/modules/user.js";
  import {
    WarningFilled,
    Edit,
    Check,
    MoreFilled,
  } from "@element-plus/icons-vue";
  import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
  import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js";
  import { getDeliveryDetailByShippingNo } from "@/api/salesManagement/deliveryLedger.js";
  import ImagePreview from "@/components/AttachmentPreview/image/index.vue";
  const emit = defineEmits(["close"]);
  const { proxy } = getCurrentInstance();
const props = defineProps({
  approveType: {
    type: [Number, String],
    default: 0
  }
})
const dialogFormVisible = ref(false);
const operationType = ref('')
const activities = ref([])
const formRef = ref(null);
const userStore = useUserStore()
const productOptions = ref([]);
const quotationLoading = ref(false)
const currentQuotation = ref({})
const purchaseLoading = ref(false)
const currentPurchase = ref({})
const isQuotationApproval = computed(() => Number(props.approveType) === 6)
const isPurchaseApproval = computed(() => Number(props.approveType) === 5)
const data = reactive({
    form: {
        approveId: "",
        approveDeptId: "",
        approveReason: "",
        checkResult: "",
    },
});
const { form } = toRefs(data);
// èŠ‚ç‚¹æ ‡é¢˜
const getNodeTitle = (index, len) => {
  if (index === len - 1) return '结束';
  return '审批';
};
// èŽ·å–å½“å‰æ¿€æ´»æ­¥éª¤
const getActiveStep = () => {
  // å¦‚果所有 isShen éƒ½ä¸º false,返回最后一个步骤(全部完成)
  const hasActive = activities.value.some(a => a.isShen === true);
  if (!hasActive) return activities.value.length;
  // å½“前节点索引
  return activities.value.findIndex(a => a.isShen  == true);
};
// æ­¥éª¤icon
const getNodeIcon = (activity, index) => {
  if (activity.approveNodeStatus === 2) return 'el-icon-warning'; // ä¸é€šè¿‡
  if (activity.isShen) return 'Edit';
  return '';
};
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  currentQuotation.value = {}
  currentPurchase.value = {}
    form.value = {...row}
    // ç«‹å³æ¸…除表单验证状态(因为字段是disabled的,不需要验证)
    nextTick(() => {
        if (formRef.value) {
            formRef.value.clearValidate();
        }
    });
    // ç¡®ä¿é€‰é¡¹åŠ è½½å®ŒæˆåŽå†åŒ¹é…å€¼ç±»åž‹
    getProductOptions().then(() => {
        // ç¡®ä¿å€¼ç±»åž‹åŒ¹é…ï¼ˆå¦‚果选项已加载)
        if (productOptions.value.length > 0 && form.value.approveDeptId) {
            const matchedOption = productOptions.value.find(opt =>
                opt.deptId == form.value.approveDeptId ||
                String(opt.deptId) === String(form.value.approveDeptId)
            );
            if (matchedOption) {
                form.value.approveDeptId = matchedOption.deptId;
            }
        }
        // å†æ¬¡æ¸…除验证,确保选项加载后值匹配正确
        nextTick(() => {
            if (formRef.value) {
                formRef.value.clearValidate();
            }
        });
    });
  // æŠ¥ä»·å®¡æ‰¹ï¼šç”¨å®¡æ‰¹äº‹ç”±å­—段承载的"报价单号"去查报价列表
  if (isQuotationApproval.value) {
    const quotationNo = row?.approveReason;
    if (quotationNo) {
      quotationLoading.value = true
      getQuotationList({ quotationNo }).then((res) => {
        const records = res?.data?.records || []
        currentQuotation.value = records[0] || {}
      }).finally(() => {
        quotationLoading.value = false
      })
    }
  }
  // é‡‡è´­å®¡æ‰¹ï¼šç”¨å®¡æ‰¹äº‹ç”±å­—段承载的"采购合同号"去查采购详情
  if (isPurchaseApproval.value) {
    const purchaseContractNumber = row?.approveReason;
    if (purchaseContractNumber) {
      purchaseLoading.value = true
      getPurchaseByCode({ purchaseContractNumber }).then((res) => {
        currentPurchase.value = res
      }).catch((err) => {
        console.error('查询采购详情失败:', err)
        proxy.$modal.msgError('查询采购详情失败')
      }).finally(() => {
        purchaseLoading.value = false
      })
    }
  }
  approveProcessDetails(row.approveId).then((res) => {
    activities.value = res.data
    // å¢žåŠ isApproval字段
    activities.value.forEach(item => {
            if (item.url && item.url.includes('word')) {
                item.urlTem = item.url.replaceAll('word', 'img')
            } else {
                item.urlTem = item.url
            }
      if (item.approveNodeStatus === 2) {
        item.isApproval = '已驳回';
      } else if (item.approveNodeStatus === 1) {
        item.isApproval = '已同意';
      } else {
        item.isApproval = '未审批';
      }
    })
  })
}
const getProductOptions = () => {
    return getDept().then((res) => {
        productOptions.value = res.data;
    });
};
// æäº¤å®¡æ‰¹
const submitForm = (status) => {
  const filteredActivities = activities.value.filter(activity => activity.isShen);
  if (!filteredActivities || filteredActivities.length === 0) {
    proxy.$modal.msgError("未找到待审批的节点");
    return;
  }
  const currentActivity = filteredActivities[0];
  if (!currentActivity) {
    proxy.$modal.msgError("未找到待审批的节点");
    return;
  }
  currentActivity.approveNodeStatus = status;
  // åˆ¤æ–­æ˜¯å¦ä¸ºæœ€åŽä¸€æ­¥
  const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1;
  updateApproveNode({ ...currentActivity, isLast }).then(() => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
  const props = defineProps({
    approveType: {
      type: [Number, String],
      default: 0,
    },
  });
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  quotationLoading.value = false
  currentQuotation.value = {}
  purchaseLoading.value = false
  currentPurchase.value = {}
  emit('close')
};
defineExpose({
  openDialog,
});
  const dialogFormVisible = ref(false);
  const operationType = ref("");
  const activities = ref([]);
  const formRef = ref(null);
  const userStore = useUserStore();
  const productOptions = ref([]);
  const quotationLoading = ref(false);
  const currentQuotation = ref({});
  const purchaseLoading = ref(false);
  const currentPurchase = ref({});
  const deliveryLoading = ref(false);
  const currentDelivery = ref({});
  const deliveryProductList = ref([]);
  const isQuotationApproval = computed(() => Number(props.approveType) === 6);
  const isPurchaseApproval = computed(() => Number(props.approveType) === 5);
  const isDeliveryApproval = computed(() => Number(props.approveType) === 7);
  const data = reactive({
    form: {
      approveId: "",
      approveDeptId: "",
      approveReason: "",
      checkResult: "",
    },
  });
  const { form } = toRefs(data);
  // èŠ‚ç‚¹æ ‡é¢˜
  const getNodeTitle = (index, len) => {
    if (index === len - 1) return "结束";
    return "审批";
  };
  // èŽ·å–å½“å‰æ¿€æ´»æ­¥éª¤
  const getActiveStep = () => {
    // å¦‚果所有 isShen éƒ½ä¸º false,返回最后一个步骤(全部完成)
    const hasActive = activities.value.some(a => a.isShen === true);
    if (!hasActive) return activities.value.length;
    // å½“前节点索引
    return activities.value.findIndex(a => a.isShen == true);
  };
  // æ­¥éª¤icon
  const getNodeIcon = (activity, index) => {
    if (activity.approveNodeStatus === 2) return "el-icon-warning"; // ä¸é€šè¿‡
    if (activity.isShen) return "Edit";
    return "";
  };
  // æ‰“开弹框
  const openDialog = (type, row) => {
    operationType.value = type;
    dialogFormVisible.value = true;
    currentQuotation.value = {};
    currentPurchase.value = {};
    form.value = { ...row };
    // ç«‹å³æ¸…除表单验证状态(因为字段是disabled的,不需要验证)
    nextTick(() => {
      if (formRef.value) {
        formRef.value.clearValidate();
      }
    });
    // ç¡®ä¿é€‰é¡¹åŠ è½½å®ŒæˆåŽå†åŒ¹é…å€¼ç±»åž‹
    getProductOptions().then(() => {
      // ç¡®ä¿å€¼ç±»åž‹åŒ¹é…ï¼ˆå¦‚果选项已加载)
      if (productOptions.value.length > 0 && form.value.approveDeptId) {
        const matchedOption = productOptions.value.find(
          opt =>
            opt.deptId == form.value.approveDeptId ||
            String(opt.deptId) === String(form.value.approveDeptId)
        );
        if (matchedOption) {
          form.value.approveDeptId = matchedOption.deptId;
        }
      }
      // å†æ¬¡æ¸…除验证,确保选项加载后值匹配正确
      nextTick(() => {
        if (formRef.value) {
          formRef.value.clearValidate();
        }
      });
    });
    // æŠ¥ä»·å®¡æ‰¹ï¼šç”¨å®¡æ‰¹äº‹ç”±å­—段承载的"报价单号"去查报价列表
    if (isQuotationApproval.value) {
      const quotationNo = row?.approveReason;
      if (quotationNo) {
        quotationLoading.value = true;
        getQuotationList({ quotationNo })
          .then(res => {
            const records = res?.data?.records || [];
            currentQuotation.value = records[0] || {};
          })
          .finally(() => {
            quotationLoading.value = false;
          });
      }
    }
    // é‡‡è´­å®¡æ‰¹ï¼šç”¨å®¡æ‰¹äº‹ç”±å­—段承载的"采购合同号"去查采购详情
    if (isPurchaseApproval.value) {
      const purchaseContractNumber = row?.approveReason;
      if (purchaseContractNumber) {
        purchaseLoading.value = true;
        getPurchaseByCode({ purchaseContractNumber })
          .then(res => {
            currentPurchase.value = res;
          })
          .catch(err => {
            console.error("查询采购详情失败:", err);
            proxy.$modal.msgError("查询采购详情失败");
          })
          .finally(() => {
            purchaseLoading.value = false;
          });
      }
    }
    // å‘货审批:用审批事由字段承载的"发货单号"去查发货详情
    if (isDeliveryApproval.value) {
      const deliveryNo = row?.approveReason;
      if (deliveryNo) {
        deliveryLoading.value = true;
        currentDelivery.value = {};
        deliveryProductList.value = [];
        getDeliveryDetailByShippingNo({ shippingNo: deliveryNo })
          .then(res => {
            const detailData = res?.data || res || {};
            currentDelivery.value = detailData;
            deliveryProductList.value =
              detailData.shippingProductDetailDtoList || [];
          })
          .catch(err => {
            console.error("查询发货详情失败:", err);
            proxy.$modal.msgError("查询发货详情失败");
          })
          .finally(() => {
            deliveryLoading.value = false;
          });
      }
    }
    approveProcessDetails(row.approveId).then(res => {
      activities.value = res.data;
      // å¢žåŠ isApproval字段
      activities.value.forEach(item => {
        if (item.url && item.url.includes("word")) {
          item.urlTem = item.url.replaceAll("word", "img");
        } else {
          item.urlTem = item.url;
        }
        if (item.approveNodeStatus === 2) {
          item.isApproval = "已驳回";
        } else if (item.approveNodeStatus === 1) {
          item.isApproval = "已同意";
        } else {
          item.isApproval = "未审批";
        }
      });
    });
  };
  const getDeliveryProductInfoList = () => {
    const row = currentDelivery.value;
    if (!row) return [];
    const normalizeBatchNoList = value => {
      if (Array.isArray(value)) return value;
      if (typeof value === "string" && value.includes(",")) {
        return value
          .split(",")
          .map(item => item.trim())
          .filter(Boolean);
      }
      return value ? [value] : [];
    };
    const detailList = deliveryProductList.value.length
      ? deliveryProductList.value
      : [
          row.batchNoDetailList,
          row.batchNoList,
          row.shippingBatchList,
          row.shippingInfoDetailList,
          row.detailList,
          row.batchDetailList,
        ].find(value => Array.isArray(value) && value.length);
    const batchNoList = normalizeBatchNoList(row.batchNo);
    const toTableRow = (item = {}) => ({
      batchNo:
        typeof item === "string" || typeof item === "number"
          ? item
          : item.batchNo ?? item.batchNumber ?? row.batchNo ?? "--",
      productName: item.productName ?? row.productName ?? "--",
      specificationModel:
        item.specificationModel ?? item.model ?? row.specificationModel ?? "--",
      deliveryQuantity:
        item.deliveryQuantity ??
        item.quantity ??
        item.shippingQuantity ??
        row.deliveryQuantity ??
        row.quantity ??
        "--",
    });
    if (detailList?.length) {
      return detailList.map(toTableRow);
    }
    if (batchNoList.length) {
      return batchNoList.map(batchNo => toTableRow({ batchNo }));
    }
    return [toTableRow()];
  };
  const getApprovalStatusText = status => {
    const statusMap = {
      0: "待审核",
      1: "审核通过",
      2: "审核拒绝",
      3: "审核中",
    };
    return statusMap[status] || "待审核";
  };
  const getProductOptions = () => {
    return getDept().then(res => {
      productOptions.value = res.data;
    });
  };
  // æäº¤å®¡æ‰¹
  const submitForm = status => {
    const filteredActivities = activities.value.filter(
      activity => activity.isShen
    );
    if (!filteredActivities || filteredActivities.length === 0) {
      proxy.$modal.msgError("未找到待审批的节点");
      return;
    }
    const currentActivity = filteredActivities[0];
    if (!currentActivity) {
      proxy.$modal.msgError("未找到待审批的节点");
      return;
    }
    currentActivity.approveNodeStatus = status;
    // åˆ¤æ–­æ˜¯å¦ä¸ºæœ€åŽä¸€æ­¥
    const isLast =
      activities.value.findIndex(a => a.isShen) === activities.value.length - 1;
    updateApproveNode({ ...currentActivity, isLast }).then(() => {
      proxy.$modal.msgSuccess("提交成功");
      closeDia();
    });
  };
  // å…³é—­å¼¹æ¡†
  const closeDia = () => {
    proxy.resetForm("formRef");
    dialogFormVisible.value = false;
    quotationLoading.value = false;
    currentQuotation.value = {};
    purchaseLoading.value = false;
    currentPurchase.value = {};
    emit("close");
  };
  defineExpose({
    openDialog,
  });
</script>
<style scoped>
.node-user {
  margin: 10px 0;
  font-size: 16px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}
.node-status {
  color: #1890ff;
  margin-left: 8px;
  font-size: 14px;
}
.node-reason {
  font-size: 15px;
  color: #333;
  margin: 10px 0;
}
.user-avatar {
    cursor: pointer;
    width: 30px;
    height: 30px;
    border-radius: 50px;
}
.signImg {
    cursor: pointer;
    width: 200px;
    height: 60px;
}
  .node-user {
    margin: 10px 0;
    font-size: 16px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .node-status {
    color: #1890ff;
    margin-left: 8px;
    font-size: 14px;
  }
  .node-reason {
    font-size: 15px;
    color: #333;
    margin: 10px 0;
  }
  .user-avatar {
    cursor: pointer;
    width: 30px;
    height: 30px;
    border-radius: 50px;
  }
  .signImg {
    cursor: pointer;
    width: 200px;
    height: 60px;
  }
</style>
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -152,7 +152,8 @@
    startDate: "", // è¯·å‡å¼€å§‹æ—¶é—´
    endDate: "", // è¯·å‡ç»“束时间
    price: null, // æŠ¥é”€é‡‘额
    location: "" // å‡ºå·®åœ°ç‚¹
    location: "", // å‡ºå·®åœ°ç‚¹
    storageBlobDTOS: []
  },
  rules: {
    approveId: [{ required: false, message: "请输入", trigger: "blur" }],
@@ -270,7 +271,7 @@
      return
    }
  }
  form.value.storageBlobDTOList = fileList.value
  form.value.storageBlobDTOS = fileList.value
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
src/views/collaborativeApproval/approvalProcess/fileList.vue
@@ -32,8 +32,7 @@
  tableData.value = list
}
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
    proxy.$download.byUrl(row.url, row.originalFilename);
}
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
src/views/collaborativeApproval/approvalProcess/index.vue
@@ -126,20 +126,23 @@
    <!-- å¼¹çª—组件 -->
    <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="currentApproveType"></info-form-dia>
    <approval-dia ref="approvalDia" @close="handleQuery" :approveType="currentApproveType"></approval-dia>
    <FileList ref="fileListRef" />
    <FileList v-if="fileDialogVisible"
              v-model:visible="fileDialogVisible"
              record-type="approve_process"
              :record-id="recordId" />
  </div>
</template>
<script setup>
import FileList from "./fileList.vue";
import { Search, Plus, Delete, Download, RefreshRight, DocumentChecked } from "@element-plus/icons-vue";
import {onMounted, ref, computed, reactive, toRefs, nextTick, getCurrentInstance} from "vue";
import {onMounted, ref, computed, reactive, toRefs, nextTick, getCurrentInstance, defineAsyncComponent} from "vue";
import {ElMessageBox} from "element-plus";
import { useRoute } from 'vue-router';
import InfoFormDia from "@/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue";
import ApprovalDia from "@/views/collaborativeApproval/approvalProcess/components/approvalDia.vue";
import {approveProcessDelete, approveProcessListPage} from "@/api/collaborativeApproval/approvalProcess.js";
import useUserStore from "@/store/modules/user";
const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
const userStore = useUserStore();
const route = useRoute();
@@ -337,7 +340,7 @@
      name: "附件",
      type: "text",
      clickFun: (row) => {
        downLoadFile(row);
        openFilesFormDia(row);
      },
    });
  }
@@ -371,11 +374,17 @@
  page.current = 1;
  getList();
};
const fileListRef = ref(null)
const downLoadFile = (row) => {
  fileListRef.value.open(row.commonFileList)
// æ‰“开附件弹窗
const recordId =ref(0)
const fileDialogVisible = ref(false)
// æ‰“开附件弹框
const openFilesFormDia = async (row) => {
  recordId.value = row.id
  fileDialogVisible.value = true
}
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
src/views/collaborativeApproval/sealManagement/index.vue
@@ -87,10 +87,18 @@
        </el-form-item>
        <el-form-item label="紧急程度" prop="urgency">
          <el-radio-group v-model="sealForm.urgency">
            <el-radio label="normal">普通</el-radio>
            <el-radio label="urgent">紧急</el-radio>
            <el-radio label="very-urgent">特急</el-radio>
            <el-radio value="normal">普通</el-radio>
            <el-radio value="urgent">紧急</el-radio>
            <el-radio value="very-urgent">特急</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="附件上传">
          <AttachmentUploadFile
            v-model:fileList="sealForm.storageBlobDTOs"
            :limit="10"
            :fileSize="50"
            buttonText="点击上传附件"
          />
        </el-form-item>
      </el-form>
    </FormDialog>
@@ -119,8 +127,27 @@
          </el-descriptions-item>
          <el-descriptions-item label="申请原因" :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
        </el-descriptions>
        <!-- é™„件列表 -->
        <div v-if="currentSealDetail.storageBlobVOList?.length || currentSealDetail.storageBlobDTOs?.length" class="attachment-section">
          <div class="attachment-title">附件列表:</div>
          <el-table :data="currentSealDetail.storageBlobVOList || currentSealDetail.storageBlobDTOs" border class="attachment-table">
            <el-table-column label="附件名称" show-overflow-tooltip>
              <template #default="scope">
                {{ scope.row.originalFilename || scope.row.name || scope.row.fileName || '未命名文件' }}
              </template>
            </el-table-column>
            <el-table-column fixed="right" label="操作" width="150" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="previewFile(scope.row)">预览</el-button>
                <el-button link type="primary" size="small" @click="downloadFile(scope.row)">下载</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </FormDialog>
    <!-- æ–‡ä»¶é¢„览组件 -->
    <FilePreview ref="filePreviewRef" />
  </div>
</template>
@@ -134,6 +161,9 @@
import useUserStore from '@/store/modules/user'
import FormDialog from '@/components/Dialog/FormDialog.vue'
import PIMTable from '@/components/PIMTable/PIMTable.vue'
import AttachmentUploadFile from '@/components/AttachmentUpload/file/index.vue'
import FilePreview from '@/components/filePreview/index.vue'
import download from '@/plugins/download.js'
// å“åº”式数据
// ç”¨å°ç”³è¯·ç›¸å…³
@@ -143,6 +173,7 @@
const tableLoading = ref(false)
const showSealDetailDialog = ref(false)
const currentSealDetail = ref(null)
const filePreviewRef = ref(null)
const sealFormRef = ref()
const userList = ref([])
const sealForm = reactive({
@@ -152,7 +183,8 @@
  reason: '',
  approveUserId: '',
  urgency: 'normal',
  status: 'pending'
  status: 'pending',
  storageBlobDTOs: []
})
const sealRules = {
@@ -281,7 +313,8 @@
        reason: '',
        approveUserId: '',
        urgency: 'normal',
        status: 'pending'
        status: 'pending',
        storageBlobDTOs: []
      })
      }
    }).catch(err => {
@@ -301,7 +334,8 @@
    reason: '',
    approveUserId: '',
    urgency: 'normal',
    status: 'pending'
    status: 'pending',
    storageBlobDTOs: []
  })
  // æ¸…除表单验证状态
  if (sealFormRef.value) {
@@ -318,6 +352,27 @@
const viewSealDetail = (row) => {
  currentSealDetail.value = row
  showSealDetailDialog.value = true
}
// é¢„览文件
const previewFile = (row) => {
  const url = row.previewURL || row.previewUrl || row.url
  if (url && filePreviewRef.value) {
    filePreviewRef.value.open(url)
  } else {
    ElMessage.warning('文件地址无效,无法预览')
  }
}
// ä¸‹è½½æ–‡ä»¶
const downloadFile = (row) => {
  const url = row.downloadURL || row.downloadUrl || row.url
  if (url) {
    const filename = row.originalFilename || row.name || row.fileName || 'download'
    download.byUrl(url, filename)
  } else {
    ElMessage.warning('文件地址无效,无法下载')
  }
}
// å®¡æ‰¹ç”¨å°ç”³è¯·
const approveSeal = (row) => {
@@ -421,4 +476,19 @@
.ml-10 {
  margin-left: 10px;
}
.attachment-section {
  margin-top: 20px;
}
.attachment-title {
  font-size: 14px;
  color: #606266;
  margin-bottom: 10px;
  font-weight: 500;
}
.attachment-table {
  border-radius: 4px;
}
</style>
src/views/collaborativeApproval/shipmentReview/fileList.vue
@@ -29,8 +29,7 @@
  tableData.value = list
}
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
    proxy.$download.byUrl(row.url, row.originalFilename);
}
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
src/views/customerService/expiryAfterSales/components/formDia.vue
@@ -20,7 +20,7 @@
                                v-model="form.productName"
                                placeholder="请输入产品名称"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('productName')"
                            />
                        </el-form-item>
                    </el-col>
@@ -30,7 +30,7 @@
                                v-model="form.batchNumber"
                                placeholder="请输入产品批号"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('batchNumber')"
                            />
                        </el-form-item>
                    </el-col>
@@ -46,7 +46,7 @@
                                type="date"
                                placeholder="请选择临期日期"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('expiryDate')"
                            />
                        </el-form-item>
                    </el-col>
@@ -57,7 +57,7 @@
                                :min="0"
                                placeholder="请输入库存数量"
                                style="width: 100%"
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('stockQuantity')"
                            />
                        </el-form-item>
                    </el-col>
@@ -69,7 +69,7 @@
                                v-model="form.customerName"
                                placeholder="请输入客户名称"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('customerName')"
                            />
                        </el-form-item>
                    </el-col>
@@ -79,7 +79,7 @@
                                v-model="form.contactPhone"
                                placeholder="请输入联系电话"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('contactPhone')"
                            />
                        </el-form-item>
                    </el-col>
@@ -91,7 +91,7 @@
                                v-model="form.problemDesc"
                                placeholder="请输入问题描述"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('problemDesc')"
                                type="textarea"
                                :rows="3"
                            />
@@ -105,7 +105,7 @@
                                v-model="form.handlerId"
                                placeholder="请选择处理人"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('handlerId')"
                                style="width: 100%"
                            >
                                <el-option
@@ -127,7 +127,7 @@
                                type="date"
                                placeholder="请选择处理日期"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('handleDate')"
                            />
                        </el-form-item>
                    </el-col>
@@ -139,7 +139,7 @@
                                v-model="form.handleResult"
                                placeholder="请输入处理结果"
                                clearable
                                :disabled="operationType === 'view'"
                                :disabled="isFieldDisabled('handleResult')"
                                type="textarea"
                                :rows="3"
                            />
@@ -175,6 +175,8 @@
            return '新增临期售后';
        case 'edit':
            return '编辑临期售后';
        case 'handle':
            return '处理临期售后';
        case 'view':
            return '查看临期售后';
        default:
@@ -212,6 +214,13 @@
})
const { form, rules } = toRefs(data);
const userList = ref([])
const handleEditableFields = ["handlerId", "handleDate", "handleResult"];
const isFieldDisabled = (field) => {
    if (operationType.value === "view") return true;
    if (operationType.value === "handle") return !handleEditableFields.includes(field);
    return false;
};
// æ‰“开弹框
const openDialog = (type, row) => {
@@ -242,7 +251,7 @@
    } else {
        // ç¼–辑或查看时填充数据
        form.value = { ...row };
        if (type === 'edit' && !form.value.handlerId) {
        if (type === 'handle' && !form.value.handlerId) {
            form.value.handlerId = userStore.id;
            form.value.handleDate = getCurrentDate();
        }
@@ -250,36 +259,49 @@
}
const submitForm = () => {
    if (operationType.value === "handle") {
        if (!form.value.handlerId || !form.value.handleDate || !form.value.handleResult) {
            proxy.$modal.msgWarning("请填写处理人、处理日期和处理结果");
            return;
        }
        handleSubmit();
        return;
    }
    proxy.$refs["formRef"].validate(valid => {
        if (valid) {
            const submitData = {
                id: form.value.id,
                productName: form.value.productName,
                batchNumber: form.value.batchNumber,
                expireDate: form.value.expiryDate,
                stockQuantity: form.value.stockQuantity,
                customerName: form.value.customerName,
                contactPhone: form.value.contactPhone,
                disRes: form.value.problemDesc,
                status: form.value.status,
                disposeUserId: form.value.handlerId,
                disposeNickName: userList.value.find(item => item.userId === form.value.handlerId)?.nickName,
                disposeResult: form.value.handleResult,
                disDate: form.value.handleDate
            };
            const apiCall = operationType.value === 'add' ? expiryAfterSalesAdd : expiryAfterSalesUpdate;
            apiCall(submitData).then(() => {
                proxy.$modal.msgSuccess(operationType.value === 'add' ? "新增成功" : "更新成功");
                closeDia();
            }).catch(error => {
                console.error('提交数据失败:', error);
                proxy.$modal.msgError('提交数据失败,请稍后重试');
            });
            handleSubmit();
        }
    });
}
const handleSubmit = () => {
    const submitData = {
        id: form.value.id,
        productName: form.value.productName,
        batchNumber: form.value.batchNumber,
        expireDate: form.value.expiryDate,
        stockQuantity: form.value.stockQuantity,
        customerName: form.value.customerName,
        contactPhone: form.value.contactPhone,
        disRes: form.value.problemDesc,
        status: operationType.value === "handle" ? 2 : form.value.status,
        disposeUserId: form.value.handlerId,
        disposeNickName: userList.value.find(item => item.userId === form.value.handlerId)?.nickName,
        disposeResult: form.value.handleResult,
        disDate: form.value.handleDate
    };
    const apiCall = operationType.value === 'add' ? expiryAfterSalesAdd : expiryAfterSalesUpdate;
    apiCall(submitData).then(() => {
        const successText = operationType.value === "add" ? "新增成功" : operationType.value === "handle" ? "处理成功" : "更新成功";
        proxy.$modal.msgSuccess(successText);
        closeDia();
    }).catch(error => {
        console.error('提交数据失败:', error);
        proxy.$modal.msgError('提交数据失败,请稍后重试');
    });
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
    proxy.resetForm("formRef");
src/views/customerService/expiryAfterSales/index.vue
@@ -39,7 +39,7 @@
                <el-button type="danger" @click="handleDelete">删除</el-button>
            </div>
        </div>
        <div class="table_list">
            <PIMTable
                rowKey="id"
@@ -60,7 +60,7 @@
                <template #operation="{ row }">
                    <el-button type="primary" link @click="openForm('view', row)">查看</el-button>
                    <el-button type="primary" link @click="openForm('edit', row)" v-if="row.status === 1">编辑</el-button>
                    <el-button type="primary" link @click="openForm('handle', row)" v-if="row.status === 1">处理</el-button>
                </template>
            </PIMTable>
        </div>
@@ -201,7 +201,7 @@
        current: page.value.current,
        size: page.value.size
    };
    expiryAfterSalesListPage(queryParams).then(res => {
        // æ˜ å°„后端返回数据到前端表格
        tableData.value = res.data.records.map(item => ({
src/views/customerService/feedbackRegistration/components/formDia.vue
@@ -1,490 +1,507 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="新增售后单"
        width="90%"
        @close="closeDia"
    >
    <el-dialog v-model="dialogFormVisible"
               title="新增售后单"
               width="90%"
               @close="closeDia">
      <div>
        <span class="descriptions">基础资料</span>
        <el-form
            :model="form"
            label-width="140px"
            label-position="top"
            :rules="rules"
            ref="formRef"
        >
        <el-form :model="form"
                 label-width="140px"
                 label-position="top"
                 :rules="rules"
                 ref="formRef">
          <el-row :gutter="30">
            <el-col :span="4">
              <el-form-item label="客户名称:" prop="customerName">
                <el-select
                    v-model="form.customerName"
                    filterable
                    @change="customerNameChange"
                >
                  <el-option
                      v-for="item in customerNameOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
              <el-form-item label="客户名称:"
                            prop="customerName">
                <el-select v-model="form.customerName"
                           filterable
                           @change="customerNameChange">
                  <el-option v-for="item in customerNameOptions"
                             :key="item.value"
                             :label="item.label"
                             :value="item.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="售后类型:" prop="serviceType">
                <el-select
                    v-model="form.serviceType"
                    filterable
                >
                  <el-option
                      v-for="dict in serviceTypeOptions"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                  />
              <el-form-item label="售后类型:"
                            prop="serviceType">
                <el-select v-model="form.serviceType"
                           filterable>
                  <el-option v-for="dict in serviceTypeOptions"
                             :key="dict.value"
                             :label="dict.label"
                             :value="dict.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="关联销售单号:" prop="salesContractNo">
                <el-select
                    v-model="form.salesContractNo"
                    @change="associatedSalesOrderNumberChange"
                    filterable
                >
                  <el-option
                      v-for="item in associatedSalesOrderNumberOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
              <el-form-item label="关联销售单号:"
                            prop="salesContractNo">
                <el-select v-model="form.salesContractNo"
                           @change="associatedSalesOrderNumberChange"
                           filterable>
                  <el-option v-for="item in associatedSalesOrderNumberOptions"
                             :key="item.value"
                             :label="item.label"
                             :value="item.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="紧急程度:" prop="urgency">
                <el-select
                    v-model="form.urgency"
                    filterable
                >
                  <el-option
                      v-for="dict in urgencyOptions"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                  />
              <el-form-item label="紧急程度:"
                            prop="urgency">
                <el-select v-model="form.urgency"
                           filterable>
                  <el-option v-for="dict in urgencyOptions"
                             :key="dict.value"
                             :label="dict.label"
                             :value="dict.value" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="4">
              <el-form-item label="问题描述:" prop="proDesc">
                <el-input
                    v-model="form.proDesc"
                    placeholder="请输入问题描述"
                />
              <el-form-item label="问题描述:"
                            prop="proDesc">
                <el-input v-model="form.proDesc"
                          placeholder="请输入问题描述" />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
        <hr>
          <div style="padding-top: 20px">
            <div style="display: flex; justify-content: space-between">
              <span class="descriptions">关联产品</span>
            <el-button
              type="primary"
              style="margin-right: 12px; margin-bottom: 10px"
              @click="isShowProductSelectDialog = true"
            >
        <div style="padding-top: 20px">
          <div style="display: flex; justify-content: space-between">
            <span class="descriptions">关联产品</span>
            <el-button type="primary"
                       style="margin-right: 12px; margin-bottom: 10px"
                       @click="isShowProductSelectDialog = true">
              é€‰æ‹©äº§å“
            </el-button>
            </div>
            <PIMTable
                :isShowPagination="false"
                rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
            >
              <template #approveStatus="{ row }">
                <el-tag :type="getApproveStatusType(row)" size="small">
                  {{ getApproveStatusText(row) }}
                </el-tag>
              </template>
              <template #shippingStatus="{ row }">
                <el-tag :type="getShippingStatusType(row)" size="small">
                  {{ getShippingStatusText(row) }}
                </el-tag>
              </template>
            </PIMTable>
          </div>
          <PIMTable :isShowPagination="false"
                    rowKey="id"
                    :column="tableColumn"
                    :tableData="tableData">
            <template #approveStatus="{ row }">
              <el-tag :type="getApproveStatusType(row)"
                      size="small">
                {{ getApproveStatusText(row) }}
              </el-tag>
            </template>
            <template #shippingStatus="{ row }">
              <el-tag :type="getShippingStatusType(row)"
                      size="small">
                {{ getShippingStatusText(row) }}
              </el-tag>
            </template>
          </PIMTable>
        </div>
      </div>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitForm">确认</el-button>
                    <el-button @click="closeDia">取消</el-button>
                </div>
            </template>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- é€‰æ‹©äº§å“å¼¹çª— -->
    <ProductSelectDialog
      v-model="isShowProductSelectDialog"
      :products="currentSalesOrderProducts"
      :selected-ids="currentSelectedProductIds"
      @confirm="handleSelectProducts"
    />
    <ProductSelectDialog v-model="isShowProductSelectDialog"
                         :products="currentSalesOrderProducts"
                         :selected-ids="currentSelectedProductIds"
                         @confirm="handleSelectProducts" />
  </div>
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
import ProductSelectDialog from "./ProductSelectDialog.vue";
import useUserStore from "@/store/modules/user.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import {afterSalesServiceAdd, afterSalesServiceUpdate, getAllCustomerList, getSalesLedger } from "@/api/customerService/index.js";
import { getCurrentDate } from "@/utils/index.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const formRef = ref(null)
const customerNameOptions = ref([])
const userStore = useUserStore();
  import { ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
  import ProductSelectDialog from "./ProductSelectDialog.vue";
  import useUserStore from "@/store/modules/user.js";
  import { userListNoPageByTenantId } from "@/api/system/user.js";
  import {
    afterSalesServiceAdd,
    afterSalesServiceUpdate,
    getAllCustomerList,
    getSalesLedger,
  } from "@/api/customerService/index.js";
  import { getCurrentDate } from "@/utils/index.js";
  const { proxy } = getCurrentInstance();
  const emit = defineEmits(["close"]);
  const dialogFormVisible = ref(false);
  const operationType = ref("");
  const formRef = ref(null);
  const customerNameOptions = ref([]);
  const userStore = useUserStore();
const data = reactive({
    form: {
    topic: "",
    serviceType: "",
    urgency: "",
    salesLedgerId: null,
    productModelIds: "",
    customerId: null,
    salesContractNo: "",
    proDesc: "",
    customerName: ""
    },
    rules: {
    customerName: [{required: true, message: "请选择客户名称", trigger: "change"}],
    serviceType: [{required: true, message: "请选择售后类型", trigger: "change"}],
    urgency: [{required: true, message: "请选择紧急程度", trigger: "change"}],
        feedbackDate: [{required: true, message: "请选择", trigger: "change"}],
    }
})
// è‡ªå®šä¹‰æ ¡éªŒå‡½æ•°ï¼šåˆ¤æ–­æ˜¯å¦éœ€è¦æ ¡éªŒå”®åŽç¼–号
const { form, rules } = toRefs(data);
const userList = ref([])
const formatCurrency = (val) => {
  if (val === null || val === undefined || val === '') return '-'
  const num = Number(val)
  return Number.isFinite(num) ? num.toFixed(2) : '-'
}
const { post_sale_waiting_list, degree_of_urgency } = proxy.useDict(
  "post_sale_waiting_list",
  "degree_of_urgency"
);
const serviceTypeOptions = computed(() => post_sale_waiting_list?.value || []);
const urgencyOptions = computed(() => degree_of_urgency?.value || []);
const getProductRowId = (row) => {
  return row?.id ?? row?.productModelId ?? row?.modelId ?? `${row?.productCategory || row?.productName || ""}-${row?.specificationModel || row?.model || ""}-${row?.unit || ""}`
}
const normalizeProductRow = (row) => {
  return {
    ...row,
    id: getProductRowId(row),
    productCategory: row?.productCategory ?? row?.productName ?? '',
    specificationModel: row?.specificationModel ?? row?.model ?? '',
    unit: row?.unit ?? '',
    approveStatus: row?.approveStatus ?? null,
    shippingStatus: row?.shippingStatus ?? '',
    expressCompany: row?.expressCompany ?? '',
    expressNumber: row?.expressNumber ?? '',
    shippingCarNumber: row?.shippingCarNumber ?? '',
    shippingDate: row?.shippingDate ?? '',
    quantity: row?.quantity ?? 0,
    taxRate: row?.taxRate ?? 0,
    taxInclusiveUnitPrice: row?.taxInclusiveUnitPrice ?? 0,
    taxInclusiveTotalPrice: row?.taxInclusiveTotalPrice ?? 0,
    taxExclusiveTotalPrice: row?.taxExclusiveTotalPrice ?? 0,
    noQuantity: row?.noQuantity ?? 0,
  }
}
const tableColumn = ref([
  { label: "产品大类", prop: "productCategory" },
  { label: "规格型号", prop: "specificationModel" },
  { label: "单位", prop: "unit" },
  {
    label: "产品状态",
    prop: "approveStatus",
    width: 100,
    align: "center",
    dataType: "slot",
    slot: "approveStatus",
  },
  {
    label: "发货状态",
    align: "center",
    width: 140,
    dataType: "slot",
    slot: "shippingStatus",
  },
  { label: "快递公司", prop: "expressCompany", width: 140 },
  { label: "快递单号", prop: "expressNumber", width: 160 },
  { label: "发货车牌", prop: "shippingCarNumber", minWidth: 100, align: "center" },
  { label: "发货日期", prop: "shippingDate", minWidth: 100, align: "center" },
  { label: "数量", prop: "quantity", width: 100 },
  { label: "税率(%)", prop: "taxRate", width: 100 },
  {
    label: "含税单价(元)",
    prop: "taxInclusiveUnitPrice",
    width: 160,
    formatData: formatCurrency,
  },
  {
    label: "含税总价(元)",
    prop: "taxInclusiveTotalPrice",
    width: 160,
    formatData: formatCurrency,
  },
  {
    label: "不含税总价(元)",
    prop: "taxExclusiveTotalPrice",
    width: 160,
    formatData: formatCurrency,
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: 'right',
    operation: [
      {
        name: "删除",
        type: "text",
        clickFun: (row) => {
          tableData.value = tableData.value.filter(i => getProductRowId(i) !== getProductRowId(row))
        },
      },
    ],
  },
])
const tableData = ref([])
// é€‰æ‹©äº§å“å¼¹çª—
const isShowProductSelectDialog = ref(false)
const handleSelectProducts = (rows) => {
  if (!Array.isArray(rows)) return
  const existingIds = new Set(tableData.value.map(i => String(getProductRowId(i))))
  const mapped = rows
    .map(normalizeProductRow)
    .filter(r => !existingIds.has(String(getProductRowId(r))))
  tableData.value = tableData.value.concat(mapped)
}
const currentSelectedProductIds = computed(() => {
  return tableData.value.map(item => getProductRowId(item)).filter(item => item !== undefined && item !== null && item !== '')
})
const associatedSalesOrderNumberChange = () => {
  const opt = associatedSalesOrderNumberOptions.value.find(
    (item) => item.value === form.value.salesContractNo
  )
  tableData.value = (opt?.productData || []).map(normalizeProductRow)
  form.value.salesLedgerId = opt?.id || null
}
const associatedSalesOrderNumberOptions = ref([])
const currentSalesOrderProducts = computed(() => {
  const opt = associatedSalesOrderNumberOptions.value.find(
    (item) => item.value === form.value.salesContractNo
  )
  return (opt?.productData || []).map(normalizeProductRow)
})
const customerNameChange = (val) => {
  form.value.salesContractNo = "";
  form.value.salesLedgerId = null;
  tableData.value = [];
  associatedSalesOrderNumberOptions.value = [];
  const opt = customerNameOptions.value.find(item => item.value === val);
  if (opt) {
    form.value.customerId = opt.id;
  } else {
    form.value.customerId = null;
  }
  getSalesLedger({
    customerName: form.value.customerName
  }).then(res => {
    if(res.code === 200){
      associatedSalesOrderNumberOptions.value = res.data.records.map(item => ({
        label: item.salesContractNo,
        value: item.salesContractNo,
        productData:item.productData,
        id: item.id
      }))
    }
  })
}
const getApproveStatusText = (row) => {
  if (!row) return '不足'
  if (row.approveStatus === 1 && (!row.shippingDate || !row.shippingCarNumber)) {
    return '充足'
  }
  if (row.approveStatus === 0 && (row.shippingDate || row.shippingCarNumber)) {
    return '已出库'
  }
  return '不足'
}
const getApproveStatusType = (row) => {
  const statusText = getApproveStatusText(row)
  return statusText === '不足' ? 'danger' : 'success'
}
const getShippingStatusText = (row) => {
  if (!row) return '待发货'
  if (row.shippingDate || row.shippingCarNumber) {
    return '已发货'
  }
  const status = row.shippingStatus
  if (status === null || status === undefined || status === '') {
    return '待发货'
  }
  const map = {
    '待发货': '待发货',
    '待审核': '待审核',
    '审核中': '审核中',
    '审核拒绝': '审核拒绝',
    '审核通过': '审核通过',
    '已发货': '已发货'
  }
  return map[String(status).trim()] || '待发货'
}
const getShippingStatusType = (row) => {
  if (!row) return 'info'
  if (row.shippingDate || row.shippingCarNumber) {
    return 'success'
  }
  const status = row.shippingStatus
  if (status === null || status === undefined || status === '') {
    return 'info'
  }
  const map = {
    '待发货': 'info',
    '待审核': 'warning',
    '审核中': 'warning',
    '审核拒绝': 'danger',
    '审核通过': 'success',
    '已发货': 'success'
  }
  return map[String(status).trim()] || 'info'
}
// æ‰“开弹框
const openDialog =async (type, row) => {
  // è¯·æ±‚多个接口,获取数据
  let res = await getAllCustomerList({
    current: 1,
  size: 1000,
  total: 0,
  const data = reactive({
    form: {
      topic: "",
      serviceType: "",
      urgency: "",
      salesLedgerId: null,
      productModelIds: "",
      customerId: null,
      salesContractNo: "",
      proDesc: "",
      customerName: "",
    },
    rules: {
      customerName: [
        { required: true, message: "请选择客户名称", trigger: "change" },
      ],
      serviceType: [
        { required: true, message: "请选择售后类型", trigger: "change" },
      ],
      urgency: [{ required: true, message: "请选择紧急程度", trigger: "change" }],
      feedbackDate: [{ required: true, message: "请选择", trigger: "change" }],
    },
  });
  if(res.records){
    customerNameOptions.value = res.records.map(item => ({
      label: item.customerName,
      value: item.customerName,
      id: item.id
    }));
  }
  // è‡ªå®šä¹‰æ ¡éªŒå‡½æ•°ï¼šåˆ¤æ–­æ˜¯å¦éœ€è¦æ ¡éªŒå”®åŽç¼–号
  operationType.value = type;
  dialogFormVisible.value = true;
    form.value = {}
    proxy.resetForm("formRef");
    form.value.checkUserId = userStore.id;
    form.value.feedbackDate = getCurrentDate();
  // æ–°å¢žæ—¶æ¸…空已选关联产品
  if (type === "add") {
    tableData.value = []
  }
    userListNoPageByTenantId().then((res) => {
        userList.value = res.data;
    });
    if (type === "edit") {
        form.value = {...row}
    if (form.value.customerName) {
      const res = await getSalesLedger({ customerName: form.value.customerName })
      if (res?.code === 200) {
        console.log(res)
        associatedSalesOrderNumberOptions.value = (res.data?.records || []).map(item => ({
  const { form, rules } = toRefs(data);
  const userList = ref([]);
  const formatCurrency = val => {
    if (val === null || val === undefined || val === "") return "-";
    const num = Number(val);
    return Number.isFinite(num) ? num.toFixed(2) : "-";
  };
  const { post_sale_waiting_list, degree_of_urgency } = proxy.useDict(
    "post_sale_waiting_list",
    "degree_of_urgency"
  );
  const serviceTypeOptions = computed(() => post_sale_waiting_list?.value || []);
  const urgencyOptions = computed(() => degree_of_urgency?.value || []);
  const getProductRowId = row => {
    return (
      row?.id ??
      row?.productModelId ??
      row?.modelId ??
      `${row?.productCategory || row?.productName || ""}-${
        row?.specificationModel || row?.model || ""
      }-${row?.unit || ""}`
    );
  };
  const normalizeProductRow = row => {
    return {
      ...row,
      id: getProductRowId(row),
      productCategory: row?.productCategory ?? row?.productName ?? "",
      specificationModel: row?.specificationModel ?? row?.model ?? "",
      unit: row?.unit ?? "",
      approveStatus: row?.approveStatus ?? null,
      shippingStatus: row?.shippingStatus ?? "",
      expressCompany: row?.expressCompany ?? "",
      expressNumber: row?.expressNumber ?? "",
      shippingCarNumber: row?.shippingCarNumber ?? "",
      shippingDate: row?.shippingDate ?? "",
      quantity: row?.quantity ?? 0,
      taxRate: row?.taxRate ?? 0,
      taxInclusiveUnitPrice: row?.taxInclusiveUnitPrice ?? 0,
      taxInclusiveTotalPrice: row?.taxInclusiveTotalPrice ?? 0,
      taxExclusiveTotalPrice: row?.taxExclusiveTotalPrice ?? 0,
      noQuantity: row?.noQuantity ?? 0,
    };
  };
  const tableColumn = ref([
    { label: "产品大类", prop: "productCategory" },
    { label: "规格型号", prop: "specificationModel" },
    { label: "单位", prop: "unit" },
    {
      label: "产品状态",
      prop: "approveStatus",
      width: 100,
      align: "center",
      dataType: "slot",
      slot: "approveStatus",
    },
    {
      label: "发货状态",
      align: "center",
      width: 140,
      dataType: "slot",
      slot: "shippingStatus",
    },
    { label: "快递公司", prop: "expressCompany", width: 140 },
    { label: "快递单号", prop: "expressNumber", width: 160 },
    {
      label: "发货车牌",
      prop: "shippingCarNumber",
      minWidth: 100,
      align: "center",
    },
    { label: "发货日期", prop: "shippingDate", minWidth: 100, align: "center" },
    { label: "数量", prop: "quantity", width: 100 },
    { label: "税率(%)", prop: "taxRate", width: 100 },
    {
      label: "含税单价(元)",
      prop: "taxInclusiveUnitPrice",
      width: 160,
      formatData: formatCurrency,
    },
    {
      label: "含税总价(元)",
      prop: "taxInclusiveTotalPrice",
      width: 160,
      formatData: formatCurrency,
    },
    {
      label: "不含税总价(元)",
      prop: "taxExclusiveTotalPrice",
      width: 160,
      formatData: formatCurrency,
    },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      fixed: "right",
      operation: [
        {
          name: "删除",
          type: "text",
          clickFun: row => {
            tableData.value = tableData.value.filter(
              i => getProductRowId(i) !== getProductRowId(row)
            );
          },
        },
      ],
    },
  ]);
  const tableData = ref([]);
  // é€‰æ‹©äº§å“å¼¹çª—
  const isShowProductSelectDialog = ref(false);
  const handleSelectProducts = rows => {
    if (!Array.isArray(rows)) return;
    const existingIds = new Set(
      tableData.value.map(i => String(getProductRowId(i)))
    );
    const mapped = rows
      .map(normalizeProductRow)
      .filter(r => !existingIds.has(String(getProductRowId(r))));
    tableData.value = tableData.value.concat(mapped);
  };
  const currentSelectedProductIds = computed(() => {
    return tableData.value
      .map(item => getProductRowId(item))
      .filter(item => item !== undefined && item !== null && item !== "");
  });
  const associatedSalesOrderNumberChange = () => {
    const opt = associatedSalesOrderNumberOptions.value.find(
      item => item.value === form.value.salesContractNo
    );
    tableData.value = (opt?.productData || []).map(normalizeProductRow);
    form.value.salesLedgerId = opt?.id || null;
  };
  const associatedSalesOrderNumberOptions = ref([]);
  const currentSalesOrderProducts = computed(() => {
    const opt = associatedSalesOrderNumberOptions.value.find(
      item => item.value === form.value.salesContractNo
    );
    return (opt?.productData || []).map(normalizeProductRow);
  });
  const customerNameChange = val => {
    form.value.salesContractNo = "";
    form.value.salesLedgerId = null;
    tableData.value = [];
    associatedSalesOrderNumberOptions.value = [];
    const opt = customerNameOptions.value.find(item => item.value === val);
    if (opt) {
      form.value.customerId = opt.id;
    } else {
      form.value.customerId = null;
    }
    getSalesLedger({
      customerName: form.value.customerName,
    }).then(res => {
      if (res.code === 200) {
        associatedSalesOrderNumberOptions.value = res.data.records.map(item => ({
          label: item.salesContractNo,
          value: item.salesContractNo,
          productData: item.productData,
          id: item.id
        }))
          id: item.id,
        }));
      }
    });
  };
  const getApproveStatusText = row => {
    if (!row) return "不足";
    if (
      row.approveStatus === 1 &&
      (!row.shippingDate || !row.shippingCarNumber)
    ) {
      return "充足";
    }
    console.log(form.value)
    }
}
const submitForm = () => {
    proxy.$refs["formRef"].validate(valid => {
        if (valid) {
      // åŒ¹é…äº§å“åž‹å·IDs
      form.value.productModelIds = tableData.value.map(item => item.id).join(",")
            if (operationType.value === "add") {
                afterSalesServiceAdd(form.value).then(response => {
                    proxy.$modal.msgSuccess("新增成功")
                    closeDia()
                })
            } else {
                afterSalesServiceUpdate(form.value).then(response => {
                    proxy.$modal.msgSuccess("修改成功")
                    closeDia()
                })
            }
        }
    })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
    proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  emit('close')
};
defineExpose({
  openDialog,
});
    if (row.approveStatus === 0 && (row.shippingDate || row.shippingCarNumber)) {
      return "已出库";
    }
    return "不足";
  };
  const getApproveStatusType = row => {
    const statusText = getApproveStatusText(row);
    return statusText === "不足" ? "danger" : "success";
  };
  const getShippingStatusText = row => {
    if (!row) return "待发货";
    if (row.shippingDate || row.shippingCarNumber) {
      return "已发货";
    }
    const status = row.shippingStatus;
    if (status === null || status === undefined || status === "") {
      return "待发货";
    }
    const map = {
      å¾…发货: "待发货",
      å¾…审核: "待审核",
      å®¡æ ¸ä¸­: "审核中",
      å®¡æ ¸æ‹’绝: "审核拒绝",
      å®¡æ ¸é€šè¿‡: "审核通过",
      å·²å‘è´§: "已发货",
    };
    return map[String(status).trim()] || "待发货";
  };
  const getShippingStatusType = row => {
    if (!row) return "info";
    if (row.shippingDate || row.shippingCarNumber) {
      return "success";
    }
    const status = row.shippingStatus;
    if (status === null || status === undefined || status === "") {
      return "info";
    }
    const map = {
      å¾…发货: "info",
      å¾…审核: "warning",
      å®¡æ ¸ä¸­: "warning",
      å®¡æ ¸æ‹’绝: "danger",
      å®¡æ ¸é€šè¿‡: "success",
      å·²å‘è´§: "success",
    };
    return map[String(status).trim()] || "info";
  };
  // æ‰“开弹框
  const openDialog = async (type, row) => {
    // è¯·æ±‚多个接口,获取数据
    let res = await getAllCustomerList({
      current: 1,
      size: 1000,
      total: 0,
    });
    console.log(res, "res");
    if (res.data.records) {
      customerNameOptions.value = res.data.records.map(item => ({
        label: item.customerName,
        value: item.customerName,
        id: item.id,
      }));
    } else {
    }
    operationType.value = type;
    dialogFormVisible.value = true;
    form.value = {};
    proxy.resetForm("formRef");
    form.value.checkUserId = userStore.id;
    form.value.feedbackDate = getCurrentDate();
    // æ–°å¢žæ—¶æ¸…空已选关联产品
    if (type === "add") {
      tableData.value = [];
    }
    userListNoPageByTenantId().then(res => {
      userList.value = res.data;
    });
    if (type === "edit") {
      form.value = { ...row };
      if (form.value.customerName) {
        const res = await getSalesLedger({
          customerName: form.value.customerName,
        });
        if (res?.code === 200) {
          console.log(res);
          associatedSalesOrderNumberOptions.value = (res.data?.records || []).map(
            item => ({
              label: item.salesContractNo,
              value: item.salesContractNo,
              productData: item.productData,
              id: item.id,
            })
          );
        }
      }
      console.log(form.value);
    }
  };
  const submitForm = () => {
    proxy.$refs["formRef"].validate(valid => {
      if (valid) {
        // åŒ¹é…äº§å“åž‹å·IDs
        form.value.productModelIds = tableData.value
          .map(item => item.id)
          .join(",");
        if (operationType.value === "add") {
          afterSalesServiceAdd(form.value).then(response => {
            proxy.$modal.msgSuccess("新增成功");
            closeDia();
          });
        } else {
          afterSalesServiceUpdate(form.value).then(response => {
            proxy.$modal.msgSuccess("修改成功");
            closeDia();
          });
        }
      }
    });
  };
  // å…³é—­å¼¹æ¡†
  const closeDia = () => {
    proxy.resetForm("formRef");
    dialogFormVisible.value = false;
    emit("close");
  };
  defineExpose({
    openDialog,
  });
</script>
<style scoped lang="scss">
.descriptions {
  margin-bottom: 20px;
  display: inline-block;
  font-size: 1rem;
  font-weight: 600;
  padding-left: 12px;
  position: relative;
}
  .descriptions {
    margin-bottom: 20px;
    display: inline-block;
    font-size: 1rem;
    font-weight: 600;
    padding-left: 12px;
    position: relative;
  }
.descriptions::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 1rem;
  background-color: #002FA7; /* Element é»˜è®¤çº¢è‰² */
  border-radius: 2px;
}
  .descriptions::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 4px;
    height: 1rem;
    background-color: #002fa7; /* Element é»˜è®¤çº¢è‰² */
    border-radius: 2px;
  }
</style>
src/views/equipmentManagement/inspectionManagement/components/formDia.vue
@@ -26,6 +26,21 @@
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="巡检项目" prop="inspectionProject">
              <el-input v-model="form.inspectionProject" placeholder="请输入巡检项目" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否启用" prop="isEnabled">
              <el-radio-group v-model="form.isEnabled">
                <el-radio :value="1">是</el-radio>
                <el-radio :value="0">否</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="备注" prop="remarks">
              <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" />
            </el-form-item>
@@ -118,6 +133,8 @@
    taskName: undefined,
    inspector: '',
    inspectorIds: '',
    inspectionProject: '',
    isEnabled: 1,
    remarks: '',
    frequencyType: '',
    frequencyDetail: '',
@@ -245,6 +262,8 @@
    taskName: undefined,
    inspector: '',
    inspectorIds: '',
    inspectionProject: '',
    isEnabled: 1,
    remarks: '',
    frequencyType: '',
    frequencyDetail: '',
src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,680 @@
<template>
  <FormDialog
    v-model="dialogVisible"
    title="上传巡检记录"
    width="980px"
    @close="handleClose"
    @cancel="handleClose"
  >
    <main class="upload-content">
      <el-card v-if="taskInfo" class="section-card">
        <el-descriptions :column="1" border>
          <el-descriptions-item label="巡检任务名称">
            {{ taskInfo.taskName || "-" }}
          </el-descriptions-item>
          <el-descriptions-item label="巡检项目">
            {{ taskInfo.inspectionProject || "-" }}
          </el-descriptions-item>
          <el-descriptions-item label="备注">
            {{ taskInfo.remarks || "-" }}
          </el-descriptions-item>
        </el-descriptions>
      </el-card>
      <el-card class="section-card">
        <h3>巡检状态</h3>
        <el-radio-group v-model="hasException">
          <el-radio-button :value="false">正常</el-radio-button>
          <el-radio-button :value="true">存在异常</el-radio-button>
        </el-radio-group>
      </el-card>
      <el-card v-if="hasException === true" class="section-card">
        <h3>异常描述</h3>
        <el-input
          v-model="abnormalDescription"
          type="textarea"
          maxlength="500"
          show-word-limit
          :rows="4"
          placeholder="请描述异常情况..."
        />
      </el-card>
      <el-card v-if="hasException === true" class="section-card">
        <el-tabs v-model="currentUploadType">
          <el-tab-pane label="生产前" name="before" />
          <el-tab-pane label="生产中" name="after" />
          <el-tab-pane label="生产后" name="issue" />
        </el-tabs>
        <div class="upload-buttons">
          <el-upload
            :show-file-list="false"
            :http-request="uploadFile"
            :disabled="getCurrentFiles().length >= uploadConfig.limit || uploading"
            accept="image/*"
          >
            <el-button type="primary" :loading="uploading">
              <el-icon><Camera /></el-icon>
              é€‰æ‹©å›¾ç‰‡
            </el-button>
          </el-upload>
          <el-upload
            :show-file-list="false"
            :http-request="uploadFile"
            :disabled="getCurrentFiles().length >= uploadConfig.limit || uploading"
            accept="video/*"
          >
            <el-button type="success" :loading="uploading">
              <el-icon><VideoCamera /></el-icon>
              é€‰æ‹©è§†é¢‘
            </el-button>
          </el-upload>
        </div>
        <el-progress
          v-if="uploading"
          :percentage="uploadProgress"
          class="upload-progress"
        />
        <div v-if="getCurrentFiles().length" class="file-list">
          <div
            v-for="(file, index) in getCurrentFiles()"
            :key="file.uid || file.id || index"
            class="file-item"
          >
            <div class="file-preview-container">
              <el-image
                v-if="file.type === 'image' || !file.type"
                :src="file.url || file.tempFilePath || file.path || file.downloadUrl"
                fit="cover"
                class="file-preview"
                :preview-src-list="[file.url || file.tempFilePath || file.path || file.downloadUrl]"
                preview-teleported
              />
              <div v-else class="video-preview" @click="previewVideo(file)">
                <el-icon><VideoCamera /></el-icon>
                <span>视频</span>
              </div>
              <el-button
                class="delete-btn"
                type="danger"
                circle
                size="small"
                @click="removeFile(index)"
              >
                <el-icon><Close /></el-icon>
              </el-button>
            </div>
            <div class="file-info">
              <div class="file-name">
                {{ file.bucketFilename || file.name || (file.type === "image" ? "图片" : "视频") }}
              </div>
              <div class="file-size">{{ formatFileSize(file.size) }}</div>
            </div>
          </div>
        </div>
        <el-empty
          v-else
          :description="`请选择要上传的${getUploadTypeText()}图片或视频`"
        />
        <el-alert
          class="upload-summary"
          type="info"
          :closable="false"
          :title="`生产前:${beforeModelValue.length}个文件 | ç”Ÿäº§ä¸­ï¼š${afterModelValue.length}个文件 | ç”Ÿäº§åŽï¼š${issueModelValue.length}个文件`"
        />
      </el-card>
      <el-result
        v-if="hasException === false"
        icon="success"
        title="设备运行正常"
        sub-title="无需上传照片"
      />
    </main>
    <template #footer>
      <footer class="footer-buttons">
        <el-button type="primary" @click="submitUpload">提交</el-button>
        <el-button v-if="hasException === true" type="warning" @click="goToRepair">
          æ–°å¢žæŠ¥ä¿®
        </el-button>
        <el-button @click="handleClose">取消</el-button>
      </footer>
    </template>
  </FormDialog>
  <el-dialog
    v-model="showVideoDialog"
    :title="currentVideoFile?.originalFilename || currentVideoFile?.name || '视频预览'"
    width="720px"
  >
    <video
      v-if="currentVideoFile"
      :src="currentVideoFile.url || currentVideoFile.downloadUrl"
      class="video-player"
      controls
      autoplay
    />
  </el-dialog>
</template>
<script setup>
import { computed, ref } from "vue";
import { useRouter } from "vue-router";
import { ElLoading, ElMessage, ElMessageBox } from "element-plus";
import { Camera, Close, VideoCamera } from "@element-plus/icons-vue";
import axios from "axios";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { uploadInspectionTask } from "@/api/inspectionManagement/index.js";
import { getToken } from "@/utils/auth";
const emit = defineEmits(["closeDia", "success"]);
const router = useRouter();
const dialogVisible = ref(false);
const taskInfo = ref(null);
const uploading = ref(false);
const uploadProgress = ref(0);
const beforeModelValue = ref([]);
const afterModelValue = ref([]);
const issueModelValue = ref([]);
const currentUploadType = ref("before");
const hasException = ref(null);
const abnormalDescription = ref("");
const showVideoDialog = ref(false);
const currentVideoFile = ref(null);
const uploadConfig = {
  action: "/common/upload",
  limit: 10,
  fileSize: 50,
  fileType: ["jpg", "jpeg", "png", "mp4", "mov"],
};
const uploadFileUrl = computed(
  () => `${import.meta.env.VITE_APP_BASE_API}${uploadConfig.action}`
);
const processFileUrl = fileUrl => {
  if (!fileUrl) return "";
  let currentUrl = String(fileUrl);
  if (currentUrl.includes("\\")) {
    const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads");
    if (uploadsIndex > -1) {
      currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`;
    } else {
      const fileName = currentUrl.split("\\").pop();
      currentUrl = `/uploads/${fileName}`;
    }
  }
  if (currentUrl && !currentUrl.startsWith("http")) {
    if (!currentUrl.startsWith("/")) {
      currentUrl = `/${currentUrl}`;
    }
    currentUrl = __BASE_API__ + currentUrl;
  }
  return currentUrl;
};
const normalizeList = (list, fileType) => {
  if (!Array.isArray(list)) return [];
  return list.filter(Boolean).map(item => {
    let currentType = item.type;
    if (!currentType && item.contentType) {
      currentType = item.contentType.startsWith("video") ? "video" : "image";
    } else if (!currentType) {
      currentType = fileType || "image";
    }
    return {
      ...item,
      url: processFileUrl(item.url || item.previewURL || item.downloadUrl || item.path || ""),
      downloadUrl: processFileUrl(
        item.downloadUrl || item.url || item.previewURL || item.path || ""
      ),
      name: item.name || item.originalFilename || item.bucketFilename,
      tempId: item.tempId || item.id || item.tempFileId,
      tempFileId: item.tempFileId || item.tempId || item.id,
      size: item.size || item.byteSize || 0,
      type: currentType,
      status: "success",
      uid: item.uid || `${Date.now()}-${Math.random()}`,
    };
  });
};
const resetState = () => {
  taskInfo.value = null;
  beforeModelValue.value = [];
  afterModelValue.value = [];
  issueModelValue.value = [];
  currentUploadType.value = "before";
  hasException.value = null;
  abnormalDescription.value = "";
  uploading.value = false;
  uploadProgress.value = 0;
  showVideoDialog.value = false;
  currentVideoFile.value = null;
};
const openDialog = row => {
  const raw = JSON.parse(JSON.stringify(row?.__raw || row || {}));
  taskInfo.value = raw;
  beforeModelValue.value = normalizeList(
    raw.commonFileListBeforeVO || raw.commonFileListBefore || [],
    "image"
  );
  afterModelValue.value = normalizeList(
    raw.commonFileListVO || raw.commonFileList || [],
    "image"
  );
  issueModelValue.value = normalizeList(
    raw.commonFileListAfterVO || raw.commonFileListAfter || [],
    "image"
  );
  abnormalDescription.value = raw.abnormalDescription || "";
  if (raw.hasException !== undefined && raw.hasException !== null) {
    hasException.value = raw.hasException;
  } else if (raw.inspectionResult !== undefined && raw.inspectionResult !== null) {
    hasException.value = String(raw.inspectionResult) === "0";
  } else {
    hasException.value = null;
  }
  if (
    hasException.value !== true &&
    (beforeModelValue.value.length || afterModelValue.value.length || issueModelValue.value.length)
  ) {
    hasException.value = true;
  }
  dialogVisible.value = true;
};
const handleClose = () => {
  dialogVisible.value = false;
  resetState();
  emit("closeDia");
};
const getCurrentFiles = () => {
  if (currentUploadType.value === "before") return beforeModelValue.value;
  if (currentUploadType.value === "after") return afterModelValue.value;
  if (currentUploadType.value === "issue") return issueModelValue.value;
  return [];
};
const getUploadTypeText = () => {
  if (currentUploadType.value === "before") return "生产前";
  if (currentUploadType.value === "after") return "生产中";
  if (currentUploadType.value === "issue") return "生产后";
  return "";
};
const getTabType = () => {
  if (currentUploadType.value === "before") return 10;
  if (currentUploadType.value === "after") return 11;
  if (currentUploadType.value === "issue") return 12;
  return 10;
};
const previewVideo = file => {
  currentVideoFile.value = file;
  showVideoDialog.value = true;
};
const uploadFile = async uploadRequest => {
  const rawFile = uploadRequest.file;
  if (getCurrentFiles().length >= uploadConfig.limit) {
    ElMessage.warning(`最多只能选择${uploadConfig.limit}个文件`);
    return;
  }
  const ext = rawFile.name.split(".").pop()?.toLowerCase();
  if (!uploadConfig.fileType.includes(ext)) {
    ElMessage.warning(`文件格式不支持,请上传 ${uploadConfig.fileType.join("/")} æ ¼å¼`);
    return;
  }
  if (rawFile.size > uploadConfig.fileSize * 1024 * 1024) {
    ElMessage.warning(`文件大小不能超过 ${uploadConfig.fileSize}MB`);
    return;
  }
  const token = getToken();
  if (!token) {
    ElMessage.warning("用户未登录");
    return;
  }
  const formData = new FormData();
  formData.append("files", rawFile);
  formData.append("type", getTabType());
  uploading.value = true;
  uploadProgress.value = 0;
  try {
    const { data } = await axios.post(uploadFileUrl.value, formData, {
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "multipart/form-data",
      },
      onUploadProgress: event => {
        if (event.total) {
          uploadProgress.value = Math.round((event.loaded / event.total) * 100);
        }
      },
    });
    if (data.code !== 200) {
      ElMessage.error(data.msg || "上传失败");
      return;
    }
    const resultData = Array.isArray(data.data) ? data.data[0] : data.data;
    const finalUrl = processFileUrl(
      resultData.url || resultData.previewURL || resultData.downloadUrl || ""
    );
    const finalName = resultData.name || resultData.originalFilename || resultData.bucketFilename;
    const finalId = resultData.tempId || resultData.id || resultData.tempFileId;
    const uploadedFile = {
      ...resultData,
      url: finalUrl,
      downloadUrl: finalUrl,
      name: finalName,
      tempId: finalId,
      tempFileId: resultData.tempFileId || finalId,
      size: rawFile.size || resultData.size || resultData.byteSize || 0,
      type: rawFile.type?.startsWith("video") ? "video" : "image",
      status: "success",
      uid: `${Date.now()}-${Math.random()}`,
    };
    getCurrentFiles().push(uploadedFile);
    ElMessage.success("上传成功");
  } catch (error) {
    ElMessage.error(error?.message || "上传失败");
  } finally {
    uploading.value = false;
  }
};
const buildFileItem = item => ({
  id: item?.id,
  tempId: item?.tempId,
  tempFileId: item?.tempFileId,
  url: item?.downloadUrl || item?.url || "",
  downloadUrl: item?.downloadUrl || item?.url || "",
  name: item?.name,
  bucketFilename: item?.bucketFilename || item?.name,
  originalFilename: item?.originalFilename || item?.name,
  size: item?.size || 0,
  byteSize: item?.byteSize || item?.size || 0,
  contentType: item?.contentType || "",
  type: item?.type,
});
const submitUpload = async () => {
  if (hasException.value === null) {
    ElMessage.warning("请选择巡检状态");
    return;
  }
  if (hasException.value === true) {
    const totalFiles =
      beforeModelValue.value.length +
      afterModelValue.value.length +
      issueModelValue.value.length;
    if (!totalFiles) {
      ElMessage.warning("请上传异常照片或视频");
      return;
    }
    if (!abnormalDescription.value.trim()) {
      ElMessage.warning("请填写异常描述");
      return;
    }
  }
  const loading = ElLoading.service({
    text: "提交中...",
    background: "rgba(0, 0, 0, 0.3)",
  });
  try {
    const allFiles = [
      ...beforeModelValue.value,
      ...afterModelValue.value,
      ...issueModelValue.value,
    ];
    const tempFileIds = allFiles
      .map(item => item?.tempId ?? item?.tempFileId ?? item?.id)
      .filter(Boolean);
    const {
      createTime,
      updateTime,
      storageBlobDTO,
      commonFileListAfterVO,
      commonFileListVO,
      commonFileListBeforeVO,
      commonFileListAfter,
      commonFileList,
      commonFileListBefore,
      __raw,
      ...baseTaskInfo
    } = taskInfo.value || {};
    const submitData = {
      ...baseTaskInfo,
      commonFileListBeforeDTO: beforeModelValue.value.map(buildFileItem),
      commonFileListDTO: afterModelValue.value.map(buildFileItem),
      commonFileListAfterDTO: issueModelValue.value.map(buildFileItem),
      hasException: hasException.value,
      inspectionResult: hasException.value ? 0 : 1,
      abnormalDescription: abnormalDescription.value,
      tempFileIds,
    };
    const result = await uploadInspectionTask(submitData);
    if (result && (result.code === 200 || result.success)) {
      ElMessage.success("提交成功");
      dialogVisible.value = false;
      resetState();
      emit("success");
      emit("closeDia");
    } else {
      ElMessage.error(result?.msg || result?.message || "提交失败");
    }
  } catch (error) {
    ElMessage.error(error?.message || "提交失败");
  } finally {
    loading.close();
  }
};
const removeFile = async index => {
  try {
    await ElMessageBox.confirm("确定要删除这个文件吗?", "确认删除", {
      type: "warning",
    });
    getCurrentFiles().splice(index, 1);
  } catch {}
};
const goToRepair = () => {
  const taskData = {
    taskId: taskInfo.value?.taskId || taskInfo.value?.id,
    taskName: taskInfo.value?.taskName,
    inspectionLocation: taskInfo.value?.inspectionLocation,
    inspector: taskInfo.value?.inspector,
    hasException: hasException.value,
    inspectionResult: hasException.value ? 0 : 1,
    commonFileListBeforeDTO: beforeModelValue.value.map(buildFileItem),
    commonFileListDTO: afterModelValue.value.map(buildFileItem),
    commonFileListAfterDTO: issueModelValue.value.map(buildFileItem),
    uploadedFiles: {
      before: beforeModelValue.value,
      after: afterModelValue.value,
      issue: issueModelValue.value,
    },
  };
  sessionStorage.setItem("repairTaskInfo", JSON.stringify(taskData));
  router.push("/equipmentManagement/repair/add");
};
const formatFileSize = size => {
  if (!size) return "0 B";
  const units = ["B", "KB", "MB", "GB"];
  let index = 0;
  let fileSize = size;
  while (fileSize >= 1024 && index < units.length - 1) {
    fileSize /= 1024;
    index += 1;
  }
  return `${fileSize.toFixed(2)} ${units[index]}`;
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
.inspection-upload-page {
  min-height: 70vh;
  background: #f5f7fa;
  padding: 20px 20px 90px;
  box-sizing: border-box;
}
.upload-content {
  max-width: 960px;
  margin: 20px auto 0;
}
.section-card {
  margin-bottom: 16px;
}
.section-card h3 {
  margin: 0 0 16px;
  font-size: 16px;
}
.upload-buttons {
  display: flex;
  gap: 12px;
  margin: 16px 0;
}
.upload-progress {
  margin-bottom: 16px;
}
.file-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 12px;
}
.file-preview-container {
  position: relative;
  aspect-ratio: 1;
  border-radius: 8px;
  overflow: hidden;
  background: #f2f3f5;
}
.file-preview {
  width: 100%;
  height: 100%;
}
.video-preview {
  width: 100%;
  height: 100%;
  background: #303133;
  color: #fff;
  display: flex;
  gap: 6px;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.delete-btn {
  position: absolute;
  top: 6px;
  right: 6px;
}
.file-info {
  margin-top: 6px;
  font-size: 12px;
}
.file-name {
  color: #606266;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-size {
  color: #909399;
  margin-top: 2px;
}
.upload-summary {
  margin-top: 16px;
}
.footer-buttons {
  position: sticky;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 14px 20px 0;
  background: #f5f7fa;
  display: flex;
  justify-content: center;
  gap: 12px;
}
.video-player {
  width: 100%;
  max-height: 70vh;
  background: #000;
}
</style>
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
@@ -1,210 +1,226 @@
<template>
  <div>
    <el-dialog title="查看附件"
               v-model="dialogVisitable" width="800px" @close="cancel">
    <el-dialog title="查看附件" v-model="dialogVisitable" width="800px" @close="cancel">
      <div class="upload-container">
        <!-- ç”Ÿäº§å‰ -->
        <div class="form-container">
          <div class="title">生产前</div>
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <img v-for="(item, index) in beforeProductionImgs" :key="index"
                 @click="showMedia(beforeProductionImgs, index, 'image')"
                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
          <div class="media-list">
            <img
              v-for="(item, index) in beforeProductionImgs"
              :key="`before-img-${index}`"
              :src="item"
              alt=""
              class="media-image"
              @click="showMedia(beforeProductionImgs, index, 'image')"
            />
          </div>
          <!-- è§†é¢‘列表 -->
          <div style="display: flex; flex-wrap: wrap;">
          <div class="media-list">
            <div
                v-for="(videoUrl, index) in beforeProductionVideos"
                :key="index"
                @click="showMedia(beforeProductionVideos, index, 'video')"
                style="position: relative; margin: 10px; cursor: pointer;"
              v-for="(videoUrl, index) in beforeProductionVideos"
              :key="`before-video-${index}`"
              class="video-item"
              @click="showMedia(beforeProductionVideos, index, 'video')"
            >
              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
                <img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
              <div class="video-thumb">
                <img src="@/assets/images/video.png" alt="播放" class="video-icon" />
              </div>
              <div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
              <div class="video-text">点击播放</div>
            </div>
          </div>
        </div>
        <!-- ç”Ÿäº§åŽ -->
        <div class="form-container">
          <div class="title">生产中</div>
          <div class="media-list">
            <img
              v-for="(item, index) in afterProductionImgs"
              :key="`during-img-${index}`"
              :src="item"
              alt=""
              class="media-image"
              @click="showMedia(afterProductionImgs, index, 'image')"
            />
          </div>
          <div class="media-list">
            <div
              v-for="(videoUrl, index) in afterProductionVideos"
              :key="`during-video-${index}`"
              class="video-item"
              @click="showMedia(afterProductionVideos, index, 'video')"
            >
              <div class="video-thumb">
                <img src="@/assets/images/video.png" alt="播放" class="video-icon" />
              </div>
              <div class="video-text">点击播放</div>
            </div>
          </div>
        </div>
        <div class="form-container">
          <div class="title">生产后</div>
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <img v-for="(item, index) in afterProductionImgs" :key="index"
                 @click="showMedia(afterProductionImgs, index, 'image')"
                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
          <div class="media-list">
            <img
              v-for="(item, index) in productionIssuesImgs"
              :key="`after-img-${index}`"
              :src="item"
              alt=""
              class="media-image"
              @click="showMedia(productionIssuesImgs, index, 'image')"
            />
          </div>
          <!-- è§†é¢‘列表 -->
          <div style="display: flex; flex-wrap: wrap;">
          <div class="media-list">
            <div
                v-for="(videoUrl, index) in afterProductionVideos"
                :key="index"
                @click="showMedia(afterProductionVideos, index, 'video')"
                style="position: relative; margin: 10px; cursor: pointer;"
              v-for="(videoUrl, index) in productionIssuesVideos"
              :key="`after-video-${index}`"
              class="video-item"
              @click="showMedia(productionIssuesVideos, index, 'video')"
            >
              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
                <img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
              <div class="video-thumb">
                <img src="@/assets/images/video.png" alt="播放" class="video-icon" />
              </div>
              <div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
            </div>
          </div>
        </div>
        <!-- ç”Ÿäº§é—®é¢˜ -->
        <div class="form-container">
          <div class="title">生产问题</div>
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <img v-for="(item, index) in productionIssuesImgs" :key="index"
                 @click="showMedia(productionIssuesImgs, index, 'image')"
                 :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt="">
          </div>
          <!-- è§†é¢‘列表 -->
          <div style="display: flex; flex-wrap: wrap;">
            <div
                v-for="(videoUrl, index) in productionIssuesVideos"
                :key="index"
                @click="showMedia(productionIssuesVideos, index, 'video')"
                style="position: relative; margin: 10px; cursor: pointer;"
            >
              <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;">
                <img src="@/assets/images/video.png" alt="播放" style="width: 30px; height: 30px; opacity: 0.8;" />
              </div>
              <div style="text-align: center; font-size: 12px; color: #666;">点击播放</div>
              <div class="video-text">点击播放</div>
            </div>
          </div>
        </div>
      </div>
    </el-dialog>
    <!-- ç»Ÿä¸€åª’体查看器 -->
    <div v-if="isMediaViewerVisible" class="media-viewer-overlay" @click.self="closeMediaViewer">
      <div class="media-viewer-content" @click.stop>
        <!-- å›¾ç‰‡ -->
        <vue-easy-lightbox
            v-if="mediaType === 'image'"
            :visible="isMediaViewerVisible"
            :imgs="mediaList"
            :index="currentMediaIndex"
            @hide="closeMediaViewer"
        ></vue-easy-lightbox>
        <!-- è§†é¢‘ -->
        <div v-else-if="mediaType === 'video'" style="position: relative;">
          <video
              :src="mediaList[currentMediaIndex]"
              autoplay
              controls
              style="max-width: 90vw; max-height: 80vh;"
          />
          v-if="mediaType === 'image'"
          :visible="isMediaViewerVisible"
          :imgs="mediaList"
          :index="currentMediaIndex"
          @hide="closeMediaViewer"
        />
        <div v-else-if="mediaType === 'video'" class="video-player-wrap">
          <video :src="mediaList[currentMediaIndex]" autoplay controls class="video-player" />
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import VueEasyLightbox from 'vue-easy-lightbox';
const { proxy } = getCurrentInstance();
// æŽ§åˆ¶å¼¹çª—显示
<script setup>
import { ref } from "vue";
import VueEasyLightbox from "vue-easy-lightbox";
const dialogVisitable = ref(false);
// å›¾ç‰‡æ•°ç»„
const beforeProductionImgs = ref([]);
const afterProductionImgs = ref([]);
const productionIssuesImgs = ref([]);
// è§†é¢‘数组
const beforeProductionVideos = ref([]);
const afterProductionVideos = ref([]);
const productionIssuesVideos = ref([]);
// åª’体查看器状态
const isMediaViewerVisible = ref(false);
const currentMediaIndex = ref(0);
const mediaList = ref([]); // å­˜å‚¨å½“前要查看的媒体列表(含图片和视频对象)
const mediaType = ref('image'); // image | video
const mediaList = ref([]);
const mediaType = ref("image");
// å¤„理每一类数据:分离图片和视频
function processItems(items) {
const processFileUrl = fileUrl => {
  if (!fileUrl) return "";
  let currentUrl = String(fileUrl);
  if (currentUrl.includes("\\")) {
    const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads");
    if (uploadsIndex > -1) {
      currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`;
    } else {
      const fileName = currentUrl.split("\\").pop();
      currentUrl = `/uploads/${fileName}`;
    }
  }
  if (currentUrl && !currentUrl.startsWith("http")) {
    if (!currentUrl.startsWith("/")) {
      currentUrl = `/${currentUrl}`;
    }
    currentUrl = __BASE_API__ + currentUrl;
  }
  return currentUrl;
};
const processItems = items => {
  const images = [];
  const videos = [];
  // æ£€æŸ¥ items æ˜¯å¦å­˜åœ¨ä¸”为数组
  if (!items || !Array.isArray(items)) {
  if (!Array.isArray(items)) {
    return { images, videos };
  }
  items.forEach(item => {
    if (!item || !item.previewURL || !item.contentType) return;
    if (!item) return;
    // å¤„理文件 URL
    const fileUrl = item.previewURL;
    const contentType = String(item.contentType).toLowerCase();
    const fileUrl = processFileUrl(
      item.previewURL || item.url || item.downloadUrl || item.path || ""
    );
    const contentType = String(item.contentType || "").toLowerCase();
    // æ ¹æ® contentType åˆ¤æ–­æ˜¯å›¾ç‰‡è¿˜æ˜¯è§†é¢‘
    if (contentType.startsWith('image/')) {
      images.push(fileUrl);
    } else if (contentType.startsWith('video/')) {
    if (!fileUrl) return;
    if (contentType.startsWith("video/")) {
      videos.push(fileUrl);
      return;
    }
  });
  return { images, videos };
}
// æ‰“开弹窗并加载数据
const openDialog = async (row) => {
  // ä½¿ç”¨æ­£ç¡®çš„字段名:commonFileListBefore, commonFileListAfter
  const { images: beforeImgs, videos: beforeVids } = processItems(row.commonFileListBeforeVO || []);
  const { images: afterImgs, videos: afterVids } = processItems(row.commonFileListAfterVO || []);
  const { images: issueImgs, videos: issueVids } = processItems(row.commonFileListVO || []);
    images.push(fileUrl);
  });
  return { images, videos };
};
const openDialog = row => {
  const { images: beforeImgs, videos: beforeVids } = processItems(
    row.commonFileListBeforeVO || []
  );
  const { images: afterImgs, videos: afterVids } = processItems(
    row.commonFileListVO || []
  );
  const { images: issueImgs, videos: issueVids } = processItems(
    row.commonFileListAfterVO || []
  );
  beforeProductionImgs.value = beforeImgs;
  beforeProductionVideos.value = beforeVids;
  afterProductionImgs.value = afterImgs;
  afterProductionVideos.value = afterVids;
  productionIssuesImgs.value = issueImgs;
  productionIssuesVideos.value = issueVids;
  dialogVisitable.value = true;
};
// æ˜¾ç¤ºåª’体(图片 or è§†é¢‘)
function showMedia(mediaArray, index, type) {
  mediaList.value = mediaArray;
const showMedia = (items, index, type) => {
  mediaList.value = items;
  currentMediaIndex.value = index;
  mediaType.value = type;
  isMediaViewerVisible.value = true;
}
};
// å…³é—­åª’体查看器
function closeMediaViewer() {
const closeMediaViewer = () => {
  isMediaViewerVisible.value = false;
  mediaList.value = [];
  mediaType.value = 'image';
}
  mediaType.value = "image";
};
// è¡¨å•关闭方法
const cancel = () => {
  dialogVisitable.value = false;
};
defineExpose({ openDialog });
</script>
<style scoped lang="scss">
.upload-container {
  display: flex;
@@ -213,7 +229,7 @@
  padding: 20px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  .form-container {
    flex: 1;
    width: 100%;
@@ -229,7 +245,7 @@
  padding-left: 10px;
  position: relative;
  margin: 6px 0;
  &::before {
    content: "";
    position: absolute;
@@ -241,12 +257,48 @@
  }
}
.media-list {
  display: flex;
  flex-wrap: wrap;
}
.media-image {
  max-width: 100px;
  height: 100px;
  margin: 5px;
  cursor: pointer;
}
.video-item {
  position: relative;
  margin: 10px;
  cursor: pointer;
}
.video-thumb {
  width: 160px;
  height: 90px;
  background-color: #333;
  display: flex;
  align-items: center;
  justify-content: center;
}
.video-icon {
  width: 30px;
  height: 30px;
  opacity: 0.8;
}
.video-text {
  text-align: center;
  font-size: 12px;
  color: #666;
}
.media-viewer-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.8);
  z-index: 9999;
  display: flex;
@@ -260,4 +312,13 @@
  max-height: 90vh;
  overflow: hidden;
}
</style>
.video-player-wrap {
  position: relative;
}
.video-player {
  max-width: 90vw;
  max-height: 80vh;
}
</style>
src/views/equipmentManagement/inspectionManagement/index.vue
@@ -70,12 +70,21 @@
                    class="no-data">--</span>
            </div>
          </template>
          <template #isEnabled="{ row }">
            <el-tag :type="row.isEnabled === 1 ? 'success' : 'danger'"
                    size="small">
              {{ row.isEnabled == 1 ? '是' : '否' }}
            </el-tag>
          </template>
        </PIMTable>
      </div>
    </el-card>
    <form-dia ref="formDia"
              @closeDia="handleQuery"></form-dia>
    <view-files ref="viewFiles"></view-files>
    <upload-files ref="uploadFiles"
                  @success="handleQuery"
                  @closeDia="handleQuery"></upload-files>
  </div>
</template>
@@ -87,6 +96,7 @@
  // ç»„件引入
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
  import FormDia from "@/views/equipmentManagement/inspectionManagement/components/formDia.vue";
  import UploadFiles from "@/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue";
  import ViewFiles from "@/views/equipmentManagement/inspectionManagement/components/viewFiles.vue";
  // æŽ¥å£å¼•å…¥
@@ -100,6 +110,7 @@
  const { proxy } = getCurrentInstance();
  const formDia = ref();
  const viewFiles = ref();
  const uploadFiles = ref();
  // æŸ¥è¯¢å‚æ•°
  const queryParams = reactive({
@@ -126,8 +137,16 @@
  // åˆ—配置
  const columns = ref([
    { prop: "taskName", label: "巡检任务名称", minWidth: 160 },
    { prop: "inspectionProject", label: "巡检项目", minWidth: 150 },
    { prop: "remarks", label: "备注", minWidth: 150 },
    { prop: "inspector", label: "执行巡检人", minWidth: 150, slot: "inspector" },
    {
      prop: "isEnabled",
      label: "是否启用",
      minWidth: 100,
      dataType: "slot",
      slot: "isEnabled",
    },
    {
      prop: "frequencyType",
      label: "频次",
@@ -176,6 +195,19 @@
    },
    { prop: "registrant", label: "登记人", minWidth: 100 },
    { prop: "createTime", label: "登记日期", minWidth: 100 },
    {
      prop: "inspectionResult",
      label: "巡检结果",
      minWidth: 100,
      dataType: "tag",
      formatData: val => {
        return val == 1 ? "正常" : "异常";
      },
      formatType: val => {
        return val == 1 ? "success" : "danger";
      },
    },
    { prop: "abnormalDescription", label: "异常描述", minWidth: 100 },
  ]);
  // æ“ä½œåˆ—配置
@@ -184,8 +216,9 @@
    const operationConfig = {
      label: "操作",
      width: 130,
      width: operations.length > 1 ? 180 : 130,
      fixed: "right",
            align: 'center',
      dataType: "action",
      operation: operations
        .map(op => {
@@ -194,6 +227,12 @@
              return {
                name: "编辑",
                clickFun: handleAdd,
                color: "#409EFF",
              };
            case "upload":
              return {
                name: "上传",
                clickFun: openUploadDialog,
                color: "#409EFF",
              };
            case "viewFile":
@@ -226,12 +265,14 @@
      ];
      operationsArr.value = ["edit"];
    } else if (value === "task") {
      const operationColumn = getOperationColumn(["viewFile"]);
      const operationColumn = getOperationColumn(["upload", "viewFile"]);
      // å®šæ—¶ä»»åŠ¡è®°å½•ä¸å±•ç¤º"是否启用"列
      const taskColumns = columns.value.filter(col => col.prop !== "isEnabled");
      tableColumns.value = [
        ...columns.value,
        ...taskColumns,
        ...(operationColumn ? [operationColumn] : []),
      ];
      operationsArr.value = ["viewFile"];
      operationsArr.value = ["upload", "viewFile"];
    }
    pageNum.value = 1;
    pageSize.value = 10;
@@ -273,6 +314,7 @@
        // å¤„理 inspector å­—段,将字符串转换为数组(适用于所有情况)
        tableData.value = rawData.map(item => {
          const processedItem = { ...item };
          processedItem.__raw = { ...item };
          // å¤„理 inspector å­—段
          if (processedItem.inspector) {
@@ -322,6 +364,12 @@
  const viewFile = row => {
    nextTick(() => {
      viewFiles.value?.openDialog(row);
    });
  };
  const openUploadDialog = row => {
    nextTick(() => {
      uploadFiles.value?.openDialog(row);
    });
  };
@@ -390,4 +438,4 @@
    color: #909399;
    font-size: 14px;
  }
</style>
</style>
src/views/equipmentManagement/ledger/index.vue
@@ -298,7 +298,34 @@
const showQRCode = async (row) => {
  // ç›´æŽ¥ä½¿ç”¨URL,不要用JSON.stringify包装
  const qrContent = proxy.javaApi + '/device-info?deviceId=' + row.id;
  qrCodeUrl.value = await QRCode.toDataURL(qrContent);
  const qrDataUrl = await QRCode.toDataURL(qrContent, { width: 200, margin: 2 });
  // åˆ›å»ºcanvas合成带名称的二维码图片
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const qrSize = 200;
  const textHeight = 30;
  const padding = 10;
  canvas.width = qrSize + padding * 2;
  canvas.height = qrSize + textHeight + padding * 2;
  // å¡«å……白色背景
  ctx.fillStyle = '#ffffff';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // ç»˜åˆ¶äºŒç»´ç 
  const qrImg = new Image();
  qrImg.src = qrDataUrl;
  await new Promise((resolve) => { qrImg.onload = resolve; });
  ctx.drawImage(qrImg, padding, padding, qrSize, qrSize);
  // ç»˜åˆ¶è®¾å¤‡åç§°
  ctx.fillStyle = '#333333';
  ctx.font = 'bold 14px Arial';
  ctx.textAlign = 'center';
  ctx.fillText(row.deviceName || '', canvas.width / 2, qrSize + padding + 20);
  qrCodeUrl.value = canvas.toDataURL('image/png');
  qrRowData.value = row;
  qrDialogVisible.value = true;
};
src/views/equipmentManagement/measurementEquipment/components/formDia.vue
@@ -36,15 +36,6 @@
                </el-row>
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="安装位置:" prop="instationLocation">
                            <el-input
                                v-model="form.instationLocation"
                                placeholder="请输入"
                                clearable
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="检定单位:" prop="unit">
              <el-input
                  v-model="form.unit"
@@ -53,17 +44,17 @@
              />
                        </el-form-item>
                    </el-col>
                </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="证书编号:" prop="model">
                    <el-col :span="12">
                        <el-form-item label="证书编号:" prop="model">
              <el-input
                  v-model="form.model"
                  placeholder="请输入"
                  clearable
              />
            </el-form-item>
          </el-col>
                    </el-col>
                </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="最新鉴定日期:" prop="mostDate">
              <el-date-picker
@@ -77,8 +68,6 @@
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="有效日期(天):" prop="valid">
              <el-input
@@ -91,15 +80,6 @@
              >
              <template #append>日</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="检定周期:" prop="cycle">
              <el-input
                  v-model="form.cycle"
                  placeholder="请输入检定周期"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -184,10 +164,8 @@
    form: {
        code: "",
    name: "",
    instationLocation: "",
    mostDate:"",
        model: "",
    cycle:"",
        validDate: "",
        nextDate: "",
        userId: "",
@@ -203,9 +181,7 @@
        nextDate: [{required: true, message: "请选择", trigger: "change"}],
        userId: [{required: true, message: "请选择", trigger: "change"}],
        recordDate: [{required: true, message: "请选择", trigger: "change"}],
    instationLocation: [{required: true, message: "请输入", trigger: "blur"}],
    mostDate: [{required: true, message: "请选择", trigger: "change"}],
    cycle: [{required: true, message: "请选择", trigger: "blur"}],
    valid: [
      {required: true, message: "请输入", trigger: "blur"},
      {
src/views/equipmentManagement/measurementEquipment/filesDia.vue
@@ -157,7 +157,7 @@
}
// ä¸‹è½½é™„ä»¶
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
    proxy.$download.byUrl(row.url, row.originalFilename);
}
// åˆ é™¤
const handleDelete = () => {
src/views/equipmentManagement/measurementEquipment/index.vue
@@ -42,6 +42,7 @@
                :tableLoading="tableLoading"
                @pagination="pagination"
        :dbRowClick="dbRowClick"
        :rowClassName="rowClassName"
            ></PIMTable>
        </div>
        <form-dia ref="formDia" @close="handleQuery"></form-dia>
@@ -89,12 +90,6 @@
    align: "center",
  },
    {
        label: "安装位置",
        prop: "instationLocation",
        width: 150,
    align:"center"
    },
    {
        label: "检定单位",
        prop: "unit",
        width: 200,
@@ -130,12 +125,6 @@
        width: 130,
    align:"center"
    },
  {
    label: "检定周期(天)",
    prop: "cycle",
    width: 130,
    align:"center"
  },
  {
    label: "状态",
    prop: "status",
@@ -193,6 +182,31 @@
const dbRowClick = (row)=>{
  rowClickData.value?.openDialog(row)
}
// è¡Œæ ·å¼ï¼šå¿«åˆ°æœŸï¼ˆ7天内)或逾期标红
const rowClassName = ({ row }) => {
  console.log('rowClassName called:', row);
  // valid æ˜¯æœ‰æ•ˆå¤©æ•°ï¼ŒmostDate æ˜¯æœ€æ–°æ£€å®šæ—¥æœŸ
  if (row.valid && row.mostDate) {
    const mostDate = new Date(row.mostDate);
    // è®¡ç®—到期日期 = æ£€å®šæ—¥æœŸ + æœ‰æ•ˆå¤©æ•°
    const validDays = parseInt(row.valid) || 0;
    const expireDate = new Date(mostDate);
    expireDate.setDate(expireDate.getDate() + validDays);
    const now = new Date();
    const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24));
    console.log('row:', row.code, 'validDays:', validDays, 'expireDate:', expireDate, 'diffDays:', diffDays);
    // 7天内到期或已逾期都标红
    if (diffDays <= 7) {
      console.log('return warning-row');
      return 'warning-row';
    }
  } else {
    console.log('row missing valid or mostDate:', row.valid, row.mostDate);
  }
  return '';
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
@@ -294,5 +308,13 @@
</script>
<style scoped>
:deep(.el-table .warning-row) {
  background-color: #fef0f0 !important;
}
:deep(.el-table .warning-row:hover > td) {
  background-color: #f9d5d5 !important;
}
:deep(.el-table .el-table__body tr.warning-row td) {
  background-color: #fef0f0 !important;
}
</style>
src/views/equipmentManagement/operationManagement/index.vue
@@ -104,7 +104,7 @@
          align="center"
        >
          <template #default="scope">
            {{ scope.row.runtimeDuration || '-' }}
            {{ getRuntimeDurationDisplay(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column
@@ -154,7 +154,8 @@
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { ref, onMounted, onUnmounted, computed } from 'vue'
import dayjs from 'dayjs'
import { ElMessage } from 'element-plus'
import {
  VideoPlay,
@@ -193,6 +194,98 @@
  return filtered
})
// è¿è¡Œä¸­æ— ç»“束时间时,运行时长需随当前时间变化,用 tick è§¦å‘模板重算
const runtimeDisplayTick = ref(0)
/** å–后端可能使用的开始/结束时间字段 */
const pickStartTime = (row) => row?.startRuntimeTime ?? row?.startTime ?? row?.start_time
const pickEndTime = (row) => row?.endRuntimeTime ?? row?.endTime ?? row?.end_time
/**
 * è§£æžæŽ¥å£/前端写入的各类时间:时间戳、ISO å­—符串、yyyy-MM-dd HH:mm:ss、Jackson æ•°ç»„ [y,M,d,h,m,s]、含中文的 toLocaleString ç­‰
 */
const parseDeviceTime = (input) => {
  if (input === null || input === undefined || input === '') return null
  if (typeof input === 'number' && !Number.isNaN(input)) {
    const d = dayjs(input)
    return d.isValid() ? d.toDate() : null
  }
  if (Array.isArray(input)) {
    const [y, mo, day, h = 0, mi = 0, se = 0] = input
    if (y == null || y === '') return null
    const d = dayjs()
        .year(Number(y))
        .month(Number(mo || 1) - 1)
        .date(Number(day || 1))
        .hour(Number(h) || 0)
        .minute(Number(mi) || 0)
        .second(Number(se) || 0)
    return d.isValid() ? d.toDate() : null
  }
  const s = String(input).trim()
  if (!s || s === '-') return null
  let d = dayjs(s)
  if (d.isValid()) return d.toDate()
  d = dayjs(s.replace(/-/g, '/'))
  if (d.isValid()) return d.toDate()
  d = dayjs(s.replace(/\//g, '-'))
  if (d.isValid()) return d.toDate()
  return null
}
const formatDurationMs = (durationMs) => {
  if (durationMs == null || Number.isNaN(durationMs) || durationMs < 0) return '-'
  const hours = Math.floor(durationMs / (1000 * 60 * 60))
  const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60))
  if (hours === 0 && minutes === 0) return '不足1分钟'
  return `${hours}小时${minutes}分钟`
}
const hasMeaningfulEnd = (endRaw) =>
    endRaw !== null &&
    endRaw !== undefined &&
    String(endRaw).trim() !== '' &&
    String(endRaw).trim() !== '-'
const formatStoredDuration = (row) => {
  const rd = row?.runtimeDuration
  if (rd === null || rd === undefined) return ''
  const t = String(rd).trim()
  return t === '' || t === '-' ? '' : String(rd)
}
/** è¿è¡Œä¸­ï¼šå§‹ç»ˆç”¨ã€Œå½“前时间 - å¼€å§‹æ—¶é—´ã€ï¼›å·²åœæ­¢ï¼šä¼˜å…ˆæŽ¥å£ runtimeDuration,否则用结束-开始;无结束可看已存时长或动态推算 */
const getRuntimeDurationDisplay = (row) => {
  void runtimeDisplayTick.value
  const start = parseDeviceTime(pickStartTime(row))
  if (!start) {
    return formatStoredDuration(row) || '-'
  }
  const statusStr = String(row?.status ?? '').trim()
  const isRunning = statusStr === '运行中' || statusStr === '1'
  const endRaw = pickEndTime(row)
  const hasEnd = hasMeaningfulEnd(endRaw)
  // æ— ç»“束时间:运行中一定动态算;已停止则优先展示后端已存时长,没有再按当前时间推算
  if (!hasEnd) {
    if (isRunning) return formatDurationMs(Date.now() - start.getTime())
    const stored = formatStoredDuration(row)
    if (stored) return stored
    return formatDurationMs(Date.now() - start.getTime())
  }
  if (isRunning) {
    return formatDurationMs(Date.now() - start.getTime())
  }
  const end = parseDeviceTime(endRaw)
  const stored = formatStoredDuration(row)
  if (stored) return stored
  if (end) return formatDurationMs(end.getTime() - start.getTime())
  return '-'
}
// æ£€æŸ¥è®¾å¤‡æ˜¯å¦è¶…时未启动
const isOverdue = (device) => {
@@ -246,12 +339,11 @@
      device.endRuntimeTime = currentTime
      // è®¡ç®—运行时长
      if (device.startRuntimeTime) {
        const startTime = new Date(device.startRuntimeTime)
        const endTime = new Date(currentTime)
        const duration = endTime - startTime
        const hours = Math.floor(duration / (1000 * 60 * 60))
        const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60))
        device.runtimeDuration = `${hours}小时${minutes}分钟`
        const startTime = parseDeviceTime(device.startRuntimeTime)
        const endTime = parseDeviceTime(currentTime)
        if (startTime && endTime) {
          device.runtimeDuration = formatDurationMs(endTime.getTime() - startTime.getTime())
        }
      }
    }
    const params = {
@@ -297,9 +389,31 @@
// ç»„件挂载时初始化数据
const POLL_MS = 60 * 1000
const RUNTIME_TICK_MS = 30 * 1000
let listPollTimer = null
let runtimeTickTimer = null
// ç»„件挂载时拉取数据,并每分钟刷新一次列表;运行中时长每 30 ç§’刷新显示
onMounted(() => {
  getList()
  listPollTimer = setInterval(() => {
    getList()
  }, POLL_MS)
  runtimeTickTimer = setInterval(() => {
    runtimeDisplayTick.value++
  }, RUNTIME_TICK_MS)
})
onUnmounted(() => {
  if (listPollTimer != null) {
    clearInterval(listPollTimer)
    listPollTimer = null
  }
  if (runtimeTickTimer != null) {
    clearInterval(runtimeTickTimer)
    runtimeTickTimer = null
  }
})
</script>
src/views/equipmentManagement/repair/Modal/AcceptanceModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,144 @@
<template>
  <FormDialog
    v-model="visible"
    title="验收审批"
    width="500px"
    @confirm="submitForm"
    @cancel="handleCancel"
    @close="handleCancel"
  >
    <el-form :model="form" :rules="rules" label-width="100px">
      <el-form-item label="验收人" prop="acceptanceName">
        <el-select
          v-model="form.acceptanceName"
          placeholder="请选择验收人"
          filterable
          style="width: 100%"
        >
          <el-option
            v-for="item in userList"
            :key="item.userId"
            :label="item.nickName"
            :value="item.nickName"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="验收时间" prop="acceptanceTime">
        <el-date-picker
          v-model="form.acceptanceTime"
          type="datetime"
          placeholder="请选择验收时间"
          format="YYYY-MM-DD HH:mm:ss"
          value-format="YYYY-MM-DD HH:mm:ss"
          style="width: 100%"
        />
      </el-form-item>
      <el-form-item label="验收备注" prop="acceptanceRemark">
        <el-input
          v-model="form.acceptanceRemark"
          type="textarea"
          :rows="3"
          placeholder="请输入验收备注"
        />
      </el-form-item>
    </el-form>
  </FormDialog>
</template>
<script setup>
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
import { userListNoPageByTenantId } from "@/api/system/user.js";
import { repairAcceptance } from "@/api/equipmentManagement/repair";
import dayjs from "dayjs";
defineOptions({
  name: "验收审批弹窗",
});
const emits = defineEmits(["ok"]);
const visible = ref(false);
const loading = ref(false);
const repairId = ref(null);
const userList = ref([]);
const form = reactive({
  acceptanceName: undefined,
  acceptanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
  acceptanceRemark: undefined,
});
const rules = {
  acceptanceName: [
    { required: true, message: "请选择验收人", trigger: "change" },
  ],
  acceptanceTime: [
    { required: true, message: "请选择验收时间", trigger: "change" },
  ],
  acceptanceRemark: [
    { required: true, message: "请输入验收备注", trigger: "blur" },
  ],
};
// åŠ è½½ç”¨æˆ·åˆ—è¡¨
const loadUserList = async () => {
  const { data } = await userListNoPageByTenantId();
  userList.value = data;
};
// æ‰“开弹窗
const open = async (row) => {
  repairId.value = row.id;
  visible.value = true;
  // é‡ç½®è¡¨å•
  form.acceptanceName = undefined;
  form.acceptanceTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
  form.acceptanceRemark = undefined;
  await loadUserList();
};
// æäº¤è¡¨å•
const submitForm = async () => {
  if (!form.acceptanceName) {
    ElMessage.warning("请选择验收人");
    return;
  }
  if (!form.acceptanceTime) {
    ElMessage.warning("请选择验收时间");
    return;
  }
  if (!form.acceptanceRemark) {
    ElMessage.warning("请输入验收备注");
    return;
  }
  loading.value = true;
  try {
    const { code } = await repairAcceptance({
      id: repairId.value,
      acceptanceName: form.acceptanceName,
      acceptanceTime: form.acceptanceTime,
      acceptanceRemark: form.acceptanceRemark,
    });
    if (code === 200) {
      ElMessage.success("验收通过");
      visible.value = false;
      emits("ok");
    }
  } finally {
    loading.value = false;
  }
};
const handleCancel = () => {
  visible.value = false;
};
defineExpose({
  open,
});
</script>
<style lang="scss" scoped></style>
src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -49,19 +49,44 @@
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="项目">
            <el-input v-model="form.machineryCategory" placeholder="请输入项目" />
          <el-form-item label="报修报修项目">
            <el-input v-model="form.machineryCategory" placeholder="请输入报修报修项目" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="12">
          <el-form-item label="维修人">
            <el-input v-model="form.maintenanceName" placeholder="请输入维修人姓名" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row v-if="id">
        <el-col :span="12">
          <el-form-item label="报修状态">
            <el-select v-model="form.status">
            <el-select v-model="form.status" disabled>
              <el-option label="待维修" :value="0"></el-option>
              <el-option label="完结" :value="1"></el-option>
              <el-option label="已验收" :value="1"></el-option>
              <el-option label="失败" :value="2"></el-option>
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
      <!-- éªŒæ”¶ä¿¡æ¯å±•示 -->
      <el-row v-if="id && form.status === 1">
        <el-col :span="12">
          <el-form-item label="验收人">
            <el-input v-model="form.acceptanceName" disabled />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="验收时间">
            <el-input v-model="form.acceptanceTime" disabled />
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="验收备注">
            <el-input v-model="form.acceptanceRemark" type="textarea" :rows="2" disabled />
          </el-form-item>
        </el-col>
      </el-row>
@@ -131,6 +156,7 @@
  status: 0, // æŠ¥ä¿®çŠ¶æ€
  machineryCategory: undefined,
  storageBlobDTOs: [],
  maintenanceName: undefined, // ç»´ä¿®äºº
});
const setDeviceModel = (deviceId) => {
@@ -148,6 +174,10 @@
  form.status = data.status;
  form.machineryCategory = data.machineryCategory;
  form.storageBlobDTOs = data.storageBlobVOs || [];
  form.maintenanceName = data.maintenanceName;
  form.acceptanceName = data.acceptanceName;
  form.acceptanceTime = data.acceptanceTime;
  form.acceptanceRemark = data.acceptanceRemark;
};
const sendForm = async () => {
src/views/equipmentManagement/repair/index.vue
@@ -100,13 +100,14 @@
        <template #statusRef="{ row }">
          <el-tag v-if="row.status === 2" type="danger">失败</el-tag>
          <el-tag v-if="row.status === 1" type="success">完结</el-tag>
          <el-tag v-if="row.status === 3" type="info">待验收</el-tag>
          <el-tag v-if="row.status === 0" type="warning">待维修</el-tag>
        </template>
        <template #operation="{ row }">
          <el-button
            type="primary"
            link
            :disabled="row.status === 1"
            :disabled="row.status === 1 || row.status === 3"
            @click="editRepair(row.id)"
          >
            ç¼–辑
@@ -114,15 +115,23 @@
          <el-button
            type="success"
            link
            :disabled="row.status === 1"
            :disabled="row.status !== 0"
            @click="addMaintain(row)"
          >
            ç»´ä¿®
          </el-button>
          <el-button
            type="warning"
            link
            :disabled="row.status !== 3"
            @click="openAcceptance(row)"
          >
            éªŒæ”¶
          </el-button>
          <el-button
            type="danger"
            link
            :disabled="row.status === 1"
            :disabled="row.status === 1 || row.status === 3"
            @click="delRepairByIds(row.id)"
          >
            åˆ é™¤
@@ -139,6 +148,7 @@
    </div>
    <RepairModal ref="repairModalRef" @ok="getTableData"/>
    <MaintainModal ref="maintainModalRef" @ok="getTableData"/>
    <AcceptanceModal ref="acceptanceModalRef" @ok="getTableData"/>
    <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" :record-type="'device_repair'" :record-id="recordId"  />
  </div>
</template>
@@ -151,6 +161,7 @@
import {ElMessageBox, ElMessage} from "element-plus";
import dayjs from "dayjs";
import MaintainModal from "./Modal/MaintainModal.vue";
import AcceptanceModal from "./Modal/AcceptanceModal.vue";
const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
defineOptions({
@@ -162,6 +173,7 @@
// æ¨¡æ€æ¡†å®žä¾‹
const repairModalRef = ref();
const maintainModalRef = ref();
const acceptanceModalRef = ref();
// è¡¨æ ¼å¤šé€‰æ¡†é€‰ä¸­é¡¹
const multipleList = ref([]);
@@ -197,7 +209,7 @@
        prop: "deviceModel",
      },
      {
        label: "项目",
        label: "报修项目",
        align: "center",
        prop: "machineryCategory",
      },
@@ -232,6 +244,17 @@
        align: "center",
        prop: "maintenanceTime",
        formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
      },
      {
        label: "验收人",
        align: "center",
        prop: "acceptanceName",
      },
      {
        label: "验收时间",
        align: "center",
        prop: "acceptanceTime",
        formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : ""),
      },
      {
        label: "状态",
@@ -301,6 +324,11 @@
  maintainModalRef.value.open(row.id, row);
};
// æ‰“开验收弹窗
const openAcceptance = (row) => {
  acceptanceModalRef.value.open(row);
};
const changePage = ({page, limit}) => {
  pagination.currentPage = page;
  pagination.pageSize = limit;
src/views/equipmentManagement/upkeep/Form/MaintenanceModal.vue
@@ -1,199 +1,216 @@
<template>
  <FormDialog
    v-model="visible"
    :title="'设备保养'"
    width="500px"
    @confirm="sendForm"
    @cancel="handleCancel"
    @close="handleClose"
  >
    <el-form :model="form" label-width="100px">
  <FormDialog v-model="visible"
              :title="'设备保养'"
              width="500px"
              @confirm="sendForm"
              @cancel="handleCancel"
              @close="handleClose">
    <el-form :model="form"
             label-width="100px">
      <el-form-item label="实际保养人">
        <el-input
          v-model="form.maintenanceActuallyName"
          placeholder="请输入实际保养人"
        ></el-input>
        <el-input v-model="form.maintenanceActuallyName"
                  placeholder="请输入实际保养人"></el-input>
      </el-form-item>
      <el-form-item label="实际保养日期">
        <el-date-picker
          v-model="form.maintenanceActuallyTime"
          placeholder="请选择实际保养日期"
          format="YYYY-MM-DD HH:mm:ss"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="datetime"
          clearable
          style="width: 100%"
        />
        <el-date-picker v-model="form.maintenanceActuallyTime"
                        placeholder="请选择实际保养日期"
                        format="YYYY-MM-DD HH:mm:ss"
                        value-format="YYYY-MM-DD HH:mm:ss"
                        type="datetime"
                        clearable
                        style="width: 100%" />
      </el-form-item>
      <el-form-item label="保养状态">
        <el-select v-model="form.status">
          <el-option label="待保养" :value="0"></el-option>
          <el-option label="完结" :value="1"></el-option>
          <el-option label="失败" :value="2"></el-option>
          <el-option label="待保养"
                     :value="0"></el-option>
          <el-option label="完结"
                     :value="1"></el-option>
          <el-option label="失败"
                     :value="2"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="保养结果">
        <el-input
          v-model="form.maintenanceResult"
          placeholder="请输入保养结果"
          type="text" />
        <el-input v-model="form.maintenanceResult"
                  placeholder="请输入保养结果"
                  type="text" />
      </el-form-item>
      <el-form-item label="设备备件">
        <el-select v-model="form.sparePartsIds" :loading="loadingSparePartOptions" placeholder="请选择设备备件" multiple filterable>
          <el-option
              v-for="item in sparePartOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id"
          />
        <el-select v-model="form.sparePartsIds"
                   :loading="loadingSparePartOptions"
                   placeholder="请选择设备备件"
                   multiple
                   filterable>
          <el-option v-for="item in sparePartOptions"
                     :key="item.id"
                     :label="item.name"
                     :value="item.id" />
        </el-select>
      </el-form-item>
      <el-form-item v-if="selectedSpareParts.length" label="领用数量">
      <el-form-item v-if="selectedSpareParts.length"
                    label="领用数量">
        <div style="width: 100%">
          <div
              v-for="item in selectedSpareParts"
              :key="item.id"
              style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;"
          >
          <div v-for="item in selectedSpareParts"
               :key="item.id"
               style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
            <div style="flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
              {{ item.name }}
              <span v-if="item.quantity !== null && item.quantity !== undefined" style="color: #909399;">
              <span v-if="item.quantity !== null && item.quantity !== undefined"
                    style="color: #909399;">
                ï¼ˆåº“存:{{ item.quantity }})
              </span>
            </div>
            <el-input-number
                v-model="sparePartQtyMap[item.id]"
                :min="1"
                :max="item.quantity !== null && item.quantity !== undefined ? Number(item.quantity) : undefined"
                :step="1"
                controls-position="right"
                style="width: 180px"
            />
            <el-input-number v-model="sparePartQtyMap[item.id]"
                             :min="1"
                             :max="item.quantity !== null && item.quantity !== undefined ? Number(item.quantity) : undefined"
                             :step="1"
                             controls-position="right"
                             style="width: 180px" />
          </div>
        </div>
      </el-form-item>
      <el-form-item label="附件">
        <FileUpload v-model:file-list="form.storageBlobDTOs" />
      </el-form-item>
    </el-form>
  </FormDialog>
</template>
<script setup>
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { addMaintenance } from "@/api/equipmentManagement/upkeep";
import useFormData from "@/hooks/useFormData";
import dayjs from "dayjs";
import useUserStore from "@/store/modules/user";
import { ElMessage } from "element-plus";
import {computed, ref} from "vue";
import {getSparePartsList} from "@/api/equipmentManagement/spareParts.js";
  import FormDialog from "@/components/Dialog/FormDialog.vue";
  import FileUpload from "@/components/AttachmentUpload/file/index.vue";
  import { addMaintenance } from "@/api/equipmentManagement/upkeep";
  import useFormData from "@/hooks/useFormData";
  import dayjs from "dayjs";
  import useUserStore from "@/store/modules/user";
  import { ElMessage } from "element-plus";
  import { computed, ref, nextTick, getCurrentInstance } from "vue";
  import { getSparePartsList } from "@/api/equipmentManagement/spareParts.js";
defineOptions({
  name: "保养模态框",
});
  defineOptions({
    name: "保养模态框",
  });
const emits = defineEmits(["ok"]);
  const emits = defineEmits(["ok"]);
// ä¿å­˜è®¡åˆ’保养记录的id
const planId = ref();
const visible = ref(false);
const loading = ref(false);
const userStore = useUserStore();
  const { proxy } = getCurrentInstance();
  // ä¿å­˜è®¡åˆ’保养记录的id
  const planId = ref();
  const visible = ref(false);
  const loading = ref(false);
  const userStore = useUserStore();
const { form, resetForm } = useFormData({
  maintenanceActuallyName: undefined, // å®žé™…保养人
  maintenanceActuallyTime: undefined, // å®žé™…保养日期
  maintenanceResult: undefined, // ä¿å…»ç»“æžœ
  status: 0, // ä¿å…»çŠ¶æ€
  sparePartsIds: [],
});
  const { form, resetForm } = useFormData({
    maintenanceActuallyName: undefined, // å®žé™…保养人
    maintenanceActuallyTime: undefined, // å®žé™…保养日期
    maintenanceResult: undefined, // ä¿å…»ç»“æžœ
    status: 0, // ä¿å…»çŠ¶æ€
    sparePartsIds: [],
    storageBlobDTOs: [],
  });
const sparePartOptions = ref([])
const loadingSparePartOptions = ref(true)
const sparePartQtyMap = ref({})
  const sparePartOptions = ref([]);
  const loadingSparePartOptions = ref(true);
  const sparePartQtyMap = ref({});
const selectedSpareParts = computed(() => {
  const ids = Array.isArray(form.sparePartsIds) ? form.sparePartsIds : [];
  const set = new Set(ids.map((i) => String(i)));
  return (sparePartOptions.value || []).filter((p) => set.has(String(p.id)));
});
  const selectedSpareParts = computed(() => {
    const ids = Array.isArray(form.sparePartsIds) ? form.sparePartsIds : [];
    const set = new Set(ids.map(i => String(i)));
    return (sparePartOptions.value || []).filter(p => set.has(String(p.id)));
  });
const setForm = (data) => {
  form.maintenanceActuallyName =
    data.maintenanceActuallyName ?? userStore.nickName;
  form.maintenanceActuallyTime =
    data.maintenanceActuallyTime
  const setForm = data => {
    form.maintenanceActuallyName =
      data.maintenanceActuallyName ?? userStore.nickName;
    form.maintenanceActuallyTime = data.maintenanceActuallyTime
      ? dayjs(data.maintenanceActuallyTime).format("YYYY-MM-DD HH:mm:ss")
      : dayjs().format("YYYY-MM-DD HH:mm:ss");
  form.maintenanceResult = data.maintenanceResult;
  form.status = 1; // é»˜è®¤çŠ¶æ€ä¸ºå®Œç»“
  // multiple é€‰æ‹©å™¨è¦æ±‚数组;后端常返回 "1,2,3"
  if (Array.isArray(data?.sparePartsIds)) {
    form.sparePartsIds = data.sparePartsIds.map((v) => Number(v)).filter((v) => Number.isFinite(v));
  } else if (typeof data?.sparePartsIds === "string") {
    form.sparePartsIds = data.sparePartsIds
    form.maintenanceResult = data.maintenanceResult;
    form.status = 1; // é»˜è®¤çŠ¶æ€ä¸ºå®Œç»“
    // multiple é€‰æ‹©å™¨è¦æ±‚数组;后端常返回 "1,2,3"
    if (Array.isArray(data?.sparePartsIds)) {
      form.sparePartsIds = data.sparePartsIds
        .map(v => Number(v))
        .filter(v => Number.isFinite(v));
    } else if (typeof data?.sparePartsIds === "string") {
      form.sparePartsIds = data.sparePartsIds
        .split(",")
        .map((s) => Number(String(s).trim()))
        .filter((v) => Number.isFinite(v));
  } else if (typeof data?.sparePartsIds === "number") {
    form.sparePartsIds = [data.sparePartsIds];
  } else {
    form.sparePartsIds = [];
  }
};
        .map(s => Number(String(s).trim()))
        .filter(v => Number.isFinite(v));
    } else if (typeof data?.sparePartsIds === "number") {
      form.sparePartsIds = [data.sparePartsIds];
    } else {
      form.sparePartsIds = [];
    }
    form.storageBlobDTOs = data.storageBlobVOs || [];
  };
/**
 * @desc ä¿å­˜ä¿å…»
 */
const sendForm = async () => {
  loading.value = true;
  try {
    // é¢†ç”¨æ•°é‡æ ¡éªŒ
    if (Array.isArray(form.sparePartsIds) && form.sparePartsIds.length > 0) {
      for (const partId of form.sparePartsIds) {
        const qty = Number(sparePartQtyMap.value?.[partId]);
        if (!Number.isFinite(qty) || qty <= 0) {
          proxy?.$modal?.msgError?.("请填写备件领用数量");
          return;
        }
        const part = sparePartOptions.value.find((p) => String(p.id) === String(partId));
        const stock = part?.quantity;
        if (stock !== null && stock !== undefined && Number.isFinite(Number(stock))) {
          if (qty > Number(stock)) {
            proxy?.$modal?.msgError?.(`备件「${part?.name || ""}」领用数量不能超过库存(${stock})`);
  /**
   * @desc ä¿å­˜ä¿å…»
   */
  const sendForm = async () => {
    loading.value = true;
    try {
      // é¢†ç”¨æ•°é‡æ ¡éªŒ
      if (Array.isArray(form.sparePartsIds) && form.sparePartsIds.length > 0) {
        for (const partId of form.sparePartsIds) {
          const qty = Number(sparePartQtyMap.value?.[partId]);
          if (!Number.isFinite(qty) || qty <= 0) {
            proxy?.$modal?.msgError?.("请填写备件领用数量");
            return;
          }
          const part = sparePartOptions.value.find(
            p => String(p.id) === String(partId)
          );
          const stock = part?.quantity;
          if (
            stock !== null &&
            stock !== undefined &&
            Number.isFinite(Number(stock))
          ) {
            if (qty > Number(stock)) {
              proxy?.$modal?.msgError?.(
                `备件「${part?.name || ""}」领用数量不能超过库存(${stock})`
              );
              return;
            }
          }
        }
      }
    }
    const data = {
      id: planId.value,
      ...form,
      sparePartsIds: form.sparePartsIds ? form.sparePartsIds.join(",") : "",
      sparePartsQty: form.sparePartsIds
          ? form.sparePartsIds.map((id) => sparePartQtyMap.value?.[id] ?? 1).join(",")
      const data = {
        id: planId.value,
        ...form,
        sparePartsIds: form.sparePartsIds ? form.sparePartsIds.join(",") : "",
        sparePartsQty: form.sparePartsIds
          ? form.sparePartsIds
              .map(id => sparePartQtyMap.value?.[id] ?? 1)
              .join(",")
          : "",
      sparePartsUseList: form.sparePartsIds
          ? form.sparePartsIds.map((id) => ({ id, quantity: sparePartQtyMap.value?.[id] ?? 1 }))
        sparePartsUseList: form.sparePartsIds
          ? form.sparePartsIds.map(id => ({
              id,
              quantity: sparePartQtyMap.value?.[id] ?? 1,
            }))
          : [],
      };
      const { code } = await addMaintenance(data);
      if (code == 200) {
        ElMessage.success("保养成功");
        emits("ok");
        resetForm();
        sparePartQtyMap.value = {};
        visible.value = false;
      }
    } finally {
      loading.value = false;
    }
    const { code } = await addMaintenance(data);
    if (code == 200) {
      ElMessage.success("保养成功");
      emits("ok");
      resetForm();
      sparePartQtyMap.value = {};
      visible.value = false;
    }
  } finally {
    loading.value = false;
  }
};
  };
const fetchSparePartOptions = () => {
  loadingSparePartOptions.value = true;
  // å’Œå¤‡ä»¶ç®¡ç†é¡µä¸€è‡´ï¼š/spareParts/listPage â†’ res.data.records
  getSparePartsList({ current: 1, size: 1000 })
      .then((res) => {
  const fetchSparePartOptions = () => {
    loadingSparePartOptions.value = true;
    // å’Œå¤‡ä»¶ç®¡ç†é¡µä¸€è‡´ï¼š/spareParts/listPage â†’ res.data.records
    getSparePartsList({ current: 1, size: 1000 })
      .then(res => {
        if (res.code === 200) {
          sparePartOptions.value = res?.data?.records || [];
        } else {
@@ -206,31 +223,31 @@
      .finally(() => {
        loadingSparePartOptions.value = false;
      });
}
  };
const handleCancel = () => {
  resetForm();
  sparePartQtyMap.value = {};
  visible.value = false;
};
  const handleCancel = () => {
    resetForm();
    sparePartQtyMap.value = {};
    visible.value = false;
  };
const handleClose = () => {
  resetForm();
  sparePartQtyMap.value = {};
  visible.value = false;
};
  const handleClose = () => {
    resetForm();
    sparePartQtyMap.value = {};
    visible.value = false;
  };
const open = async (id, row) => {
  planId.value = id; // ä¿å­˜è®¡åˆ’保养记录的id
  visible.value = true;
  await nextTick();
  fetchSparePartOptions()
  setForm(row);
};
  const open = async (id, row) => {
    planId.value = id; // ä¿å­˜è®¡åˆ’保养记录的id
    visible.value = true;
    await nextTick();
    fetchSparePartOptions();
    setForm(row);
  };
defineExpose({
  open,
});
  defineExpose({
    open,
  });
</script>
<style lang="scss" scoped></style>
src/views/equipmentManagement/upkeep/Form/PlanModal.vue
@@ -32,10 +32,10 @@
          disabled
        />
      </el-form-item>
      <el-form-item label="项目">
      <el-form-item label="保养项目">
        <el-input
            v-model="form.machineryCategory"
            placeholder="请输入项目"
            placeholder="请输入保养项目"
        />
      </el-form-item>
      <el-form-item label="录入人">
@@ -61,6 +61,13 @@
          <el-option label="完结" :value="1"></el-option>
          <el-option label="失败" :value="2"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="保养人">
        <el-input
          v-model="form.maintenancePerson"
          placeholder="请输入保养人姓名"
          clearable
        />
      </el-form-item>
      <el-form-item label="计划保养日期">
        <el-date-picker
@@ -124,6 +131,7 @@
  status: 0, //保修状态
  machineryCategory: undefined,
  storageBlobDTOs: [],
  maintenancePerson: undefined, // ä¿å…»äºº
});
const setDeviceModel = (deviceId) => {
@@ -142,6 +150,7 @@
  form.createUser = Number(data.createUser);
  form.status = data.status;
  form.machineryCategory = data.machineryCategory;
  form.maintenancePerson = data.maintenancePerson;
  if (data.maintenancePlanTime) {
    form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
      "YYYY-MM-DD HH:mm:ss"
src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -67,6 +67,28 @@
            </el-row>
            <el-row>
                <el-col :span="12">
                    <el-form-item label="保养项目" prop="machineryCategory">
                        <el-input
                            v-model.trim="form.machineryCategory"
                            placeholder="请输入保养项目"
                            maxlength="100"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="保养人" prop="maintenancePerson">
                        <el-input
                            v-model.trim="form.maintenancePerson"
                            placeholder="请输入保养人姓名"
                            maxlength="100"
                            clearable
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-row>
                <el-col :span="12">
                    <el-form-item label="任务频率" prop="frequencyType">
                        <el-select v-model="form.frequencyType" placeholder="请选择" clearable>
                            <el-option label="每日" value="DAILY"/>
@@ -154,18 +176,21 @@
        taskName: undefined,
        // å½•入人:单选一个用户 id
        inspector: undefined,
        machineryCategory: "",
        remarks: '',
        frequencyType: '',
        frequencyDetail: '',
        week: '',
        time: '',
        deviceModel: undefined, // è§„格型号
        registrationDate: ''
        registrationDate: '',
        maintenancePerson: '' // ä¿å…»äºº
    },
    rules: {
        taskId: [{ required: true, message: "请选择设备", trigger: "change" },],
        inspector: [{ required: true, message: "请选择录入人", trigger: "blur" },],
        registrationDate: [{ required: true, message: "请选择登记时间", trigger: "change" }]
        registrationDate: [{ required: true, message: "请选择登记时间", trigger: "change" }],
        machineryCategory: [{ required: true, message: "请输入保养项目", trigger: "blur" }]
    }
})
const { form, rules } = toRefs(data)
@@ -238,14 +263,15 @@
        taskId: undefined,
        taskName: undefined,
        inspector: undefined,
        inspector: undefined,
        machineryCategory: "",
        remarks: '',
        frequencyType: '',
        frequencyDetail: '',
        week: '',
        time: '',
        deviceModel: undefined,
        registrationDate: ''
        registrationDate: '',
        maintenancePerson: ''
    }
}
src/views/equipmentManagement/upkeep/index.vue
@@ -2,8 +2,8 @@
  <div class="app-container">
    <el-tabs v-model="activeTab"
             @tab-change="handleTabChange">
      <!-- å®šæ—¶ä»»åŠ¡ç®¡ç†tab -->
      <el-tab-pane label="定时任务管理"
      <!-- ä¿å…»ä»»åŠ¡tab -->
      <el-tab-pane label="保养任务"
                   name="scheduled">
        <div class="search_form">
          <el-form :model="scheduledFilters"
@@ -37,7 +37,7 @@
        <div class="table_list">
          <div class="actions">
            <el-text class="mx-1"
                     size="large">定时任务管理</el-text>
                     size="large">保养任务</el-text>
            <div>
              <el-button type="primary"
                         icon="Plus"
@@ -84,8 +84,8 @@
          </PIMTable>
        </div>
      </el-tab-pane>
      <!-- ä»»åŠ¡è®°å½•tab(原设备保养页面) -->
      <el-tab-pane label="任务记录"
      <!-- ä¿å…»è®°å½•tab(原设备保养页面) -->
      <el-tab-pane label="保养记录"
                   name="record">
        <div class="search_form">
          <el-form :model="filters"
@@ -130,7 +130,7 @@
        <div class="table_list">
          <div class="actions">
            <el-text class="mx-1"
                     size="large">任务记录</el-text>
                     size="large">保养记录</el-text>
            <div>
              <el-button type="success"
                         icon="Van"
@@ -262,7 +262,7 @@
  const fileDialogVisible = ref(false);
  const currentMaintenanceTaskId = ref(null);
  // ä»»åŠ¡è®°å½•tab(原设备保养页面)相关变量
  // ä¿å…»è®°å½•tab(原设备保养页面)相关变量
  const filters = reactive({
    deviceName: "",
    maintenancePlanTime: "",
@@ -278,7 +278,7 @@
  });
  const multipleList = ref([]);
  // å®šæ—¶ä»»åŠ¡ç®¡ç†tab相关变量
  // ä¿å…»ä»»åŠ¡tab相关变量
  const scheduledFilters = reactive({
    taskName: "",
    status: "",
@@ -292,12 +292,18 @@
  });
  const scheduledMultipleList = ref([]);
  // å®šæ—¶ä»»åŠ¡ç®¡ç†è¡¨æ ¼åˆ—é…ç½®
  // ä¿å…»ä»»åŠ¡è¡¨æ ¼åˆ—é…ç½®
  const scheduledColumns = ref([
    { prop: "taskName", label: "设备名称" },
    {
      label: "规格型号",
      prop: "deviceModel",
    },
    {
      label: "保养项目",
      prop: "machineryCategory",
      minWidth: 120,
      formatData: cell => cell || "--",
    },
    {
      prop: "frequencyType",
@@ -336,6 +342,7 @@
        );
      },
    },
    { prop: "maintenancePerson", label: "保养人", minWidth: 100 },
    { prop: "registrant", label: "登记人", minWidth: 100 },
    { prop: "registrationDate", label: "登记日期", minWidth: 100 },
    {
@@ -348,7 +355,7 @@
    },
  ]);
  // ä»»åŠ¡è®°å½•è¡¨æ ¼åˆ—é…ç½®ï¼ˆåŽŸè®¾å¤‡ä¿å…»è¡¨æ ¼åˆ—ï¼‰
  // ä¿å…»è®°å½•表格列配置(原设备保养表格列)
  const columns = ref([
    {
      label: "设备名称",
@@ -364,7 +371,9 @@
      label: "计划保养日期",
      align: "center",
      prop: "maintenancePlanTime",
      formatData: cell => dayjs(cell).format("YYYY-MM-DD"),
      formatData: cell => {
        return cell == null ? "-" : dayjs(cell).format("YYYY-MM-DD");
      },
    },
    {
      label: "录入人",
@@ -372,9 +381,10 @@
      prop: "createUserName",
    },
    {
      label: "项目",
      label: "保养项目",
      align: "center",
      prop: "machineryCategory",
      formatData: cell => cell || "--",
    },
    // {
    //   label: "录入日期",
@@ -428,7 +438,7 @@
    }
  };
  // å®šæ—¶ä»»åŠ¡ç®¡ç†ç›¸å…³æ–¹æ³•
  // ä¿å…»ä»»åŠ¡ç›¸å…³æ–¹æ³•
  const getScheduledTableData = async () => {
    try {
      const params = {
@@ -495,7 +505,7 @@
    ElMessage.info("导出定时任务功能待实现");
  };
  // ä»»åŠ¡è®°å½•ç›¸å…³æ–¹æ³•ï¼ˆåŽŸè®¾å¤‡ä¿å…»é¡µé¢æ–¹æ³•ï¼‰
  // ä¿å…»è®°å½•相关方法(原设备保养页面方法)
  const getTableData = async () => {
    try {
      const params = {
src/views/financialManagement/assets/fixedAssets.vue
@@ -38,11 +38,12 @@
        <div>
          <el-button type="primary" @click="add" icon="Plus">新增资产</el-button>
          <el-button type="warning" @click="handleDepreciation" icon="Money">折旧计提</el-button>
          <el-button @click="handleOut" icon="Download">导出</el-button>
          <!-- <el-button @click="handleOut" icon="Download">导出</el-button> -->
        </div>
      </div>
      <PIMTable
        rowKey="id"
        isSelection
        :column="columns"
        :tableData="dataList"
        :page="{
@@ -50,6 +51,7 @@
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @selection-change="handleSelectionChange"
        @pagination="changePage"
      >
        <template #originalValue="{ row }">
@@ -76,7 +78,7 @@
    </div>
    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
      <el-form :model="form" :rules="rules" :disabled="isView" ref="formRef" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="资产编号" prop="assetCode">
@@ -178,7 +180,7 @@
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitForm">确定</el-button>
        <el-button v-if="!isView" type="primary" @click="submitForm">确定</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </template>
    </FormDialog>
@@ -189,6 +191,13 @@
import { ref, reactive, onMounted, computed } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import {
  listFixedAssetPage,
  addFixedAsset,
  updateFixedAsset,
  deleteFixedAsset,
  depreciateFixedAsset,
} from "@/api/financialManagement/fixedAsset";
defineOptions({
  name: "固定资产",
@@ -210,23 +219,30 @@
const columns = [
  { label: "资产编号", prop: "assetCode", width: "130" },
  { label: "资产名称", prop: "assetName", width: "150" },
  { label: "资产类别", prop: "category", slot: "category" },
  { label: "资产类别", prop: "category", dataType: "slot", slot: "category" },
  { label: "规格型号", prop: "specification", width: "120" },
  { label: "资产原值", prop: "originalValue", slot: "originalValue" },
  { label: "累计折旧", prop: "accumulatedDepreciation", slot: "accumulatedDepreciation" },
  { label: "资产净值", prop: "netValue", slot: "netValue" },
  { label: "状态", prop: "status", slot: "status" },
  { label: "操作", prop: "operation", slot: "operation", width: "180", fixed: "right" },
  { label: "资产原值", prop: "originalValue", dataType: "slot", slot: "originalValue" },
  { label: "累计折旧", prop: "accumulatedDepreciation", dataType: "slot", slot: "accumulatedDepreciation" },
  { label: "资产净值", prop: "netValue", dataType: "slot", slot: "netValue" },
  { label: "状态", prop: "status", dataType: "slot", slot: "status" },
  { label: "操作", prop: "operation", dataType: "slot", slot: "operation", width: "180", fixed: "right" },
];
const dataList = ref([]);
const multipleList = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
const isView = ref(false);
const currentId = ref(null);
const selectedIds = computed(() =>
  multipleList.value
    .map(item => item?.id)
    .filter(id => id !== undefined && id !== null && id !== "")
);
const form = reactive({
const createDefaultForm = () => ({
  assetCode: "",
  assetName: "",
  category: "",
@@ -244,6 +260,10 @@
  remark: "",
});
const form = reactive({
  ...createDefaultForm(),
});
const rules = {
  assetName: [{ required: true, message: "请输入资产名称", trigger: "blur" }],
  category: [{ required: true, message: "请选择资产类别", trigger: "change" }],
@@ -251,13 +271,6 @@
  originalValue: [{ required: true, message: "请输入资产原值", trigger: "blur" }],
  usefulLife: [{ required: true, message: "请输入使用年限", trigger: "blur" }],
};
const mockData = [
  { id: 1, assetCode: "GD2024001", assetName: "办公电脑", category: "electronic", specification: "联想ThinkPad X1", purchaseDate: "2023-01-15", originalValue: 8000, usefulLife: 5, residualRate: 5, accumulatedDepreciation: 1520, netValue: 6480, location: "办公室", department: "财务部", keeper: "张三", status: "in_use", remark: "" },
  { id: 2, assetCode: "GD2024002", assetName: "打印机", category: "electronic", specification: "惠普M479fdw", purchaseDate: "2023-03-20", originalValue: 3500, usefulLife: 5, residualRate: 5, accumulatedDepreciation: 532, netValue: 2968, location: "文印室", department: "行政部", keeper: "李四", status: "in_use", remark: "" },
  { id: 3, assetCode: "GD2024003", assetName: "办公桌椅", category: "furniture", specification: "实木办公桌", purchaseDate: "2023-06-10", originalValue: 2500, usefulLife: 10, residualRate: 5, accumulatedDepreciation: 118.75, netValue: 2381.25, location: "办公室", department: "销售部", keeper: "王五", status: "in_use", remark: "" },
  { id: 4, assetCode: "GD2024004", assetName: "商务车", category: "vehicle", specification: "别克GL8", purchaseDate: "2022-08-01", originalValue: 280000, usefulLife: 10, residualRate: 5, accumulatedDepreciation: 53200, netValue: 226800, location: "停车场", department: "行政部", keeper: "赵六", status: "in_use", remark: "" },
];
const totalOriginalValue = computed(() => {
  return dataList.value.reduce((sum, item) => sum + Number(item.originalValue), 0);
@@ -288,35 +301,44 @@
};
const getStatusLabel = (status) => {
  const map = { in_use: "在用", idle: "闲置", scrapped: "报废" };
  return map[status] || status;
  const key = String(status || "").toLowerCase();
  const map = { in_use: "在用", idle: "闲置", repair: "维修中", scrapped: "报废" };
  return map[key] || status;
};
const getStatusType = (status) => {
  const map = { in_use: "success", idle: "warning", scrapped: "info" };
  return map[status] || "";
  const key = String(status || "").toLowerCase();
  const map = { in_use: "success", idle: "warning", repair: "warning", scrapped: "info" };
  return map[key] || "";
};
const calculateNetValue = () => {
  form.netValue = Number((form.originalValue - form.accumulatedDepreciation).toFixed(2));
  const originalValue = Number(form.originalValue || 0);
  const accumulatedDepreciation = Number(form.accumulatedDepreciation || 0);
  form.netValue = Number((originalValue - accumulatedDepreciation).toFixed(2));
};
const getTableData = () => {
  let result = [...mockData];
  if (filters.assetCode) {
    result = result.filter(item => item.assetCode.includes(filters.assetCode));
// è”调约定:分页参数固定为 current/size,返回 data.records/data.total
const getTableData = async () => {
  try {
    const { data } = await listFixedAssetPage({
      current: pagination.currentPage,
      size: pagination.pageSize,
      assetCode: filters.assetCode,
      assetName: filters.assetName,
      category: filters.category,
      status: filters.status,
    });
    dataList.value = data?.records || [];
    multipleList.value = [];
    pagination.total = Number(data?.total || 0);
  } catch (error) {
    // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
  }
  if (filters.assetName) {
    result = result.filter(item => item.assetName.includes(filters.assetName));
  }
  if (filters.category) {
    result = result.filter(item => item.category === filters.category);
  }
  if (filters.status) {
    result = result.filter(item => item.status === filters.status);
  }
  pagination.total = result.length;
  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
};
const handleSelectionChange = (selectionList) => {
  multipleList.value = selectionList;
};
const resetFilters = () => {
@@ -334,39 +356,32 @@
  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, {
    assetCode: "GD" + Date.now().toString().slice(-8),
    assetName: "",
    category: "",
    specification: "",
  Object.assign(form, createDefaultForm(), {
    assetCode: buildAssetCode(),
    purchaseDate: new Date().toISOString().split('T')[0],
    originalValue: 0,
    usefulLife: 5,
    residualRate: 5,
    accumulatedDepreciation: 0,
    netValue: 0,
    location: "",
    department: "",
    keeper: "",
    status: "in_use",
    remark: "",
  });
  dialogVisible.value = true;
};
const edit = (row) => {
  isEdit.value = true;
  isView.value = false;
  currentId.value = row.id;
  dialogTitle.value = "编辑固定资产";
  Object.assign(form, row);
  Object.assign(form, createDefaultForm(), row);
  dialogVisible.value = true;
};
const view = (row) => {
  ElMessage.info(`查看资产: ${row.assetName}`);
  edit(row);
  isView.value = true;
};
const handleDelete = (row) => {
@@ -374,31 +389,30 @@
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData.splice(index, 1);
  }).then(async () => {
    // è”调约定:删除接口使用 ids=1&ids=2
    await deleteFixedAsset([row.id]);
    if (dataList.value.length === 1 && pagination.currentPage > 1) {
      pagination.currentPage -= 1;
    }
    ElMessage.success("删除成功");
    getTableData();
    await getTableData();
  });
};
const handleDepreciation = () => {
  ElMessageBox.confirm("确认进行本月折旧计提吗?", "提示", {
  const ids = selectedIds.value;
  const confirmText = ids.length
    ? `确认对选中的 ${ids.length} æ¡èµ„产进行本月折旧计提吗?`
    : "确认进行本月折旧计提吗?";
  ElMessageBox.confirm(confirmText, "提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "info",
  }).then(() => {
    mockData.forEach(item => {
      if (item.status === "in_use") {
        const monthlyDepreciation = (item.originalValue * (1 - item.residualRate / 100)) / (item.usefulLife * 12);
        item.accumulatedDepreciation = Number((item.accumulatedDepreciation + monthlyDepreciation).toFixed(2));
        item.netValue = Number((item.originalValue - item.accumulatedDepreciation).toFixed(2));
      }
    });
  }).then(async () => {
    await depreciateFixedAsset({ ids });
    ElMessage.success("折旧计提完成");
    getTableData();
    await getTableData();
  });
};
@@ -407,22 +421,28 @@
};
const submitForm = () => {
  formRef.value.validate((valid) => {
  if (isView.value) {
    dialogVisible.value = false;
    return;
  }
  formRef.value.validate(async valid => {
    if (valid) {
      calculateNetValue();
      if (isEdit.value) {
        const index = mockData.findIndex(item => item.id === currentId.value);
        if (index !== -1) {
          mockData[index] = { ...mockData[index], ...form };
      try {
        calculateNetValue();
        const payload = { ...form };
        if (isEdit.value) {
          payload.id = currentId.value;
          await updateFixedAsset(payload);
          ElMessage.success("编辑成功");
        } else {
          await addFixedAsset(payload);
          ElMessage.success("新增成功");
        }
        ElMessage.success("编辑成功");
      } else {
        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
        mockData.push({ id: newId, ...form });
        ElMessage.success("新增成功");
        dialogVisible.value = false;
        await getTableData();
      } catch (error) {
        // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
      }
      dialogVisible.value = false;
      getTableData();
    }
  });
};
src/views/financialManagement/assets/intangibleAssets.vue
@@ -39,11 +39,12 @@
        <div>
          <el-button type="primary" @click="add" icon="Plus">新增资产</el-button>
          <el-button type="warning" @click="handleAmortization" icon="Money">摊销计提</el-button>
          <el-button @click="handleOut" icon="Download">导出</el-button>
          <!-- <el-button @click="handleOut" icon="Download">导出</el-button> -->
        </div>
      </div>
      <PIMTable
        rowKey="id"
        isSelection
        :column="columns"
        :tableData="dataList"
        :page="{
@@ -51,6 +52,7 @@
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @selection-change="handleSelectionChange"
        @pagination="changePage"
      >
        <template #originalValue="{ row }">
@@ -77,7 +79,7 @@
    </div>
    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
      <el-form :model="form" :rules="rules" :disabled="isView" ref="formRef" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="资产编号" prop="assetCode">
@@ -171,7 +173,7 @@
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitForm">确定</el-button>
        <el-button v-if="!isView" type="primary" @click="submitForm">确定</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </template>
    </FormDialog>
@@ -182,6 +184,13 @@
import { ref, reactive, onMounted, computed } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import {
  listIntangibleAssetPage,
  addIntangibleAsset,
  updateIntangibleAsset,
  deleteIntangibleAsset,
  amortizeIntangibleAsset,
} from "@/api/financialManagement/intangibleAsset";
defineOptions({
  name: "无形资产",
@@ -203,23 +212,30 @@
const columns = [
  { label: "资产编号", prop: "assetCode", width: "130" },
  { label: "资产名称", prop: "assetName", width: "150" },
  { label: "资产类别", prop: "category", slot: "category" },
  { label: "资产类别", prop: "category", dataType: "slot", slot: "category" },
  { label: "证书编号", prop: "certificateNo", width: "150" },
  { label: "资产原值", prop: "originalValue", slot: "originalValue" },
  { label: "累计摊销", prop: "accumulatedAmortization", slot: "accumulatedAmortization" },
  { label: "资产净值", prop: "netValue", slot: "netValue" },
  { label: "状态", prop: "status", slot: "status" },
  { label: "操作", prop: "operation", slot: "operation", width: "180", fixed: "right" },
  { label: "资产原值", prop: "originalValue", dataType: "slot", slot: "originalValue" },
  { label: "累计摊销", prop: "accumulatedAmortization", dataType: "slot", slot: "accumulatedAmortization" },
  { label: "资产净值", prop: "netValue", dataType: "slot", slot: "netValue" },
  { label: "状态", prop: "status", dataType: "slot", slot: "status" },
  { label: "操作", prop: "operation", dataType: "slot", slot: "operation", width: "180", fixed: "right" },
];
const dataList = ref([]);
const multipleList = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
const isView = ref(false);
const currentId = ref(null);
const selectedIds = computed(() =>
  multipleList.value
    .map(item => item?.id)
    .filter(id => id !== undefined && id !== null && id !== "")
);
const form = reactive({
const createDefaultForm = () => ({
  assetCode: "",
  assetName: "",
  category: "",
@@ -236,6 +252,10 @@
  remark: "",
});
const form = reactive({
  ...createDefaultForm(),
});
const rules = {
  assetName: [{ required: true, message: "请输入资产名称", trigger: "blur" }],
  category: [{ required: true, message: "请选择资产类别", trigger: "change" }],
@@ -243,13 +263,6 @@
  originalValue: [{ required: true, message: "请输入资产原值", trigger: "blur" }],
  amortizationPeriod: [{ required: true, message: "请输入摊销年限", trigger: "blur" }],
};
const mockData = [
  { id: 1, assetCode: "WX2024001", assetName: "ERP软件许可", category: "software", certificateNo: "SW-2023-001", acquisitionDate: "2023-01-01", originalValue: 50000, amortizationPeriod: 10, residualRate: 0, accumulatedAmortization: 5000, netValue: 45000, validityDate: "2033-01-01", status: "in_use", description: "企业资源计划管理系统", remark: "" },
  { id: 2, assetCode: "WX2024002", assetName: "发明专利", category: "patent", certificateNo: "ZL202210123456.7", acquisitionDate: "2022-06-15", originalValue: 100000, amortizationPeriod: 20, residualRate: 0, accumulatedAmortization: 3750, netValue: 96250, validityDate: "2042-06-15", status: "in_use", description: "一种新型生产工艺", remark: "" },
  { id: 3, assetCode: "WX2024003", assetName: "商标权", category: "trademark", certificateNo: "TM-2023-008", acquisitionDate: "2023-03-10", originalValue: 20000, amortizationPeriod: 10, residualRate: 0, accumulatedAmortization: 1500, netValue: 18500, validityDate: "2033-03-10", status: "in_use", description: "公司品牌商标", remark: "" },
  { id: 4, assetCode: "WX2024004", assetName: "土地使用权", category: "land", certificateNo: "土国用(2023)第001号", acquisitionDate: "2023-07-01", originalValue: 500000, amortizationPeriod: 50, residualRate: 0, accumulatedAmortization: 5000, netValue: 495000, validityDate: "2073-07-01", status: "in_use", description: "工业用地使用权", remark: "" },
];
const totalOriginalValue = computed(() => {
  return dataList.value.reduce((sum, item) => sum + Number(item.originalValue), 0);
@@ -281,35 +294,49 @@
};
const getStatusLabel = (status) => {
  const map = { in_use: "在用", idle: "闲置", amortized: "已摊销完毕" };
  return map[status] || status;
  const key = String(status || "").toLowerCase();
  const map = {
    in_use: "在用",
    idle: "闲置",
    expired: "已到期",
    amortized: "已摊销完毕",
  };
  return map[key] || status;
};
const getStatusType = (status) => {
  const map = { in_use: "success", idle: "warning", amortized: "info" };
  return map[status] || "";
  const key = String(status || "").toLowerCase();
  const map = { in_use: "success", idle: "warning", expired: "warning", amortized: "info" };
  return map[key] || "";
};
const calculateNetValue = () => {
  form.netValue = Number((form.originalValue - form.accumulatedAmortization).toFixed(2));
  const originalValue = Number(form.originalValue || 0);
  const accumulatedAmortization = Number(form.accumulatedAmortization || 0);
  form.netValue = Number((originalValue - accumulatedAmortization).toFixed(2));
};
const getTableData = () => {
  let result = [...mockData];
  if (filters.assetCode) {
    result = result.filter(item => item.assetCode.includes(filters.assetCode));
// è”调约定:分页参数固定为 current/size,返回 data.records/data.total
const getTableData = async () => {
  try {
    const { data } = await listIntangibleAssetPage({
      current: pagination.currentPage,
      size: pagination.pageSize,
      assetCode: filters.assetCode,
      assetName: filters.assetName,
      category: filters.category,
      status: filters.status,
    });
    dataList.value = data?.records || [];
    multipleList.value = [];
    pagination.total = Number(data?.total || 0);
  } catch (error) {
    // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
  }
  if (filters.assetName) {
    result = result.filter(item => item.assetName.includes(filters.assetName));
  }
  if (filters.category) {
    result = result.filter(item => item.category === filters.category);
  }
  if (filters.status) {
    result = result.filter(item => item.status === filters.status);
  }
  pagination.total = result.length;
  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
};
const handleSelectionChange = (selectionList) => {
  multipleList.value = selectionList;
};
const resetFilters = () => {
@@ -327,38 +354,32 @@
  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, {
    assetCode: "WX" + Date.now().toString().slice(-8),
    assetName: "",
    category: "",
    certificateNo: "",
  Object.assign(form, createDefaultForm(), {
    assetCode: buildAssetCode(),
    acquisitionDate: new Date().toISOString().split('T')[0],
    originalValue: 0,
    amortizationPeriod: 10,
    residualRate: 0,
    accumulatedAmortization: 0,
    netValue: 0,
    validityDate: "",
    status: "in_use",
    description: "",
    remark: "",
  });
  dialogVisible.value = true;
};
const edit = (row) => {
  isEdit.value = true;
  isView.value = false;
  currentId.value = row.id;
  dialogTitle.value = "编辑无形资产";
  Object.assign(form, row);
  Object.assign(form, createDefaultForm(), row);
  dialogVisible.value = true;
};
const view = (row) => {
  ElMessage.info(`查看资产: ${row.assetName}`);
  edit(row);
  isView.value = true;
};
const handleDelete = (row) => {
@@ -366,35 +387,30 @@
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData.splice(index, 1);
  }).then(async () => {
    // è”调约定:删除接口使用 ids=1&ids=2
    await deleteIntangibleAsset([row.id]);
    if (dataList.value.length === 1 && pagination.currentPage > 1) {
      pagination.currentPage -= 1;
    }
    ElMessage.success("删除成功");
    getTableData();
    await getTableData();
  });
};
const handleAmortization = () => {
  ElMessageBox.confirm("确认进行本月摊销计提吗?", "提示", {
  const ids = selectedIds.value;
  const confirmText = ids.length
    ? `确认对选中的 ${ids.length} æ¡èµ„产进行本月摊销计提吗?`
    : "确认进行本月摊销计提吗?";
  ElMessageBox.confirm(confirmText, "提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "info",
  }).then(() => {
    mockData.forEach(item => {
      if (item.status === "in_use") {
        const monthlyAmortization = (item.originalValue * (1 - item.residualRate / 100)) / (item.amortizationPeriod * 12);
        item.accumulatedAmortization = Number((item.accumulatedAmortization + monthlyAmortization).toFixed(2));
        item.netValue = Number((item.originalValue - item.accumulatedAmortization).toFixed(2));
        if (item.netValue <= 0) {
          item.status = "amortized";
          item.netValue = 0;
        }
      }
    });
  }).then(async () => {
    await amortizeIntangibleAsset({ ids });
    ElMessage.success("摊销计提完成");
    getTableData();
    await getTableData();
  });
};
@@ -403,22 +419,28 @@
};
const submitForm = () => {
  formRef.value.validate((valid) => {
  if (isView.value) {
    dialogVisible.value = false;
    return;
  }
  formRef.value.validate(async valid => {
    if (valid) {
      calculateNetValue();
      if (isEdit.value) {
        const index = mockData.findIndex(item => item.id === currentId.value);
        if (index !== -1) {
          mockData[index] = { ...mockData[index], ...form };
      try {
        calculateNetValue();
        const payload = { ...form };
        if (isEdit.value) {
          payload.id = currentId.value;
          await updateIntangibleAsset(payload);
          ElMessage.success("编辑成功");
        } else {
          await addIntangibleAsset(payload);
          ElMessage.success("新增成功");
        }
        ElMessage.success("编辑成功");
      } else {
        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
        mockData.push({ id: newId, ...form });
        ElMessage.success("新增成功");
        dialogVisible.value = false;
        await getTableData();
      } catch (error) {
        // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
      }
      dialogVisible.value = false;
      getTableData();
    }
  });
};
src/views/financialManagement/generalLedger/index.vue
@@ -1,23 +1,39 @@
<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.subjectCode" placeholder="请输入科目编码" clearable style="width: 200px;" />
        <el-input v-model="filters.subjectCode"
                  placeholder="请输入科目编码"
                  clearable
                  style="width: 200px;" />
      </el-form-item>
      <el-form-item label="科目名称:">
        <el-input v-model="filters.subjectName" placeholder="请输入科目名称" clearable style="width: 200px;" />
        <el-input v-model="filters.subjectName"
                  placeholder="请输入科目名称"
                  clearable
                  style="width: 200px;" />
      </el-form-item>
      <el-form-item label="科目类型:">
        <el-select v-model="filters.subjectType" placeholder="请选择" clearable style="width: 200px;">
          <el-option label="资产类" value="asset" />
          <el-option label="负债类" value="liability" />
          <el-option label="权益类" value="equity" />
          <el-option label="成本类" value="cost" />
          <el-option label="损益类" value="profit_loss" />
        <el-select v-model="filters.subjectType"
                   placeholder="请选择"
                   clearable
                   style="width: 200px;">
          <el-option label="资产类"
                     value="资产类" />
          <el-option label="负债类"
                     value="负债类" />
          <el-option label="权益类"
                     value="权益类" />
          <el-option label="成本类"
                     value="成本类" />
          <el-option label="损益类"
                     value="损益类" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getTableData">搜索</el-button>
        <el-button type="primary"
                   @click="getTableData">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </el-form-item>
    </el-form>
@@ -25,76 +41,131 @@
      <div class="actions">
        <div></div>
        <div>
          <el-button type="primary" @click="add" icon="Plus">新增</el-button>
          <el-button @click="handleOut" icon="Download">导出</el-button>
          <el-button type="primary"
                     @click="add"
                     icon="Plus">新增</el-button>
          <!-- <el-button @click="handleOut"
                     icon="Download">导出</el-button> -->
        </div>
      </div>
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @pagination="changePage"
      >
        <template #subjectType="{ row }">
          <el-tag :type="getSubjectTypeType(row.subjectType)">{{ getSubjectTypeLabel(row.subjectType) }}</el-tag>
        </template>
        <template #balanceDirection="{ row }">
          <el-tag :type="row.balanceDirection === 'debit' ? 'success' : 'danger'">
            {{ row.balanceDirection === 'debit' ? '借方' : '贷方' }}
          </el-tag>
        </template>
        <template #status="{ row }">
          <el-tag :type="row.status === 'active' ? 'success' : 'info'">
            {{ row.status === 'active' ? '启用' : '禁用' }}
          </el-tag>
        </template>
        <template #operation="{ row }">
          <el-button type="primary" link @click="edit(row)">编辑</el-button>
          <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
        </template>
      </PIMTable>
      <el-table ref="tableRef"
                v-loading="loading"
                :data="dataList"
                row-key="id"
                :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
                height="calc(100vh - 280px)"
                border
                stripe
                highlight-current-row
                class="subject-table">
        <el-table-column label="科目编码" prop="subjectCode" width="140">
          <template #default="scope">
            <span class="subject-code">{{ scope.row.subjectCode }}</span>
          </template>
        </el-table-column>
        <el-table-column label="科目名称" prop="subjectName" min-width="180">
          <template #default="scope">
            <span class="subject-name" :class="{ 'is-parent': scope.row.children?.length > 0 }">
              {{ scope.row.subjectName }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="科目类型" prop="subjectType" width="100" align="center">
          <template #default="scope">
            <el-tag size="small" :type="getSubjectTypeType(scope.row.subjectType)">
              {{ scope.row.subjectType }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="余额方向" prop="balanceDirection" width="100" align="center">
          <template #default="scope">
            <el-tag size="small" :type="scope.row.balanceDirection === '借方' ? 'primary' : 'danger'">
              {{ scope.row.balanceDirection }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="状态" prop="status" width="80" align="center">
          <template #default="scope">
            <el-tag size="small" :type="scope.row.status === 0 || scope.row.status === '0' ? 'success' : 'info'">
              {{ scope.row.status === 0 || scope.row.status === '0' ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="备注" prop="remark" show-overflow-tooltip min-width="150" />
        <el-table-column label="操作" align="center" fixed="right" width="240">
          <template #default="scope">
            <el-button link type="primary" icon="Plus" @click="addChild(scope.row)">新增</el-button>
            <el-button link type="primary" icon="Edit" @click="edit(scope.row)">编辑</el-button>
            <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="600px" @confirm="submitForm" @cancel="dialogVisible = false">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
        <el-form-item label="科目编码" prop="subjectCode">
          <el-input v-model="form.subjectCode" placeholder="请输入科目编码" />
    <FormDialog :title="dialogTitle"
                v-model="dialogVisible"
                width="600px"
                @confirm="submitForm"
                @cancel="dialogVisible = false">
      <el-form :model="form"
               :rules="rules"
               ref="formRef"
               label-width="100px">
        <el-form-item label="父级科目">
          <el-input :model-value="parentSubjectLabel"
                    disabled />
        </el-form-item>
        <el-form-item label="科目名称" prop="subjectName">
          <el-input v-model="form.subjectName" placeholder="请输入科目名称" />
        <el-form-item label="科目编码"
                      prop="subjectCode">
          <el-input v-model="form.subjectCode"
                    placeholder="请输入科目编码" />
        </el-form-item>
        <el-form-item label="科目类型" prop="subjectType">
          <el-select v-model="form.subjectType" placeholder="请选择科目类型" style="width: 100%;">
            <el-option label="资产类" value="asset" />
            <el-option label="负债类" value="liability" />
            <el-option label="权益类" value="equity" />
            <el-option label="成本类" value="cost" />
            <el-option label="损益类" value="profit_loss" />
        <el-form-item label="科目名称"
                      prop="subjectName">
          <el-input v-model="form.subjectName"
                    placeholder="请输入科目名称" />
        </el-form-item>
        <el-form-item label="科目类型"
                      prop="subjectType">
          <el-select v-model="form.subjectType"
                     placeholder="请选择科目类型"
                     style="width: 100%;">
            <el-option label="资产类"
                       value="资产类" />
            <el-option label="负债类"
                       value="负债类" />
            <el-option label="权益类"
                       value="权益类" />
            <el-option label="成本类"
                       value="成本类" />
            <el-option label="损益类"
                       value="损益类" />
          </el-select>
        </el-form-item>
        <el-form-item label="余额方向" prop="balanceDirection">
        <el-form-item label="余额方向"
                      prop="balanceDirection">
          <el-radio-group v-model="form.balanceDirection">
            <el-radio label="debit">借方</el-radio>
            <el-radio label="credit">贷方</el-radio>
            <el-radio label="借方">借方</el-radio>
            <el-radio label="贷方">贷方</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="状态" prop="status">
        <el-form-item label="状态"
                      prop="status">
          <el-radio-group v-model="form.status">
            <el-radio label="active">启用</el-radio>
            <el-radio label="inactive">禁用</el-radio>
            <el-radio :label="0">启用</el-radio>
            <el-radio :label="1">禁用</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
        <el-form-item label="备注"
                      prop="remark">
          <el-input v-model="form.remark"
                    type="textarea"
                    :rows="3"
                    placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitForm">确定</el-button>
        <el-button type="primary"
                   @click="submitForm">确定</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </template>
    </FormDialog>
@@ -102,190 +173,326 @@
</template>
<script setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
  import { ref, reactive, onMounted, getCurrentInstance, nextTick } from "vue";
  import { ElMessage, ElMessageBox } from "element-plus";
  import FormDialog from "@/components/Dialog/FormDialog.vue";
  import {
    listAccountSubject,
    addAccountSubject,
    updateAccountSubject,
    delAccountSubject,
    exportAccountSubject,
  } from "@/api/financialManagement/accountSubject";
defineOptions({
  name: "总帐科目",
});
  defineOptions({
    name: "总帐科目",
  });
const filters = reactive({
  subjectCode: "",
  subjectName: "",
  subjectType: "",
});
  const { proxy } = getCurrentInstance();
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
});
const columns = [
  { label: "科目编码", prop: "subjectCode", width: "120" },
  { label: "科目名称", prop: "subjectName", width: "150" },
  { label: "科目类型", prop: "subjectType", slot: "subjectType" },
  { label: "余额方向", prop: "balanceDirection", slot: "balanceDirection" },
  { label: "状态", prop: "status", slot: "status" },
  { label: "备注", prop: "remark", showOverflowTooltip: true },
  { label: "操作", prop: "operation", slot: "operation", width: "150", fixed: "right" },
];
const dataList = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
const currentId = ref(null);
const form = reactive({
  subjectCode: "",
  subjectName: "",
  subjectType: "",
  balanceDirection: "debit",
  status: "active",
  remark: "",
});
const rules = {
  subjectCode: [{ required: true, message: "请输入科目编码", trigger: "blur" }],
  subjectName: [{ required: true, message: "请输入科目名称", trigger: "blur" }],
  subjectType: [{ required: true, message: "请选择科目类型", trigger: "change" }],
};
const mockData = [
  { id: 1, subjectCode: "1001", subjectName: "库存现金", subjectType: "asset", balanceDirection: "debit", status: "active", remark: "" },
  { id: 2, subjectCode: "1002", subjectName: "银行存款", subjectType: "asset", balanceDirection: "debit", status: "active", remark: "" },
  { id: 3, subjectCode: "1122", subjectName: "应收账款", subjectType: "asset", balanceDirection: "debit", status: "active", remark: "" },
  { id: 4, subjectCode: "2202", subjectName: "应付账款", subjectType: "liability", balanceDirection: "credit", status: "active", remark: "" },
  { id: 5, subjectCode: "4001", subjectName: "实收资本", subjectType: "equity", balanceDirection: "credit", status: "active", remark: "" },
  { id: 6, subjectCode: "5001", subjectName: "生产成本", subjectType: "cost", balanceDirection: "debit", status: "active", remark: "" },
  { id: 7, subjectCode: "6001", subjectName: "主营业务收入", subjectType: "profit_loss", balanceDirection: "credit", status: "active", remark: "" },
  { id: 8, subjectCode: "6401", subjectName: "主营业务成本", subjectType: "profit_loss", balanceDirection: "debit", status: "active", remark: "" },
];
const getSubjectTypeLabel = (type) => {
  const map = {
    asset: "资产类",
    liability: "负债类",
    equity: "权益类",
    cost: "成本类",
    profit_loss: "损益类",
  };
  return map[type] || type;
};
const getSubjectTypeType = (type) => {
  const map = {
    asset: "success",
    liability: "danger",
    equity: "warning",
    cost: "info",
    profit_loss: "primary",
  };
  return map[type] || "";
};
const getTableData = () => {
  let result = [...mockData];
  if (filters.subjectCode) {
    result = result.filter(item => item.subjectCode.includes(filters.subjectCode));
  }
  if (filters.subjectName) {
    result = result.filter(item => item.subjectName.includes(filters.subjectName));
  }
  if (filters.subjectType) {
    result = result.filter(item => item.subjectType === filters.subjectType);
  }
  pagination.total = result.length;
  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
};
const resetFilters = () => {
  filters.subjectCode = "";
  filters.subjectName = "";
  filters.subjectType = "";
  pagination.currentPage = 1;
  getTableData();
};
const changePage = ({ current, size }) => {
  pagination.currentPage = current;
  pagination.pageSize = size;
  getTableData();
};
const add = () => {
  isEdit.value = false;
  dialogTitle.value = "新增科目";
  Object.assign(form, {
  const filters = reactive({
    subjectCode: "",
    subjectName: "",
    subjectType: "",
    balanceDirection: "debit",
    status: "active",
  });
  const pagination = reactive({
    currentPage: 1,
    pageSize: 10,
    total: 0,
  });
  const columns = [
    { label: "科目编码", prop: "subjectCode", width: "120" },
    { label: "科目名称", prop: "subjectName", width: "150" },
    { label: "科目类型", prop: "subjectType" },
    {
      label: "余额方向",
      prop: "balanceDirection",
      dataType: "tag",
      formatData: value => {
        if (value === "借方") {
          return "借方";
        }
        return "贷方";
      },
      formatType: value => {
        if (value === "借方") {
          return "primary";
        }
        return "danger";
      },
    },
    {
      label: "状态",
      prop: "status",
      dataType: "tag",
      formatData: value => {
        if (value === 0 || value === "0") {
          return "启用";
        }
        return "禁用";
      },
      formatType: value => {
        if (value === 0 || value === "0") {
          return "success";
        }
        return "info";
      },
    },
    { label: "备注", prop: "remark", showOverflowTooltip: true },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      fixed: "right",
      width: "220",
      operation: [
        {
          name: "新增",
          type: "primary",
          clickFun: row => {
            addChild(row);
          },
        },
        {
          name: "编辑",
          type: "primary",
          clickFun: row => {
            edit(row);
          },
        },
        {
          name: "删除",
          type: "danger",
          clickFun: row => {
            handleDelete(row);
          },
        },
      ],
    },
  ];
  const dataList = ref([]);
  const dialogVisible = ref(false);
  const dialogTitle = ref("");
  const parentSubjectLabel = ref("顶级科目");
  const formRef = ref(null);
  const tableRef = ref(null);
  const isEdit = ref(false);
  const loading = ref(false);
  const form = reactive({
    id: undefined,
    parentId: null,
    subjectCode: "",
    subjectName: "",
    subjectType: "",
    balanceDirection: "借方",
    status: 0,
    remark: "",
  });
  dialogVisible.value = true;
};
const edit = (row) => {
  isEdit.value = true;
  currentId.value = row.id;
  dialogTitle.value = "编辑科目";
  Object.assign(form, row);
  dialogVisible.value = true;
};
  const rules = {
    subjectCode: [{ required: true, message: "请输入科目编码", trigger: "blur" }],
    subjectName: [{ required: true, message: "请输入科目名称", trigger: "blur" }],
    subjectType: [
      { required: true, message: "请选择科目类型", trigger: "change" },
    ],
  };
const submitForm = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      if (isEdit.value) {
        const index = mockData.findIndex(item => item.id === currentId.value);
        if (index !== -1) {
          mockData[index] = { ...mockData[index], ...form };
        }
        ElMessage.success("编辑成功");
      } else {
        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
        mockData.push({ id: newId, ...form });
        ElMessage.success("新增成功");
  const getSubjectTypeType = type => {
    const map = {
      èµ„产类: "success",
      è´Ÿå€ºç±»: "danger",
      æƒç›Šç±»: "warning",
      æˆæœ¬ç±»: "info",
      æŸç›Šç±»: "primary",
    };
    return map[type] || "";
  };
  const getTableData = () => {
    loading.value = true;
    const query = {
      current: pagination.currentPage,
      size: pagination.pageSize,
      ...filters,
    };
    listAccountSubject(query).then(response => {
      dataList.value = response.data.records || [];
      loading.value = false;
    }).catch(() => {
      loading.value = false;
    });
  };
  const resetFilters = () => {
    filters.subjectCode = "";
    filters.subjectName = "";
    filters.subjectType = "";
    pagination.currentPage = 1;
    getTableData();
  };
  const changePage = obj => {
    pagination.currentPage = obj.page;
    pagination.pageSize = obj.limit;
    getTableData();
  };
  const buildParentSubjectLabel = parentRow => {
    if (!parentRow) {
      return "顶级科目";
    }
    const code = parentRow.subjectCode || "";
    const name = parentRow.subjectName || "";
    return `${code} ${name}`.trim();
  };
  const resetForm = ({ parentId = null, parentRow = null } = {}) => {
    Object.assign(form, {
      id: undefined,
      parentId,
      subjectCode: "",
      subjectName: "",
      subjectType: "",
      balanceDirection: "借方",
      status: 0,
      remark: "",
    });
    parentSubjectLabel.value = buildParentSubjectLabel(parentRow);
  };
  const add = () => {
    isEdit.value = false;
    dialogTitle.value = "新增科目";
    resetForm({ parentId: null, parentRow: null });
    dialogVisible.value = true;
  };
  const addChild = row => {
    isEdit.value = false;
    dialogTitle.value = "新增子科目";
    resetForm({ parentId: row.id, parentRow: row });
    form.subjectType = row.subjectType || "";
    form.balanceDirection = row.balanceDirection || "借方";
    dialogVisible.value = true;
  };
  const findSubjectById = (nodes, id) => {
    for (const item of nodes || []) {
      if (item.id === id) {
        return item;
      }
      dialogVisible.value = false;
      getTableData();
      if (item.children && item.children.length > 0) {
        const found = findSubjectById(item.children, id);
        if (found) {
          return found;
        }
      }
    }
  });
};
    return null;
  };
const handleDelete = (row) => {
  ElMessageBox.confirm("确认删除该科目吗?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData.splice(index, 1);
    }
    ElMessage.success("删除成功");
  const edit = row => {
    isEdit.value = true;
    dialogTitle.value = "编辑科目";
    Object.assign(form, row);
    form.parentId = row.parentId ?? null;
    const parentRow =
      row.parentId === null || row.parentId === undefined
        ? null
        : findSubjectById(dataList.value, row.parentId);
    parentSubjectLabel.value = parentRow
      ? buildParentSubjectLabel(parentRow)
      : row.parentId
      ? `上级ID: ${row.parentId}`
      : buildParentSubjectLabel(null);
    dialogVisible.value = true;
  };
  const submitForm = () => {
    formRef.value.validate(valid => {
      if (valid) {
        if (isEdit.value) {
          updateAccountSubject(form).then(() => {
            ElMessage.success("编辑成功");
            dialogVisible.value = false;
            getTableData();
          });
        } else {
          addAccountSubject(form).then(() => {
            ElMessage.success("新增成功");
            dialogVisible.value = false;
            getTableData();
          });
        }
      }
    });
  };
  const handleDelete = row => {
    const ids = row.id;
    ElMessageBox.confirm("确认删除该科目吗?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        return delAccountSubject(ids);
      })
      .then(() => {
        ElMessage.success("删除成功");
        getTableData();
      });
  };
  const handleOut = () => {
    proxy.download(
      "accountSubject/export",
      {
        ...filters,
      },
      `account_subject_${new Date().getTime()}.xlsx`
    );
  };
  onMounted(() => {
    getTableData();
  });
};
const handleOut = () => {
  ElMessage.success("导出成功");
};
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;
  }
  .subject-table {
    border-radius: 8px;
    overflow: hidden;
    :deep(.el-table__row) {
      transition: background-color 0.3s;
    }
    :deep(.el-table__row:hover) {
      background-color: #f5f7fa;
    }
    .subject-code {
      color: #606266;
    }
    .subject-name {
      font-weight: 500;
      &.is-parent {
        color: #409eff;
      }
    }
  }
</style>
src/views/financialManagement/payable/purchaseIn.vue
@@ -1,19 +1,27 @@
<template>
  <!-- é‡‡è´­å…¥åº“ -->
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="入库单号:">
        <el-input v-model="filters.inCode" placeholder="请输入入库单号" clearable style="width: 200px;" />
        <el-input v-model="filters.inboundBatches" placeholder="请输入入库单号" clearable style="width: 200px;" />
      </el-form-item>
      <el-form-item label="供应商:">
        <el-select v-model="filters.supplierId" placeholder="请选择供应商" clearable style="width: 200px;">
          <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
        <el-input v-model="filters.supplierName" 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="getTableData">搜索</el-button>
        <el-button type="primary" @click="onSearch">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </el-form-item>
    </el-form>
@@ -28,6 +36,7 @@
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :tableLoading="tableLoading"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
@@ -35,107 +44,28 @@
        }"
        @pagination="changePage"
      >
        <template #amount="{ row }">
          <span class="text-primary">Â¥{{ formatMoney(row.amount) }}</span>
        </template>
        <template #status="{ row }">
          <el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
        </template>
        <template #operation="{ row }">
          <el-button type="primary" link @click="view(row)">查看</el-button>
          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">编辑</el-button>
          <el-button type="danger" link @click="handleDelete(row)" v-if="row.status === 'pending'">删除</el-button>
        <template #inboundDate="{ row }">
          {{ row.InboundDate || row.inboundDate || "" }}
        </template>
      </PIMTable>
    </div>
    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="入库单号" prop="inCode">
              <el-input v-model="form.inCode" placeholder="请输入入库单号" :disabled="isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="供应商" prop="supplierId">
              <el-select v-model="form.supplierId" placeholder="请选择供应商" style="width: 100%;" :disabled="isEdit">
                <el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="入库日期" prop="inDate">
              <el-date-picker v-model="form.inDate" 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="amount">
              <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="入库明细" prop="details">
          <el-table :data="form.details" border style="width: 100%">
            <el-table-column prop="materialName" label="物料名称" width="150">
              <template #default="{ $index }">
                <el-input v-model="form.details[$index].materialName" placeholder="物料名称" />
              </template>
            </el-table-column>
            <el-table-column prop="spec" label="规格" width="120">
              <template #default="{ $index }">
                <el-input v-model="form.details[$index].spec" placeholder="规格" />
              </template>
            </el-table-column>
            <el-table-column prop="quantity" label="数量" width="100">
              <template #default="{ $index }">
                <el-input-number v-model="form.details[$index].quantity" :min="0" style="width: 100%;" />
              </template>
            </el-table-column>
            <el-table-column prop="unitPrice" label="单价" width="120">
              <template #default="{ $index }">
                <el-input-number v-model="form.details[$index].unitPrice" :min="0" :precision="2" style="width: 100%;" />
              </template>
            </el-table-column>
            <el-table-column prop="total" label="金额" width="120">
              <template #default="{ row }">
                <span>Â¥{{ formatMoney(row.quantity * row.unitPrice) }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="80">
              <template #default="{ $index }">
                <el-button type="danger" link @click="removeDetail($index)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
          <el-button type="primary" link @click="addDetail" style="margin-top: 10px;">+ æ·»åŠ æ˜Žç»†</el-button>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitForm">确定</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </template>
    </FormDialog>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { ref, reactive, onMounted, getCurrentInstance } from "vue";
import { ElMessage } from "element-plus";
import { listPageAccountPurchase } from "@/api/financialManagement/accountPurchase";
defineOptions({
  name: "采购入库",
});
const { proxy } = getCurrentInstance();
const filters = reactive({
  inCode: "",
  supplierId: "",
  inboundBatches: "",
  supplierName: "",
  dateRange: [],
});
@@ -146,170 +76,85 @@
});
const columns = [
  { label: "入库单号", prop: "inCode", width: "150" },
  { label: "供应商", prop: "supplierName", width: "180" },
  { label: "入库日期", prop: "inDate", width: "120" },
  { label: "入库金额", prop: "amount", slot: "amount" },
  { label: "状态", prop: "status", slot: "status" },
  { label: "备注", prop: "remark", showOverflowTooltip: true },
  { label: "操作", prop: "operation", slot: "operation", width: "200", fixed: "right" },
  { label: "入库单号", prop: "inboundBatches", minWidth: "150" },
  { label: "供应商", prop: "supplierName", minWidth: "180" },
  {
    label: "入库日期",
    prop: "InboundDate",
    minWidth: "170",
    dataType: "slot",
    slot: "inboundDate",
  },
  { label: "产品名称", prop: "productName", minWidth: "140" },
  { label: "产品规格", prop: "specificationModel", minWidth: "140" },
  { label: "采购订单号", prop: "purchaseContractNumber", minWidth: "150" },
];
const dataList = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
const currentId = ref(null);
const tableLoading = ref(false);
const supplierList = [
  { id: 1, name: "北京原材料供应商" },
  { id: 2, name: "上海电子元器件公司" },
  { id: 3, name: "广州包装材料厂" },
  { id: 4, name: "深圳五金配件公司" },
];
function buildFilterParams() {
  const params = {
    inboundBatches: filters.inboundBatches || undefined,
    supplierName: filters.supplierName || undefined,
  };
  if (filters.dateRange && filters.dateRange.length === 2) {
    params.startDate = filters.dateRange[0];
    params.endDate = filters.dateRange[1];
  }
  return params;
}
const form = reactive({
  inCode: "",
  supplierId: "",
  inDate: "",
  amount: 0,
  details: [],
  remark: "",
});
const rules = {
  inCode: [{ required: true, message: "请输入入库单号", trigger: "blur" }],
  supplierId: [{ required: true, message: "请选择供应商", trigger: "change" }],
  inDate: [{ required: true, message: "请选择入库日期", trigger: "change" }],
  amount: [{ required: true, message: "请输入入库金额", trigger: "blur" }],
};
const mockData = [
  { id: 1, inCode: "RK2024001", supplierId: 1, supplierName: "北京原材料供应商", inDate: "2024-01-10", amount: 8000, status: "approved", details: [{ materialName: "钢材", spec: "Q235", quantity: 10, unitPrice: 500 }], remark: "" },
  { id: 2, inCode: "RK2024002", supplierId: 2, supplierName: "上海电子元器件公司", inDate: "2024-01-12", amount: 12000, status: "pending", details: [{ materialName: "芯片", spec: "STM32", quantity: 100, unitPrice: 80 }], remark: "" },
  { id: 3, inCode: "RK2024003", supplierId: 3, supplierName: "广州包装材料厂", inDate: "2024-01-15", amount: 3500, status: "approved", details: [{ materialName: "纸箱", spec: "50*40*30", quantity: 500, unitPrice: 5 }], remark: "" },
];
const formatMoney = (value) => {
  if (value === undefined || value === null) return "0.00";
  return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
const getStatusLabel = (status) => {
  const map = { pending: "待审核", approved: "已审核", rejected: "已驳回" };
  return map[status] || status;
};
const getStatusType = (status) => {
  const map = { pending: "warning", approved: "success", rejected: "danger" };
  return map[status] || "";
const onSearch = () => {
  pagination.currentPage = 1;
  getTableData();
};
const getTableData = () => {
  let result = [...mockData];
  if (filters.inCode) {
    result = result.filter(item => item.inCode.includes(filters.inCode));
  }
  if (filters.supplierId) {
    result = result.filter(item => item.supplierId === filters.supplierId);
  }
  if (filters.dateRange && filters.dateRange.length === 2) {
    result = result.filter(item => item.inDate >= filters.dateRange[0] && item.inDate <= filters.dateRange[1]);
  }
  pagination.total = result.length;
  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
  tableLoading.value = true;
  listPageAccountPurchase({
    ...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 = [];
    })
    .finally(() => {
      tableLoading.value = false;
    });
};
const resetFilters = () => {
  filters.inCode = "";
  filters.supplierId = "";
  filters.inboundBatches = "";
  filters.supplierName = "";
  filters.dateRange = [];
  pagination.currentPage = 1;
  getTableData();
};
const changePage = ({ current, size }) => {
  pagination.currentPage = current;
  pagination.pageSize = size;
const changePage = ({ page, limit }) => {
  pagination.currentPage = page;
  pagination.pageSize = limit;
  getTableData();
};
const addDetail = () => {
  form.details.push({ materialName: "", spec: "", quantity: 0, unitPrice: 0 });
};
const removeDetail = (index) => {
  form.details.splice(index, 1);
};
const add = () => {
  isEdit.value = false;
  dialogTitle.value = "新增入库";
  Object.assign(form, {
    inCode: "RK" + Date.now().toString().slice(-8),
    supplierId: "",
    inDate: new Date().toISOString().split('T')[0],
    amount: 0,
    details: [{ materialName: "", spec: "", quantity: 0, unitPrice: 0 }],
    remark: "",
  });
  dialogVisible.value = true;
};
const edit = (row) => {
  isEdit.value = true;
  currentId.value = row.id;
  dialogTitle.value = "编辑入库";
  Object.assign(form, row);
  if (!form.details || form.details.length === 0) {
    form.details = [{ materialName: "", spec: "", quantity: 0, unitPrice: 0 }];
  }
  dialogVisible.value = true;
};
const view = (row) => {
  ElMessage.info(`查看入库单: ${row.inCode}`);
};
const handleDelete = (row) => {
  ElMessageBox.confirm("确认删除该入库单吗?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData.splice(index, 1);
    }
    ElMessage.success("删除成功");
    getTableData();
  });
};
const handleOut = () => {
  ElMessage.success("导出成功");
};
const submitForm = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      const supplier = supplierList.find(item => item.id === form.supplierId);
      if (isEdit.value) {
        const index = mockData.findIndex(item => item.id === currentId.value);
        if (index !== -1) {
          mockData[index] = { ...mockData[index], ...form, supplierName: supplier?.name };
        }
        ElMessage.success("编辑成功");
      } else {
        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
        mockData.push({ id: newId, ...form, supplierName: supplier?.name, status: "pending" });
        ElMessage.success("新增成功");
      }
      dialogVisible.value = false;
      getTableData();
    }
  });
  proxy.download(
    "/accountPurchase/exportAccountPurchaseInbound",
    buildFilterParams(),
    `采购入库_${new Date().getTime()}.xlsx`
  );
};
onMounted(() => {
@@ -322,10 +167,5 @@
  display: flex;
  justify-content: space-between;
  margin-bottom: 15px;
}
.text-primary {
  color: #409eff;
  font-weight: bold;
}
</style>
src/views/financialManagement/payable/purchaseReturn.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,239 @@
<template>
  <!-- é‡‡è´­é€€è´§ -->
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="退货单号:">
        <el-input
          v-model="filters.returnNo"
          placeholder="请输入退货单号"
          clearable
          style="width: 200px"
        />
      </el-form-item>
      <el-form-item label="供应商:">
        <el-input
          v-model="filters.supplierName"
          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-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSearch">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </el-form-item>
    </el-form>
    <div class="table_list">
      <div class="actions">
        <div></div>
        <div>
          <el-button @click="handleOut" icon="Download">导出</el-button>
        </div>
      </div>
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :tableLoading="tableLoading"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @pagination="changePage"
      />
    </div>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, getCurrentInstance } from "vue";
import { ElMessage } from "element-plus";
import { listPageAccountPurchaseReturn } from "@/api/financialManagement/accountPurchase";
defineOptions({
  name: "采购退货",
});
const { proxy } = getCurrentInstance();
const filters = reactive({
  returnNo: "",
  supplierName: "",
  dateRange: [],
});
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
});
const columns = [
  { label: "退货单号", prop: "returnNo", minWidth: "150" },
  { label: "供应商", prop: "supplierName", minWidth: "180" },
  { label: "关联入库单号", prop: "inboundBatches", minWidth: "150" },
  { label: "退货日期", prop: "preparedAt", minWidth: "170" },
  {
    label: "退款总额",
    prop: "totalAmount",
    minWidth: "150",
    align: "right",
    formatData: (val) =>
      val === null || val === undefined || val === ""
        ? ""
        : Number(val).toLocaleString("zh-CN", {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
          }),
  },
  { label: "退货方式", prop: "returnType", minWidth: "150" },
  { label: "采购订单号", prop: "purchaseContractNumber", minWidth: "150" },
];
const dataList = ref([]);
const tableLoading = ref(false);
function buildFilterParams() {
  const params = {
    returnNo: filters.returnNo || undefined,
    supplierName: filters.supplierName || undefined,
  };
  if (filters.dateRange && filters.dateRange.length === 2) {
    params.startDate = filters.dateRange[0];
    params.endDate = filters.dateRange[1];
  }
  return params;
}
const onSearch = () => {
  pagination.currentPage = 1;
  getTableData();
};
const getTableData = () => {
  tableLoading.value = true;
  listPageAccountPurchaseReturn({
    ...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 = [];
    })
    .finally(() => {
      tableLoading.value = false;
    });
};
const resetFilters = () => {
  filters.returnNo = "";
  filters.supplierName = "";
  filters.dateRange = [];
  pagination.currentPage = 1;
  getTableData();
};
const changePage = ({ page, limit }) => {
  pagination.currentPage = page;
  pagination.pageSize = limit;
  getTableData();
};
const handleOut = () => {
  proxy.download(
    "/accountPurchase/exportAccountPurchaseReturn",
    buildFilterParams(),
    `采购退货_${new Date().getTime()}.xlsx`
  );
};
onMounted(() => {
  getTableData();
});
</script>
<style lang="scss" scoped>
.actions {
  display: flex;
  justify-content: space-between;
  margin-bottom: 15px;
}
</style>
src/views/financialManagement/receivable/salesOut.vue
@@ -1,19 +1,27 @@
<template>
<!-- é”€å”®å‡ºåº“ -->
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="出库单号:">
        <el-input v-model="filters.outCode" placeholder="请输入出库单号" clearable style="width: 200px;" />
        <el-input v-model="filters.outboundBatches" placeholder="请输入出库单号" clearable style="width: 200px;" />
      </el-form-item>
      <el-form-item label="客户:">
        <el-select v-model="filters.customerId" placeholder="请选择客户" clearable style="width: 200px;">
          <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
      <el-form-item label="客户名称:">
        <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="getTableData">搜索</el-button>
        <el-button type="primary" @click="onSearch">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </el-form-item>
    </el-form>
@@ -28,76 +36,32 @@
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :tableLoading="tableLoading"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @pagination="changePage"
      >
        <template #status="{ row }">
          <el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
        </template>
        <template #operation="{ row }">
          <el-button type="primary" link @click="view(row)">查看</el-button>
          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">编辑</el-button>
          <el-button type="danger" link @click="handleDelete(row)" v-if="row.status === 'pending'">删除</el-button>
        </template>
      </PIMTable>
      />
    </div>
    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="出库单号" prop="outCode">
              <el-input v-model="form.outCode" placeholder="请输入出库单号" :disabled="isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户" prop="customerId">
              <el-select v-model="form.customerId" placeholder="请选择客户" style="width: 100%;" :disabled="isEdit">
                <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="出库日期" prop="outDate">
              <el-date-picker v-model="form.outDate" 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="amount">
              <el-input-number v-model="form.amount" :min="0" :precision="2" 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>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitForm">确定</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </template>
    </FormDialog>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { ref, reactive, onMounted, getCurrentInstance } from "vue";
import { ElMessage } from "element-plus";
import { listPageAccountSales } from "@/api/financialManagement/accountSales";
defineOptions({
  name: "销售出库",
});
const { proxy } = getCurrentInstance();
const filters = reactive({
  outCode: "",
  customerId: "",
  outboundBatches: "",
  customerName: "",
  dateRange: [],
});
@@ -108,153 +72,87 @@
});
const columns = [
  { label: "出库单号", prop: "outCode", width: "150" },
  { label: "客户名称", prop: "customerName", width: "180" },
  { label: "出库日期", prop: "outDate", width: "120" },
  { label: "金额", prop: "amount", width: "120" },
  { label: "状态", prop: "status", slot: "status" },
  { label: "备注", prop: "remark", showOverflowTooltip: true },
  { label: "操作", prop: "operation", slot: "operation", width: "200", fixed: "right" },
  { 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 dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
const currentId = ref(null);
const tableLoading = ref(false);
const customerList = [
  { id: 1, name: "北京科技有限公司" },
  { id: 2, name: "上海贸易公司" },
  { id: 3, name: "广州实业有限公司" },
  { id: 4, name: "深圳电子公司" },
];
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;
}
const form = reactive({
  outCode: "",
  customerId: "",
  outDate: "",
  amount: 0,
  remark: "",
});
const rules = {
  outCode: [{ required: true, message: "请输入出库单号", trigger: "blur" }],
  customerId: [{ required: true, message: "请选择客户", trigger: "change" }],
  outDate: [{ required: true, message: "请选择出库日期", trigger: "change" }],
  amount: [{ required: true, message: "请输入金额", trigger: "blur" }],
};
const mockData = [
  { id: 1, outCode: "CK2024001", customerId: 1, customerName: "北京科技有限公司", outDate: "2024-01-15", amount: 5000, status: "approved", remark: "" },
  { id: 2, outCode: "CK2024002", customerId: 2, customerName: "上海贸易公司", outDate: "2024-01-16", amount: 8000, status: "pending", remark: "" },
  { id: 3, outCode: "CK2024003", customerId: 3, customerName: "广州实业有限公司", outDate: "2024-01-18", amount: 12000, status: "approved", remark: "" },
  { id: 4, outCode: "CK2024004", customerId: 4, customerName: "深圳电子公司", outDate: "2024-01-20", amount: 3500, status: "pending", remark: "" },
];
const getStatusLabel = (status) => {
  const map = { pending: "待审核", approved: "已审核", rejected: "已驳回" };
  return map[status] || status;
};
const getStatusType = (status) => {
  const map = { pending: "warning", approved: "success", rejected: "danger" };
  return map[status] || "";
const onSearch = () => {
  pagination.currentPage = 1;
  getTableData();
};
const getTableData = () => {
  let result = [...mockData];
  if (filters.outCode) {
    result = result.filter(item => item.outCode.includes(filters.outCode));
  }
  if (filters.customerId) {
    result = result.filter(item => item.customerId === filters.customerId);
  }
  if (filters.dateRange && filters.dateRange.length === 2) {
    result = result.filter(item => item.outDate >= filters.dateRange[0] && item.outDate <= filters.dateRange[1]);
  }
  pagination.total = result.length;
  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
  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 = [];
    })
    .finally(() => {
      tableLoading.value = false;
    });
};
const resetFilters = () => {
  filters.outCode = "";
  filters.customerId = "";
  filters.outboundBatches = "";
  filters.customerName = "";
  filters.dateRange = [];
  pagination.currentPage = 1;
  getTableData();
};
const changePage = ({ current, size }) => {
  pagination.currentPage = current;
  pagination.pageSize = size;
const changePage = ({ page, limit }) => {
  pagination.currentPage = page;
  pagination.pageSize = limit;
  getTableData();
};
const add = () => {
  isEdit.value = false;
  dialogTitle.value = "新增出库";
  Object.assign(form, {
    outCode: "CK" + Date.now(),
    customerId: "",
    outDate: "",
    amount: 0,
    remark: "",
  });
  dialogVisible.value = true;
};
const edit = (row) => {
  isEdit.value = true;
  currentId.value = row.id;
  dialogTitle.value = "编辑出库";
  Object.assign(form, row);
  dialogVisible.value = true;
};
const view = (row) => {
  ElMessage.info(`查看出库单: ${row.outCode}`);
};
const submitForm = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      const customer = customerList.find(item => item.id === form.customerId);
      if (isEdit.value) {
        const index = mockData.findIndex(item => item.id === currentId.value);
        if (index !== -1) {
          mockData[index] = { ...mockData[index], ...form, customerName: customer?.name };
        }
        ElMessage.success("编辑成功");
      } else {
        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
        mockData.push({ id: newId, ...form, customerName: customer?.name, status: "pending" });
        ElMessage.success("新增成功");
      }
      dialogVisible.value = false;
      getTableData();
    }
  });
};
const handleDelete = (row) => {
  ElMessageBox.confirm("确认删除该出库单吗?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData.splice(index, 1);
    }
    ElMessage.success("删除成功");
    getTableData();
  });
};
const handleOut = () => {
  ElMessage.success("导出成功");
  proxy.download(
    "/accountSales/exportAccountSalesOutbound",
    buildFilterParams(),
    `销售出库_${new Date().getTime()}.xlsx`
  );
};
onMounted(() => {
src/views/financialManagement/receivable/salesReturn.vue
@@ -1,19 +1,27 @@
<template>
  <!-- é”€å”®é€€è´§ -->
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="退货单号:">
        <el-input v-model="filters.returnCode" placeholder="请输入退货单号" clearable style="width: 200px;" />
        <el-input v-model="filters.returnNo" placeholder="请输入退货单号" clearable style="width: 200px;" />
      </el-form-item>
      <el-form-item label="客户:">
        <el-select v-model="filters.customerId" placeholder="请选择客户" clearable style="width: 200px;">
          <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
      <el-form-item label="客户名称:">
        <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="getTableData">搜索</el-button>
        <el-button type="primary" @click="onSearch">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </el-form-item>
    </el-form>
@@ -28,90 +36,32 @@
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :tableLoading="tableLoading"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @pagination="changePage"
      >
        <template #status="{ row }">
          <el-tag :type="getStatusType(row.status)">{{ getStatusLabel(row.status) }}</el-tag>
        </template>
        <template #operation="{ row }">
          <el-button type="primary" link @click="view(row)">查看</el-button>
          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'pending'">编辑</el-button>
          <el-button type="success" link @click="handleAudit(row)" v-if="row.status === 'pending'">审核</el-button>
        </template>
      </PIMTable>
      />
    </div>
    <FormDialog :title="dialogTitle" v-model="dialogVisible" width="800px" @confirm="submitForm" @cancel="dialogVisible = false">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="退货单号" prop="returnCode">
              <el-input v-model="form.returnCode" placeholder="请输入退货单号" :disabled="isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="关联出库单" prop="outCode">
              <el-select v-model="form.outCode" placeholder="请选择出库单" style="width: 100%;" :disabled="isEdit">
                <el-option v-for="item in outList" :key="item.outCode" :label="item.outCode" :value="item.outCode" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="客户" prop="customerId">
              <el-select v-model="form.customerId" placeholder="请选择客户" style="width: 100%;" :disabled="isEdit">
                <el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="退货日期" prop="returnDate">
              <el-date-picker v-model="form.returnDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" style="width: 100%;" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="退货金额" prop="amount">
              <el-input-number v-model="form.amount" :min="0" :precision="2" style="width: 100%;" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="退货原因" prop="reason">
              <el-input v-model="form.reason" placeholder="请输入退货原因" />
            </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>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitForm">确定</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
      </template>
    </FormDialog>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { ref, reactive, onMounted, getCurrentInstance } from "vue";
import { ElMessage } from "element-plus";
import { listPageAccountSalesReturn } from "@/api/financialManagement/accountSales";
defineOptions({
  name: "销售退货",
});
const { proxy } = getCurrentInstance();
const filters = reactive({
  returnCode: "",
  customerId: "",
  returnNo: "",
  customerName: "",
  dateRange: [],
});
@@ -122,173 +72,89 @@
});
const columns = [
  { label: "退货单号", prop: "returnCode", width: "150" },
  { label: "客户名称", prop: "customerName", width: "180" },
  { label: "关联出库单", prop: "outCode", width: "150" },
  { label: "退货日期", prop: "returnDate", width: "120" },
  { label: "退货金额", prop: "amount", width: "120" },
  { label: "退货原因", prop: "reason", width: "150", showOverflowTooltip: true },
  { label: "状态", prop: "status", slot: "status" },
  { label: "操作", prop: "operation", slot: "operation", width: "200", fixed: "right" },
  { label: "退货单号", prop: "returnNo", minWidth: "150" },
  { label: "客户名称", prop: "customerName", minWidth: "180" },
  { label: "关联发货单号", prop: "shippingNo", minWidth: "150" },
  { label: "退货日期", prop: "makeTime", minWidth: "170" },
  {
    label: "退款总额",
    prop: "refundAmount",
    minWidth: "120",
    align: "right",
    formatData: (val) =>
      val === null || val === undefined || val === ""
        ? ""
        : Number(val).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
  },
  { label: "退货原因", prop: "returnReason", minWidth: "150", showOverflowTooltip: true },
  { label: "销售订单号", prop: "salesContractNo", minWidth: "150" },
];
const dataList = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const isEdit = ref(false);
const currentId = ref(null);
const tableLoading = ref(false);
const customerList = [
  { id: 1, name: "北京科技有限公司" },
  { id: 2, name: "上海贸易公司" },
  { id: 3, name: "广州实业有限公司" },
  { id: 4, name: "深圳电子公司" },
];
function buildFilterParams() {
  const params = {
    returnNo: filters.returnNo || undefined,
    customerName: filters.customerName || undefined,
  };
  if (filters.dateRange && filters.dateRange.length === 2) {
    params.startDate = filters.dateRange[0];
    params.endDate = filters.dateRange[1];
  }
  return params;
}
const outList = [
  { outCode: "CK2024001", customerId: 1 },
  { outCode: "CK2024002", customerId: 2 },
  { outCode: "CK2024003", customerId: 3 },
];
const form = reactive({
  returnCode: "",
  outCode: "",
  customerId: "",
  returnDate: "",
  amount: 0,
  reason: "",
  remark: "",
});
const rules = {
  returnCode: [{ required: true, message: "请输入退货单号", trigger: "blur" }],
  outCode: [{ required: true, message: "请选择关联出库单", trigger: "change" }],
  customerId: [{ required: true, message: "请选择客户", trigger: "change" }],
  returnDate: [{ required: true, message: "请选择退货日期", trigger: "change" }],
  amount: [{ required: true, message: "请输入退货金额", trigger: "blur" }],
};
const mockData = [
  { id: 1, returnCode: "TH2024001", outCode: "CK2024001", customerId: 1, customerName: "北京科技有限公司", returnDate: "2024-01-20", amount: 1000, reason: "质量问题", status: "approved", remark: "" },
  { id: 2, returnCode: "TH2024002", outCode: "CK2024002", customerId: 2, customerName: "上海贸易公司", returnDate: "2024-01-22", amount: 500, reason: "规格不符", status: "pending", remark: "" },
];
const getStatusLabel = (status) => {
  const map = { pending: "待审核", approved: "已审核", rejected: "已驳回" };
  return map[status] || status;
};
const getStatusType = (status) => {
  const map = { pending: "warning", approved: "success", rejected: "danger" };
  return map[status] || "";
const onSearch = () => {
  pagination.currentPage = 1;
  getTableData();
};
const getTableData = () => {
  let result = [...mockData];
  if (filters.returnCode) {
    result = result.filter(item => item.returnCode.includes(filters.returnCode));
  }
  if (filters.customerId) {
    result = result.filter(item => item.customerId === filters.customerId);
  }
  if (filters.dateRange && filters.dateRange.length === 2) {
    result = result.filter(item => item.returnDate >= filters.dateRange[0] && item.returnDate <= filters.dateRange[1]);
  }
  pagination.total = result.length;
  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
  tableLoading.value = true;
  listPageAccountSalesReturn({
    ...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 = [];
    })
    .finally(() => {
      tableLoading.value = false;
    });
};
const resetFilters = () => {
  filters.returnCode = "";
  filters.customerId = "";
  filters.returnNo = "";
  filters.customerName = "";
  filters.dateRange = [];
  pagination.currentPage = 1;
  getTableData();
};
const changePage = ({ current, size }) => {
  pagination.currentPage = current;
  pagination.pageSize = size;
const changePage = ({ page, limit }) => {
  pagination.currentPage = page;
  pagination.pageSize = limit;
  getTableData();
};
const add = () => {
  isEdit.value = false;
  dialogTitle.value = "新增退货";
  Object.assign(form, {
    returnCode: "TH" + Date.now(),
    outCode: "",
    customerId: "",
    returnDate: "",
    amount: 0,
    reason: "",
    remark: "",
  });
  dialogVisible.value = true;
};
const edit = (row) => {
  isEdit.value = true;
  currentId.value = row.id;
  dialogTitle.value = "编辑退货";
  Object.assign(form, row);
  dialogVisible.value = true;
};
const view = (row) => {
  ElMessage.info(`查看退货单: ${row.returnCode}`);
};
const handleAudit = (row) => {
  ElMessageBox.confirm("确认审核通过该退货单吗?", "提示", {
    confirmButtonText: "通过",
    cancelButtonText: "驳回",
    distinguishCancelAndClose: true,
    type: "warning",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData[index].status = "approved";
    }
    ElMessage.success("审核通过");
    getTableData();
  }).catch((action) => {
    if (action === "cancel") {
      const index = mockData.findIndex(item => item.id === row.id);
      if (index !== -1) {
        mockData[index].status = "rejected";
      }
      ElMessage.warning("已驳回");
      getTableData();
    }
  });
};
const submitForm = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      const customer = customerList.find(item => item.id === form.customerId);
      if (isEdit.value) {
        const index = mockData.findIndex(item => item.id === currentId.value);
        if (index !== -1) {
          mockData[index] = { ...mockData[index], ...form, customerName: customer?.name };
        }
        ElMessage.success("编辑成功");
      } else {
        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
        mockData.push({ id: newId, ...form, customerName: customer?.name, status: "pending" });
        ElMessage.success("新增成功");
      }
      dialogVisible.value = false;
      getTableData();
    }
  });
};
const handleOut = () => {
  ElMessage.success("导出成功");
  proxy.download(
    "/accountSales/exportAccountSalesReturn",
    buildFilterParams(),
    `销售退货_${new Date().getTime()}.xlsx`
  );
};
onMounted(() => {
src/views/financialManagement/voucher/detailLedger.vue
@@ -1,165 +1,126 @@
<template>
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="会计科目:">
        <el-cascader v-model="filters.subject" :options="subjectOptions" :props="{ label: 'name', value: 'code' }" placeholder="请选择会计科目" clearable style="width: 250px;" filterable />
      </el-form-item>
      <el-form-item label="辅助核算:">
        <el-select v-model="filters.auxiliary" placeholder="请选择辅助核算" clearable style="width: 180px;">
          <el-option label="客户" value="customer" />
          <el-option label="供应商" value="supplier" />
          <el-option label="部门" value="department" />
          <el-option label="员工" value="employee" />
          <el-option label="项目" value="project" />
        </el-select>
      </el-form-item>
      <el-form-item label="核算对象:">
        <el-select v-model="filters.auxiliaryItem" placeholder="请选择核算对象" clearable style="width: 200px;" :disabled="!filters.auxiliary">
          <el-option v-for="item in auxiliaryItems" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="期间:">
        <el-date-picker v-model="filters.startMonth" type="month" placeholder="开始月份" value-format="YYYY-MM" style="width: 140px;" />
        <span style="margin: 0 10px;">至</span>
        <el-date-picker v-model="filters.endMonth" type="month" placeholder="结束月份" value-format="YYYY-MM" style="width: 140px;" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getTableData">查询</el-button>
        <el-button @click="resetFilters">重置</el-button>
        <el-button @click="handlePrint" icon="Printer">打印</el-button>
        <el-button @click="handleOut" icon="Download">导出</el-button>
      </el-form-item>
    </el-form>
  <div class="app-container ledger-page">
    <div class="ledger-layout">
      <aside class="subject-panel">
        <el-input v-model="subjectKeyword" placeholder="请输入科目名称/编号" clearable prefix-icon="Search" />
        <el-scrollbar class="subject-tree-scroll">
          <el-tree
            ref="subjectTreeRef"
            :data="subjectOptions"
            node-key="code"
            :props="{ label: 'name', children: 'children' }"
            highlight-current
            default-expand-all
            :expand-on-click-node="false"
            :filter-node-method="filterSubjectNode"
            @node-click="handleSubjectClick"
          >
            <template #default="{ data }">
              <span class="subject-node">{{ data.code }} {{ data.name }}</span>
            </template>
          </el-tree>
        </el-scrollbar>
      </aside>
    <div class="ledger-header" v-if="currentSubject">
      <h2>科目明细账</h2>
      <p>科目: {{ currentSubject.code }} {{ currentSubject.name }}</p>
      <p v-if="filters.auxiliary && filters.auxiliaryItem">辅助核算: {{ getAuxiliaryLabel() }}</p>
      <p>期间: {{ filters.startMonth }} è‡³ {{ filters.endMonth }}</p>
      <section class="ledger-content">
        <el-form :model="filters" :inline="true" class="filter-form">
          <el-form-item label="期间:">
            <el-date-picker v-model="filters.startMonth" type="month" placeholder="开始月份" value-format="YYYY-MM" style="width: 140px;" />
            <span style="margin: 0 10px;">至</span>
            <el-date-picker v-model="filters.endMonth" type="month" placeholder="结束月份" value-format="YYYY-MM" style="width: 140px;" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="getTableData">查询</el-button>
            <el-button @click="resetFilters">重置</el-button>
<!--            <el-button @click="handlePrint" icon="Printer">打印</el-button>-->
            <el-button @click="handleOut" icon="Download">导出</el-button>
          </el-form-item>
        </el-form>
        <div class="table_list">
          <el-table :data="dataList" border style="width: 100%">
            <el-table-column prop="date" label="日期" width="120" />
            <el-table-column prop="voucherNo" label="凭证字号" width="120" />
            <el-table-column prop="summary" label="摘要" min-width="200" show-overflow-tooltip />
            <el-table-column prop="debit" label="借方" width="150">
              <template #default="{ row }">
                <span v-if="row.debit > 0" class="text-danger">Â¥{{ formatMoney(row.debit) }}</span>
                <span v-else>-</span>
              </template>
            </el-table-column>
            <el-table-column prop="credit" label="贷方" width="150">
              <template #default="{ row }">
                <span v-if="row.credit > 0" class="text-success">Â¥{{ formatMoney(row.credit) }}</span>
                <span v-else>-</span>
              </template>
            </el-table-column>
            <el-table-column label="方向" width="80">
              <template #default="{ row }">
                <el-tag :type="row.direction === '借' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column label="余额" width="150">
              <template #default="{ row }">
                <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">Â¥{{ formatMoney(Math.abs(row.balance)) }}</span>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <el-empty v-if="!currentSubject" description="请选择会计科目查询" style="margin-top: 50px;" />
      </section>
    </div>
    <div class="table_list">
      <el-table :data="dataList" border style="width: 100%" show-summary :summary-method="getSummaries">
        <el-table-column prop="date" label="日期" width="120" />
        <el-table-column prop="voucherNo" label="凭证字号" width="120" />
        <el-table-column prop="summary" label="摘要" min-width="200" show-overflow-tooltip />
        <el-table-column label="借方" width="150">
          <template #default="{ row }">
            <span v-if="row.debit > 0" class="text-danger">Â¥{{ formatMoney(row.debit) }}</span>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="贷方" width="150">
          <template #default="{ row }">
            <span v-if="row.credit > 0" class="text-success">Â¥{{ formatMoney(row.credit) }}</span>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="方向" width="80">
          <template #default="{ row }">
            <el-tag :type="row.direction === '借' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="余额" width="150">
          <template #default="{ row }">
            <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">Â¥{{ formatMoney(Math.abs(row.balance)) }}</span>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <el-empty v-if="!currentSubject" description="请选择会计科目查询" style="margin-top: 50px;" />
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, computed, watch } from "vue";
import { ref, reactive, onMounted, computed, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { listAccountSubject } from "@/api/financialManagement/accountSubject";
import { getDetailLedger } from "@/api/financialManagement/ledger";
defineOptions({
  name: "科目明细账",
});
const filters = reactive({
  subject: [],
  auxiliary: "",
  auxiliaryItem: "",
  startMonth: "2024-01",
  endMonth: "2024-03",
  subject: "",
  startMonth: "",
  endMonth: "",
});
const dataList = ref([]);
const subjectOptions = ref([]);
const subjectKeyword = ref("");
const subjectTreeRef = ref();
const subjectOptions = [
  {
    code: "1122",
    name: "应收账款",
    children: [
      { code: "112201", name: "北京科技有限公司" },
      { code: "112202", name: "上海贸易公司" },
      { code: "112203", name: "广州实业有限公司" },
    ],
  },
  {
    code: "2202",
    name: "应付账款",
    children: [
      { code: "220201", name: "北京原材料供应商" },
      { code: "220202", name: "上海电子元器件公司" },
      { code: "220203", name: "广州包装材料厂" },
    ],
  },
  {
    code: "6602",
    name: "管理费用",
    children: [
      { code: "660201", name: "办公费" },
      { code: "660202", name: "差旅费" },
      { code: "660203", name: "业务招待费" },
    ],
  },
const getPreviousMonth = () => {
  const date = new Date();
  date.setDate(1);
  date.setMonth(date.getMonth() - 1);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  return `${year}-${month}`;
};
const defaultMonth = getPreviousMonth();
filters.startMonth = defaultMonth;
filters.endMonth = defaultMonth;
const fallbackSubjects = [
  { code: "1122", name: "应收账款" },
  { code: "2202", name: "应付账款" },
  { code: "6602", name: "管理费用" },
];
const auxiliaryItems = computed(() => {
  const map = {
    customer: [
      { value: "1", label: "北京科技有限公司" },
      { value: "2", label: "上海贸易公司" },
      { value: "3", label: "广州实业有限公司" },
    ],
    supplier: [
      { value: "1", label: "北京原材料供应商" },
      { value: "2", label: "上海电子元器件公司" },
      { value: "3", label: "广州包装材料厂" },
    ],
    department: [
      { value: "1", label: "财务部" },
      { value: "2", label: "销售部" },
      { value: "3", label: "采购部" },
    ],
    employee: [
      { value: "1", label: "张三" },
      { value: "2", label: "李四" },
      { value: "3", label: "王五" },
    ],
    project: [
      { value: "1", label: "项目A" },
      { value: "2", label: "项目B" },
      { value: "3", label: "项目C" },
    ],
  };
  return map[filters.auxiliary] || [];
});
watch(() => filters.auxiliary, () => {
  filters.auxiliaryItem = "";
});
const currentSubject = computed(() => {
  if (!filters.subject || filters.subject.length === 0) return null;
  const code = filters.subject[filters.subject.length - 1];
  return findSubject(subjectOptions, code);
});
const toTree = (nodes = []) =>
  nodes
    .filter(item => item.subjectCode && item.subjectName)
    .map(item => ({
      code: item.subjectCode,
      name: item.subjectName,
      children: toTree(item.children || []),
    }));
const findSubject = (options, code) => {
  for (const item of options) {
@@ -172,9 +133,68 @@
  return null;
};
const getAuxiliaryLabel = () => {
  const item = auxiliaryItems.value.find(i => i.value === filters.auxiliaryItem);
  return item ? item.label : "";
const currentSubject = computed(() => {
  if (!filters.subject) return null;
  return findSubject(subjectOptions.value, filters.subject);
});
const getFirstSubjectCode = (nodes = []) => {
  for (const item of nodes) {
    if (item.code) return item.code;
    if (item.children && item.children.length > 0) {
      const childCode = getFirstSubjectCode(item.children);
      if (childCode) return childCode;
    }
  }
  return "";
};
const setDefaultSubjectSelection = async () => {
  const firstCode = getFirstSubjectCode(subjectOptions.value);
  if (!firstCode) {
    filters.subject = "";
    subjectTreeRef.value?.setCurrentKey(null);
    return;
  }
  filters.subject = firstCode;
  await nextTick();
  subjectTreeRef.value?.setCurrentKey(firstCode);
};
const filterSubjectNode = (value, data) => {
  const keyword = value?.trim();
  if (!keyword) return true;
  return `${data.code}${data.name}`.includes(keyword);
};
watch(subjectKeyword, (value) => {
  subjectTreeRef.value?.filter(value || "");
});
const handleSubjectClick = async (data) => {
  filters.subject = data.code;
  await getTableData();
};
const loadSubjectOptions = async () => {
  let options = [];
  try {
    const { data } = await listAccountSubject({
      current: 1,
      size: 1000,
    });
    options = toTree(data?.records || []);
  } catch (error) {
    // å…¨å±€æ‹¦æˆªå™¨å·²æç¤ºï¼Œä¸‹é¢èµ°å…œåº•ç§‘ç›®
  }
  if (options.length === 0) {
    options = fallbackSubjects.map(item => ({ ...item, children: [] }));
  }
  subjectOptions.value = options;
  await setDefaultSubjectSelection();
  if (filters.subject) {
    await getTableData();
  }
};
const formatMoney = (value) => {
@@ -182,63 +202,34 @@
  return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
const mockData = [
  { date: "2024-01-01", voucherNo: "-", summary: "期初余额", debit: 0, credit: 0, direction: "借", balance: 10000 },
  { date: "2024-01-05", voucherNo: "è®°-0001", summary: "销售出库", debit: 5000, credit: 0, direction: "借", balance: 15000 },
  { date: "2024-01-10", voucherNo: "è®°-0002", summary: "收到货款", debit: 0, credit: 3000, direction: "借", balance: 12000 },
  { date: "2024-01-15", voucherNo: "è®°-0003", summary: "销售出库", debit: 8000, credit: 0, direction: "借", balance: 20000 },
  { date: "2024-01-20", voucherNo: "è®°-0004", summary: "销售退货", debit: 0, credit: 2000, direction: "借", balance: 18000 },
  { date: "2024-01-25", voucherNo: "è®°-0005", summary: "收到货款", debit: 0, credit: 5000, direction: "借", balance: 13000 },
  { date: "2024-01-31", voucherNo: "-", summary: "本月合计", debit: 13000, credit: 10000, direction: "借", balance: 13000 },
  { date: "2024-02-01", voucherNo: "-", summary: "期初余额", debit: 0, credit: 0, direction: "借", balance: 13000 },
  { date: "2024-02-10", voucherNo: "è®°-0006", summary: "销售出库", debit: 6000, credit: 0, direction: "借", balance: 19000 },
  { date: "2024-02-15", voucherNo: "è®°-0007", summary: "收到货款", debit: 0, credit: 4000, direction: "借", balance: 15000 },
  { date: "2024-02-28", voucherNo: "-", summary: "本月合计", debit: 6000, credit: 4000, direction: "借", balance: 15000 },
  { date: "2024-03-01", voucherNo: "-", summary: "期初余额", debit: 0, credit: 0, direction: "借", balance: 15000 },
  { date: "2024-03-05", voucherNo: "è®°-0008", summary: "销售出库", debit: 7000, credit: 0, direction: "借", balance: 22000 },
  { date: "2024-03-10", voucherNo: "è®°-0009", summary: "收到货款", debit: 0, credit: 6000, direction: "借", balance: 16000 },
  { date: "2024-03-31", voucherNo: "-", summary: "本月合计", debit: 7000, credit: 6000, direction: "借", balance: 16000 },
  { date: "2024-03-31", voucherNo: "-", summary: "本年累计", debit: 26000, credit: 20000, direction: "借", balance: 16000 },
];
const getTableData = () => {
// è”调约定:明细账按科目与期间过滤
const getTableData = async () => {
  if (!currentSubject.value) {
    dataList.value = [];
    return;
  }
  dataList.value = [...mockData];
  try {
    const { data } = await getDetailLedger({
      subjectCode: currentSubject.value.code,
      startMonth: filters.startMonth,
      endMonth: filters.endMonth,
    });
    dataList.value = Array.isArray(data) ? data : data?.records || [];
  } catch (error) {
    // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
  }
};
const resetFilters = () => {
  filters.subject = [];
  filters.auxiliary = "";
  filters.auxiliaryItem = "";
  filters.startMonth = "2024-01";
  filters.endMonth = "2024-03";
const resetFilters = async () => {
  filters.startMonth = defaultMonth;
  filters.endMonth = defaultMonth;
  dataList.value = [];
};
const getSummaries = (param) => {
  const { columns, data } = param;
  const sums = [];
  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = "合计";
      return;
    }
    if (column.property === "debit") {
      const values = data.map(item => Number(item.debit));
      const sum = values.reduce((prev, curr) => prev + curr, 0);
      sums[index] = "Â¥" + formatMoney(sum);
    } else if (column.property === "credit") {
      const values = data.map(item => Number(item.credit));
      const sum = values.reduce((prev, curr) => prev + curr, 0);
      sums[index] = "Â¥" + formatMoney(sum);
    } else {
      sums[index] = "";
    }
  });
  return sums;
  subjectKeyword.value = "";
  subjectTreeRef.value?.filter("");
  await setDefaultSubjectSelection();
  if (filters.subject) {
    await getTableData();
  }
};
const handlePrint = () => {
@@ -249,22 +240,43 @@
  ElMessage.success("导出成功");
};
onMounted(() => {
  // é»˜è®¤ä¸åŠ è½½æ•°æ®ï¼Œéœ€è¦é€‰æ‹©ç§‘ç›®
onMounted(async () => {
  await loadSubjectOptions();
});
</script>
<style lang="scss" scoped>
.ledger-header {
  text-align: center;
  margin-bottom: 20px;
  h2 {
    margin: 0 0 10px 0;
  }
  p {
    color: #606266;
    margin: 5px 0;
  }
.ledger-layout {
  display: flex;
  gap: 16px;
}
.subject-panel {
  width: 260px;
  flex-shrink: 0;
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  background-color: #fff;
}
.subject-tree-scroll {
  height: 600px;
  margin-top: 12px;
}
.subject-node {
  display: inline-flex;
  align-items: center;
}
.ledger-content {
  flex: 1;
  min-width: 0;
}
.filter-form {
  margin-bottom: 12px;
}
.text-primary {
@@ -286,4 +298,12 @@
  color: #e6a23c;
  font-weight: bold;
}
.subject-panel :deep(.el-tree-node__content) {
  height: 34px;
}
.subject-panel :deep(.el-tree-node.is-current > .el-tree-node__content) {
  background-color: #f0f7ff;
}
</style>
src/views/financialManagement/voucher/generalLedger.vue
@@ -1,114 +1,128 @@
<template>
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="会计科目:">
        <el-cascader v-model="filters.subject" :options="subjectOptions" :props="{ label: 'name', value: 'code' }" placeholder="请选择会计科目" clearable style="width: 250px;" filterable />
      </el-form-item>
      <el-form-item label="期间:">
        <el-date-picker v-model="filters.startMonth" type="month" placeholder="开始月份" value-format="YYYY-MM" style="width: 140px;" />
        <span style="margin: 0 10px;">至</span>
        <el-date-picker v-model="filters.endMonth" type="month" placeholder="结束月份" value-format="YYYY-MM" style="width: 140px;" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getTableData">查询</el-button>
        <el-button @click="resetFilters">重置</el-button>
        <el-button @click="handlePrint" icon="Printer">打印</el-button>
        <el-button @click="handleOut" icon="Download">导出</el-button>
      </el-form-item>
    </el-form>
  <div class="app-container ledger-page">
    <div class="ledger-layout">
      <aside class="subject-panel">
        <el-input v-model="subjectKeyword" placeholder="请输入科目名称/编号" clearable prefix-icon="Search" />
        <el-scrollbar class="subject-tree-scroll">
          <el-tree
            ref="subjectTreeRef"
            :data="subjectOptions"
            node-key="code"
            :props="{ label: 'name', children: 'children' }"
            highlight-current
            default-expand-all
            :expand-on-click-node="false"
            :filter-node-method="filterSubjectNode"
            @node-click="handleSubjectClick"
          >
            <template #default="{ data }">
              <span class="subject-node">{{ data.code }} {{ data.name }}</span>
            </template>
          </el-tree>
        </el-scrollbar>
      </aside>
    <div class="ledger-header" v-if="currentSubject">
      <h2>科目总账</h2>
      <p>科目: {{ currentSubject.code }} {{ currentSubject.name }}</p>
      <p>期间: {{ filters.startMonth }} è‡³ {{ filters.endMonth }}</p>
      <section class="ledger-content">
        <el-form :model="filters" :inline="true" class="filter-form">
          <el-form-item label="期间:">
            <el-date-picker v-model="filters.startMonth" type="month" placeholder="开始月份" value-format="YYYY-MM" style="width: 140px;" />
            <span style="margin: 0 10px;">至</span>
            <el-date-picker v-model="filters.endMonth" type="month" placeholder="结束月份" value-format="YYYY-MM" style="width: 140px;" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="getTableData">查询</el-button>
            <el-button @click="resetFilters">重置</el-button>
<!--            <el-button @click="handlePrint" icon="Printer">打印</el-button>-->
            <!-- <el-button @click="handleOut" icon="Download">导出</el-button> -->
          </el-form-item>
        </el-form>
        <div class="table_list">
          <el-table :data="dataList" border style="width: 100%">
            <el-table-column prop="date" label="日期"/>
            <!-- <el-table-column prop="voucherNo" label="凭证字号" width="120" /> -->
            <!-- <el-table-column prop="summary" label="摘要" min-width="200" show-overflow-tooltip /> -->
            <el-table-column prop="debit" label="借方">
              <template #default="{ row }">
                <span v-if="row.debit > 0" class="text-danger">Â¥{{ formatMoney(row.debit) }}</span>
                <span v-else>-</span>
              </template>
            </el-table-column>
            <el-table-column prop="credit" label="贷方">
              <template #default="{ row }">
                <span v-if="row.credit > 0" class="text-success">Â¥{{ formatMoney(row.credit) }}</span>
                <span v-else>-</span>
              </template>
            </el-table-column>
            <el-table-column label="方向">
              <template #default="{ row }">
                <el-tag :type="row.direction === '借' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column label="余额">
              <template #default="{ row }">
                <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">Â¥{{ formatMoney(Math.abs(row.balance)) }}</span>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <el-empty v-if="!currentSubject" description="请选择会计科目查询" style="margin-top: 50px;" />
      </section>
    </div>
    <div class="table_list">
      <el-table :data="dataList" border style="width: 100%" show-summary :summary-method="getSummaries">
        <el-table-column prop="date" label="日期" width="120" />
        <el-table-column prop="voucherNo" label="凭证字号" width="120" />
        <el-table-column prop="summary" label="摘要" min-width="200" show-overflow-tooltip />
        <el-table-column label="借方" width="150">
          <template #default="{ row }">
            <span v-if="row.debit > 0" class="text-danger">Â¥{{ formatMoney(row.debit) }}</span>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="贷方" width="150">
          <template #default="{ row }">
            <span v-if="row.credit > 0" class="text-success">Â¥{{ formatMoney(row.credit) }}</span>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="方向" width="80">
          <template #default="{ row }">
            <el-tag :type="row.direction === '借' ? 'success' : 'danger'" size="small">{{ row.direction }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="余额" width="150">
          <template #default="{ row }">
            <span :class="row.balance >= 0 ? 'text-primary' : 'text-warning'">Â¥{{ formatMoney(Math.abs(row.balance)) }}</span>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <el-empty v-if="!currentSubject" description="请选择会计科目查询" style="margin-top: 50px;" />
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from "vue";
import { ref, reactive, onMounted, computed, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { listAccountSubject } from "@/api/financialManagement/accountSubject";
import { getGeneralLedger } from "@/api/financialManagement/ledger";
defineOptions({
  name: "科目总账",
});
const filters = reactive({
  subject: [],
  startMonth: "2024-01",
  endMonth: "2024-03",
  subject: "",
  startMonth: "",
  endMonth: "",
});
const dataList = ref([]);
const subjectOptions = ref([]);
const subjectKeyword = ref("");
const subjectTreeRef = ref();
const subjectOptions = [
  {
    code: "1001",
    name: "库存现金",
    children: [],
  },
  {
    code: "1002",
    name: "银行存款",
    children: [
      { code: "100201", name: "工商银行" },
      { code: "100202", name: "建设银行" },
    ],
  },
  {
    code: "1122",
    name: "应收账款",
    children: [],
  },
  {
    code: "2202",
    name: "应付账款",
    children: [],
  },
  {
    code: "6001",
    name: "主营业务收入",
    children: [],
  },
const getPreviousMonth = () => {
  const date = new Date();
  date.setDate(1);
  date.setMonth(date.getMonth() - 1);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  return `${year}-${month}`;
};
const defaultMonth = getPreviousMonth();
filters.startMonth = defaultMonth;
filters.endMonth = defaultMonth;
const fallbackSubjects = [
  { code: "1001", name: "库存现金" },
  { code: "1002", name: "银行存款" },
  { code: "1122", name: "应收账款" },
  { code: "2202", name: "应付账款" },
  { code: "6001", name: "主营业务收入" },
];
const currentSubject = computed(() => {
  if (!filters.subject || filters.subject.length === 0) return null;
  const code = filters.subject[filters.subject.length - 1];
  return findSubject(subjectOptions, code);
});
const toTree = (nodes = []) =>
  nodes
    .filter(item => item.subjectCode && item.subjectName)
    .map(item => ({
      code: item.subjectCode,
      name: item.subjectName,
      children: toTree(item.children || []),
    }));
const findSubject = (options, code) => {
  for (const item of options) {
@@ -121,65 +135,104 @@
  return null;
};
const currentSubject = computed(() => {
  if (!filters.subject) return null;
  return findSubject(subjectOptions.value, filters.subject);
});
const getFirstSubjectCode = (nodes = []) => {
  for (const item of nodes) {
    if (item.code) return item.code;
    if (item.children && item.children.length > 0) {
      const childCode = getFirstSubjectCode(item.children);
      if (childCode) return childCode;
    }
  }
  return "";
};
const setDefaultSubjectSelection = async () => {
  const firstCode = getFirstSubjectCode(subjectOptions.value);
  if (!firstCode) {
    filters.subject = "";
    subjectTreeRef.value?.setCurrentKey(null);
    return;
  }
  filters.subject = firstCode;
  await nextTick();
  subjectTreeRef.value?.setCurrentKey(firstCode);
};
const filterSubjectNode = (value, data) => {
  const keyword = value?.trim();
  if (!keyword) return true;
  return `${data.code}${data.name}`.includes(keyword);
};
watch(subjectKeyword, (value) => {
  subjectTreeRef.value?.filter(value || "");
});
const handleSubjectClick = async (data) => {
  filters.subject = data.code;
  await getTableData();
};
const loadSubjectOptions = async () => {
  let options = [];
  try {
    const { data } = await listAccountSubject({
      current: 1,
      size: 1000,
      status: 0,
    });
    options = toTree(data?.records || []);
  } catch (error) {
    // å…¨å±€æ‹¦æˆªå™¨å·²æç¤ºï¼Œä¸‹é¢èµ°å…œåº•ç§‘ç›®
  }
  if (options.length === 0) {
    options = fallbackSubjects.map(item => ({ ...item, children: [] }));
  }
  subjectOptions.value = options;
  await setDefaultSubjectSelection();
  if (filters.subject) {
    await getTableData();
  }
};
const formatMoney = (value) => {
  if (value === undefined || value === null) return "0.00";
  return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
const mockData = [
  { date: "2024-01-01", voucherNo: "-", summary: "期初余额", debit: 0, credit: 0, direction: "借", balance: 100000 },
  { date: "2024-01-05", voucherNo: "è®°-0001", summary: "销售收入", debit: 5650, credit: 0, direction: "借", balance: 105650 },
  { date: "2024-01-10", voucherNo: "è®°-0002", summary: "采购支出", debit: 0, credit: 8000, direction: "借", balance: 97650 },
  { date: "2024-01-15", voucherNo: "è®°-0003", summary: "收到货款", debit: 10000, credit: 0, direction: "借", balance: 107650 },
  { date: "2024-01-20", voucherNo: "è®°-0004", summary: "支付费用", debit: 0, credit: 5000, direction: "借", balance: 102650 },
  { date: "2024-01-31", voucherNo: "-", summary: "本月合计", debit: 15650, credit: 13000, direction: "借", balance: 102650 },
  { date: "2024-02-01", voucherNo: "-", summary: "期初余额", debit: 0, credit: 0, direction: "借", balance: 102650 },
  { date: "2024-02-10", voucherNo: "è®°-0005", summary: "销售收入", debit: 8000, credit: 0, direction: "借", balance: 110650 },
  { date: "2024-02-15", voucherNo: "è®°-0006", summary: "采购支出", debit: 0, credit: 12000, direction: "借", balance: 98650 },
  { date: "2024-02-28", voucherNo: "-", summary: "本月合计", debit: 8000, credit: 12000, direction: "借", balance: 98650 },
  { date: "2024-03-01", voucherNo: "-", summary: "期初余额", debit: 0, credit: 0, direction: "借", balance: 98650 },
  { date: "2024-03-05", voucherNo: "è®°-0007", summary: "销售收入", debit: 12000, credit: 0, direction: "借", balance: 110650 },
  { date: "2024-03-10", voucherNo: "è®°-0008", summary: "支付工资", debit: 0, credit: 15000, direction: "借", balance: 95650 },
  { date: "2024-03-31", voucherNo: "-", summary: "本月合计", debit: 12000, credit: 15000, direction: "借", balance: 95650 },
  { date: "2024-03-31", voucherNo: "-", summary: "本年累计", debit: 35650, credit: 40000, direction: "借", balance: 95650 },
];
const getTableData = () => {
// è”调约定:总账接口返回行数组(rowType/date/voucherNo/summary/debit/credit/direction/balance)
const getTableData = async () => {
  if (!currentSubject.value) {
    dataList.value = [];
    return;
  }
  dataList.value = [...mockData];
  try {
    const { data } = await getGeneralLedger({
      subjectCode: currentSubject.value.code,
      startMonth: filters.startMonth,
      endMonth: filters.endMonth,
    });
    dataList.value = Array.isArray(data) ? data : data?.records || [];
  } catch (error) {
    // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
  }
};
const resetFilters = () => {
  filters.subject = [];
  filters.startMonth = "2024-01";
  filters.endMonth = "2024-03";
const resetFilters = async () => {
  filters.startMonth = defaultMonth;
  filters.endMonth = defaultMonth;
  dataList.value = [];
};
const getSummaries = (param) => {
  const { columns, data } = param;
  const sums = [];
  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = "合计";
      return;
    }
    if (column.property === "debit") {
      const values = data.map(item => Number(item.debit));
      const sum = values.reduce((prev, curr) => prev + curr, 0);
      sums[index] = "Â¥" + formatMoney(sum);
    } else if (column.property === "credit") {
      const values = data.map(item => Number(item.credit));
      const sum = values.reduce((prev, curr) => prev + curr, 0);
      sums[index] = "Â¥" + formatMoney(sum);
    } else {
      sums[index] = "";
    }
  });
  return sums;
  subjectKeyword.value = "";
  subjectTreeRef.value?.filter("");
  await setDefaultSubjectSelection();
  if (filters.subject) {
    await getTableData();
  }
};
const handlePrint = () => {
@@ -190,22 +243,43 @@
  ElMessage.success("导出成功");
};
onMounted(() => {
  // é»˜è®¤ä¸åŠ è½½æ•°æ®ï¼Œéœ€è¦é€‰æ‹©ç§‘ç›®
onMounted(async () => {
  await loadSubjectOptions();
});
</script>
<style lang="scss" scoped>
.ledger-header {
  text-align: center;
  margin-bottom: 20px;
  h2 {
    margin: 0 0 10px 0;
  }
  p {
    color: #606266;
    margin: 5px 0;
  }
.ledger-layout {
  display: flex;
  gap: 16px;
}
.subject-panel {
  width: 260px;
  flex-shrink: 0;
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  background-color: #fff;
}
.subject-tree-scroll {
  height: 600px;
  margin-top: 12px;
}
.subject-node {
  display: inline-flex;
  align-items: center;
}
.ledger-content {
  flex: 1;
  min-width: 0;
}
.filter-form {
  margin-bottom: 12px;
}
.text-primary {
@@ -227,4 +301,12 @@
  color: #e6a23c;
  font-weight: bold;
}
.subject-panel :deep(.el-tree-node__content) {
  height: 34px;
}
.subject-panel :deep(.el-tree-node.is-current > .el-tree-node__content) {
  background-color: #f0f7ff;
}
</style>
src/views/financialManagement/voucher/index.vue
@@ -9,9 +9,12 @@
      </el-form-item>
      <el-form-item label="制单人:">
        <el-select v-model="filters.creator" placeholder="请选择制单人" clearable style="width: 150px;">
          <el-option label="张三" value="张三" />
          <el-option label="李四" value="李四" />
          <el-option label="王五" value="王五" />
          <el-option
            v-for="item in creatorOptions"
            :key="item"
            :label="item"
            :value="item"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="状态:">
@@ -29,13 +32,13 @@
    <div class="table_list">
      <div class="actions">
        <div>
          <el-statistic title="借方合计" :value="totalDebit" precision="2" prefix="Â¥" />
          <el-statistic title="贷方合计" :value="totalCredit" precision="2" prefix="Â¥" style="margin-left: 30px;" />
          <el-statistic title="借方合计" :value="totalDebit" :precision="2" prefix="Â¥" />
          <el-statistic title="贷方合计" :value="totalCredit" :precision="2" prefix="Â¥" style="margin-left: 30px;" />
        </div>
        <div>
          <el-button type="primary" @click="add" icon="Plus">新增凭证</el-button>
          <el-button @click="handleImport" icon="Upload">导入</el-button>
          <el-button @click="handleOut" icon="Download">导出</el-button>
          <!-- <el-button @click="handleImport" icon="Upload">导入</el-button> -->
          <!-- <el-button @click="handleOut" icon="Download">导出</el-button> -->
        </div>
      </div>
      <PIMTable
@@ -62,9 +65,9 @@
        </template>
        <template #operation="{ row }">
          <el-button type="primary" link @click="view(row)">查看</el-button>
          <el-button type="primary" link @click="edit(row)" v-if="row.status === 'unposted'">编辑</el-button>
          <el-button type="success" link @click="handlePost(row)" v-if="row.status === 'unposted'">过账</el-button>
          <el-button type="danger" link @click="handleCancel(row)" v-if="row.status === 'unposted'">作废</el-button>
          <el-button type="primary" link @click="edit(row)" v-if="canEditVoucher(row.status)">编辑</el-button>
          <el-button type="success" link @click="handlePost(row)" v-if="canEditVoucher(row.status)">过账</el-button>
          <el-button type="danger" link @click="handleCancel(row)" v-if="canEditVoucher(row.status)">作废</el-button>
        </template>
      </PIMTable>
    </div>
@@ -75,25 +78,29 @@
          <h2 class="voucher-title">记账凭证</h2>
          <div class="voucher-period">{{ form.voucherDate ? form.voucherDate.substring(0, 7) + '期' : '' }}</div>
        </div>
        <el-form :model="form" :rules="rules" ref="formRef" label-width="0">
        <el-form :model="form" :rules="rules" :disabled="isViewMode" ref="formRef" label-width="0">
          <div class="voucher-info">
            <div class="voucher-no-section">
              <span class="label">凭证字:</span>
              <el-select v-model="form.voucherPrefix" style="width: 70px;">
              <el-select v-model="form.voucherPrefix" :disabled="isViewMode" style="width: 70px;">
                <el-option label="è®°" value="è®°" />
                <el-option label="现" value="现" />
                <el-option label="银" value="银" />
                <el-option label="转" value="转" />
                <el-option label="收" value="收" />
                <el-option label="付" value="付" />
              </el-select>
              <el-input v-model="form.voucherNum" style="width: 60px;" />
              <el-input v-model="form.voucherNum" :disabled="isViewMode" style="width: 60px;" />
              <span class="label" style="margin-left: 5px;">号</span>
            </div>
            <div class="voucher-date-section">
              <span class="label">日期:</span>
              <el-date-picker v-model="form.voucherDate" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" style="width: 140px;" />
              <el-date-picker v-model="form.voucherDate" :disabled="isViewMode" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" style="width: 140px;" />
            </div>
            <div class="voucher-attachment-section">
              <span class="label">附件:</span>
              <el-input-number v-model="form.attachmentCount" :min="0" :controls="false" style="width: 60px;" />
              <el-input-number v-model="form.attachmentCount" :disabled="isViewMode" :min="0" :controls="false" style="width: 60px;" />
              <span class="label" style="margin-left: 5px;">å¼ </span>
              <el-button type="primary" link style="margin-left: 10px;">上传文件</el-button>
            </div>
          </div>
          <div class="voucher-table">
@@ -134,18 +141,28 @@
              <tbody>
                <tr v-for="(entry, rowIndex) in form.entries" :key="rowIndex" @click="selectRow(rowIndex)" :class="{ 'selected-row': selectedRowIndex === rowIndex }">
                  <td class="col-summary">
                    <el-input v-model="entry.summary" placeholder="请输入摘要" @focus="selectRow(rowIndex)" />
                    <el-input v-model="entry.summary" :disabled="isViewMode" placeholder="请输入摘要" @focus="selectRow(rowIndex)" />
                  </td>
                  <td class="col-subject">
                    <el-select v-model="entry.subjectCode" placeholder="选择科目" filterable @change="(val) => handleSubjectChange(val, rowIndex)" @focus="selectRow(rowIndex)">
                      <el-option v-for="item in subjectList" :key="item.code" :label="item.code + item.name" :value="item.code" />
                    </el-select>
                    <div class="subject-name">{{ entry.subjectName }}</div>
                    <el-tree-select
                      v-model="entry.subjectCode"
                      :data="subjectTreeOptions"
                      :props="subjectTreeSelectProps"
                      :disabled="isViewMode"
                      placeholder="选择科目"
                      filterable
                      check-strictly
                      clearable
                      :render-after-expand="false"
                      @change="(val) => handleSubjectChange(val, rowIndex)"
                      @focus="selectRow(rowIndex)"
                    />
                    <!-- <div class="subject-name">{{ entry.subjectName }}</div> -->
                  </td>
                  <!-- å€Ÿæ–¹11列 -->
                  <template v-if="editingCell.row === rowIndex && editingCell.type === 'debit'">
                    <td colspan="11" class="debit-input-cell">
                      <el-input-number ref="amountInputRef" v-model="entry.debit" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" />
                      <el-input-number ref="amountInputRef" v-model="entry.debit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" :value-on-clear="undefined" size="small" @blur="finishEdit" class="full-width-input" />
                    </td>
                  </template>
                  <template v-else>
@@ -156,7 +173,7 @@
                  <!-- è´·æ–¹11列 -->
                  <template v-if="editingCell.row === rowIndex && editingCell.type === 'credit'">
                    <td colspan="11" class="credit-input-cell">
                      <el-input-number ref="amountInputRef" v-model="entry.credit" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" />
                      <el-input-number ref="amountInputRef" v-model="entry.credit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" :value-on-clear="undefined" size="small" @blur="finishEdit" class="full-width-input" />
                    </td>
                  </template>
                  <template v-else>
@@ -165,7 +182,7 @@
                    </td>
                  </template>
                  <td class="col-action">
                    <el-button type="danger" link size="small" @click="removeEntry(rowIndex)" icon="Delete" :disabled="form.entries.length <= 2">删除</el-button>
                    <el-button type="danger" link size="small" @click="removeEntry(rowIndex)" icon="Delete" :disabled="isViewMode || form.entries.length <= 2">删除</el-button>
                  </td>
                </tr>
                <tr class="total-row">
@@ -182,22 +199,68 @@
            </table>
          </div>
          <div class="voucher-toolbar">
            <el-button type="primary" link @click="addEntry" icon="Plus">新增行</el-button>
            <el-button type="primary" link @click="addEntry" icon="Plus" :disabled="isViewMode">新增行</el-button>
          </div>
          <div class="voucher-footer">
            <div class="creator-section">
              <span class="label">制单人:{{ form.creator }}</span>
              <span class="label">制单人:</span>
              <el-select
                v-model="form.creator"
                :disabled="isViewMode"
                placeholder="请选择制单人"
                filterable
                clearable
                style="width: 200px;"
              >
                <el-option
                  v-for="item in creatorOptions"
                  :key="item"
                  :label="item"
                  :value="item"
                />
              </el-select>
            </div>
          </div>
          <!-- ç¼–辑模式:使用 AttachmentUploadFile ä¸Šä¼ ç»„ä»¶ -->
          <div class="voucher-attachment-upload" v-if="!isViewMode">
            <div class="attachment-label">附件上传:</div>
            <AttachmentUploadFile
              v-model:fileList="form.attachments"
              :disabled="isViewMode"
              :limit="10"
              :fileSize="50"
              buttonText="点击上传附件"
              @change="handleAttachmentChange"
            />
          </div>
        </el-form>
        <!-- æŸ¥çœ‹æ¨¡å¼ï¼šå±•示附件列表(放在 el-form å¤–面,避免被 disabled) -->
        <div class="voucher-attachment-upload" v-if="isViewMode && form.attachments?.length">
          <div class="attachment-label">附件列表:</div>
          <el-table :data="form.attachments" border class="attachment-table">
            <el-table-column label="附件名称" show-overflow-tooltip>
              <template #default="scope">
                {{ scope.row.originalFilename || scope.row.name || scope.row.fileName || '未命名文件' }}
              </template>
            </el-table-column>
            <el-table-column fixed="right" label="操作" width="150" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="previewFile(scope.row)">预览</el-button>
                <el-button link type="primary" size="small" @click="downloadFile(scope.row)">下载</el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
      <template #footer>
        <div>
          <el-button type="primary" @click="submitForm" :disabled="!isBalanced">保存</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button v-if="!isViewMode" type="primary" @click="submitForm" :disabled="!isBalanced">保存</el-button>
          <el-button @click="dialogVisible = false">{{ isViewMode ? '关闭' : '取消' }}</el-button>
        </div>
      </template>
    </FormDialog>
    <!-- æ–‡ä»¶é¢„览组件 -->
    <FilePreview ref="filePreviewRef" />
  </div>
</template>
@@ -205,10 +268,28 @@
import { ref, reactive, onMounted, computed, nextTick } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import AttachmentUploadFile from "@/components/AttachmentUpload/file/index.vue";
import FileList from "@/components/Dialog/FileList.vue";
import FilePreview from "@/components/filePreview/index.vue";
import download from "@/plugins/download.js";
import useUserStore from "@/store/modules/user";
import { userListNoPageByTenantId } from "@/api/system/user";
import { listAccountSubject } from "@/api/financialManagement/accountSubject";
import {
  listVoucherPage,
  addVoucher,
  updateVoucher,
  postVoucher,
  cancelVoucher,
  getVoucherDetail,
} from "@/api/financialManagement/voucher";
defineOptions({
  name: "凭证管理",
});
const userStore = useUserStore();
const getDefaultCreator = () => userStore.nickName || userStore.name || "张三";
const filters = reactive({
  voucherNo: "",
@@ -227,39 +308,94 @@
  { label: "凭证字号", prop: "voucherNo", width: "120" },
  { label: "凭证日期", prop: "voucherDate", width: "120" },
  { label: "摘要", prop: "summary", showOverflowTooltip: true },
  { label: "借方金额", prop: "debit", slot: "debit" },
  { label: "贷方金额", prop: "credit", slot: "credit" },
  { label: "借方金额", prop: "debit", dataType: "slot", slot: "debit" },
  { label: "贷方金额", prop: "credit", dataType: "slot", slot: "credit" },
  { label: "制单人", prop: "creator", width: "100" },
  { label: "状态", prop: "status", slot: "status" },
  { label: "操作", prop: "operation", slot: "operation", width: "220", fixed: "right" },
  { label: "状态", prop: "status", dataType: "slot", slot: "status" },
  { label: "操作", prop: "operation", dataType: "slot", slot: "operation", width: "220", fixed: "right" },
];
const dataList = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref(null);
const dialogMode = ref("add");
const isEdit = ref(false);
const currentId = ref(null);
const isViewMode = computed(() => dialogMode.value === "view");
const filePreviewRef = ref(null);
const subjectList = [
  { code: "1001", name: "库存现金" },
  { code: "1002", name: "银行存款" },
  { code: "1122", name: "应收账款" },
  { code: "2202", name: "应付账款" },
  { code: "5001", name: "生产成本" },
  { code: "6001", name: "主营业务收入" },
  { code: "6401", name: "主营业务成本" },
const fallbackSubjectTree = [
  { subjectCode: "1001", subjectName: "库存现金", balanceDirection: "借方", children: [] },
  { subjectCode: "1002", subjectName: "银行存款", balanceDirection: "借方", children: [] },
  { subjectCode: "1122", subjectName: "应收账款", balanceDirection: "借方", children: [] },
  { subjectCode: "2202", subjectName: "应付账款", balanceDirection: "贷方", children: [] },
  { subjectCode: "5001", subjectName: "生产成本", balanceDirection: "借方", children: [] },
  { subjectCode: "6001", subjectName: "主营业务收入", balanceDirection: "贷方", children: [] },
  { subjectCode: "6401", subjectName: "主营业务成本", balanceDirection: "借方", children: [] },
];
const form = reactive({
const subjectTreeOptions = ref([]);
const subjectList = ref([]);
const subjectTreeSelectProps = {
  children: "children",
  label: "label",
  value: "value",
};
const buildSubjectTreeOptions = (nodes = [], flatList = []) =>
  (nodes || [])
    .filter(item => item.subjectCode && item.subjectName)
    .map(item => {
      const balanceDirection = item.balanceDirection || "";
      const flatItem = {
        code: item.subjectCode,
        name: item.subjectName,
        balanceDirection,
      };
      flatList.push(flatItem);
      return {
        value: flatItem.code,
        label: `${flatItem.code} ${flatItem.name}${balanceDirection ? ` [${balanceDirection}]` : ""}`,
        children: buildSubjectTreeOptions(item.children || [], flatList),
      };
    });
const createEmptyEntry = () => ({
  subjectCode: "",
  subjectName: "",
  balanceDirection: "",
  summary: "",
  debit: undefined,
  credit: undefined,
});
const createDefaultForm = () => ({
  voucherNo: "",
  voucherPrefix: "è®°",
  voucherNum: "",
  voucherDate: "",
  attachmentCount: 0,
  entries: [],
  creator: "张三",
  attachments: [],
  entries: [createEmptyEntry(), createEmptyEntry()],
  creator: getDefaultCreator(),
  remark: "",
});
const form = reactive({
  ...createDefaultForm(),
});
const userOptions = ref([]);
const creatorOptions = computed(() => {
  const source = [
    ...userOptions.value.map(item => item.nickName || item.userName || item.name),
    getDefaultCreator(),
    form.creator,
    filters.creator,
  ];
  return [...new Set(source.filter(Boolean))];
});
const selectedRowIndex = ref(-1);
@@ -276,12 +412,6 @@
const rules = {
  voucherDate: [{ required: true, message: "请选择凭证日期", trigger: "change" }],
};
const mockData = [
  { id: 1, voucherNo: "è®°-0001", voucherDate: "2024-01-15", summary: "销售收入", debit: 5650, credit: 5650, creator: "张三", status: "posted", entries: [{ subjectCode: "1002", subjectName: "银行存款", summary: "销售收入", debit: 5650, credit: 0 }, { subjectCode: "6001", subjectName: "主营业务收入", summary: "销售收入", debit: 0, credit: 5000 }, { subjectCode: "2221", subjectName: "应交税费", summary: "销项税额", debit: 0, credit: 650 }] },
  { id: 2, voucherNo: "è®°-0002", voucherDate: "2024-01-16", summary: "采购原材料", debit: 9040, credit: 9040, creator: "李四", status: "unposted", entries: [{ subjectCode: "5001", subjectName: "生产成本", summary: "采购原材料", debit: 8000, credit: 0 }, { subjectCode: "2221", subjectName: "应交税费", summary: "进项税额", debit: 1040, credit: 0 }, { subjectCode: "2202", subjectName: "应付账款", summary: "采购原材料", debit: 0, credit: 9040 }] },
  { id: 3, voucherNo: "è®°-0003", voucherDate: "2024-01-18", summary: "支付货款", debit: 5000, credit: 5000, creator: "张三", status: "posted", entries: [{ subjectCode: "2202", subjectName: "应付账款", summary: "支付货款", debit: 5000, credit: 0 }, { subjectCode: "1002", subjectName: "银行存款", summary: "支付货款", debit: 0, credit: 5000 }] },
];
const totalDebit = computed(() => {
  return dataList.value.reduce((sum, item) => sum + Number(item.debit), 0);
@@ -304,32 +434,79 @@
  return Number(value).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};
const normalizeVoucherStatus = status => String(status || "").toLowerCase();
const canEditVoucher = status => {
  const key = normalizeVoucherStatus(status);
  return key === "unposted" || status === "未过账";
};
const getStatusLabel = (status) => {
  const key = normalizeVoucherStatus(status);
  const map = { unposted: "未过账", posted: "已过账", cancelled: "已作废" };
  return map[status] || status;
  return map[key] || status;
};
const getStatusType = (status) => {
  const key = normalizeVoucherStatus(status);
  const map = { unposted: "warning", posted: "success", cancelled: "info" };
  return map[status] || "";
  return map[key] || "";
};
const getTableData = () => {
  let result = [...mockData];
  if (filters.voucherNo) {
    result = result.filter(item => item.voucherNo.includes(filters.voucherNo));
// è”调约定:分页参数使用 current/size,日期范围拆分为 startDate/endDate
const getTableData = async () => {
  try {
    const [startDate, endDate] =
      filters.dateRange && filters.dateRange.length === 2 ? filters.dateRange : ["", ""];
    const { data } = await listVoucherPage({
      current: pagination.currentPage,
      size: pagination.pageSize,
      voucherNo: filters.voucherNo,
      creator: filters.creator,
      status: filters.status,
      startDate,
      endDate,
    });
    dataList.value = data?.records || [];
    pagination.total = Number(data?.total || 0);
  } catch (error) {
    // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
  }
  if (filters.dateRange && filters.dateRange.length === 2) {
    result = result.filter(item => item.voucherDate >= filters.dateRange[0] && item.voucherDate <= filters.dateRange[1]);
};
// å‡­è¯åˆ†å½•里的科目下拉与总账科目保持一致,避免提交不存在科目
const loadSubjectList = async () => {
  try {
    const { data } = await listAccountSubject({
      current: 1,
      size: 1000,
      status: 0
    });
    const flatList = [];
    const treeOptions = buildSubjectTreeOptions(data?.records || [], flatList);
    if (treeOptions.length > 0) {
      subjectTreeOptions.value = treeOptions;
      subjectList.value = flatList;
      return;
    }
    const fallbackFlatList = [];
    subjectTreeOptions.value = buildSubjectTreeOptions(fallbackSubjectTree, fallbackFlatList);
    subjectList.value = fallbackFlatList;
  } catch (error) {
    // å…¨å±€æ‹¦æˆªå™¨å·²æç¤ºé”™è¯¯ï¼Œè¿™é‡Œä¿ç•™é»˜è®¤ç§‘目作为兜底
    const fallbackFlatList = [];
    subjectTreeOptions.value = buildSubjectTreeOptions(fallbackSubjectTree, fallbackFlatList);
    subjectList.value = fallbackFlatList;
  }
  if (filters.creator) {
    result = result.filter(item => item.creator === filters.creator);
};
const loadUserOptions = async () => {
  try {
    const { data } = await userListNoPageByTenantId();
    userOptions.value = Array.isArray(data) ? data : [];
  } catch (error) {
    userOptions.value = [];
  }
  if (filters.status) {
    result = result.filter(item => item.status === filters.status);
  }
  pagination.total = result.length;
  dataList.value = result.slice((pagination.currentPage - 1) * pagination.pageSize, pagination.currentPage * pagination.pageSize);
};
const resetFilters = () => {
@@ -348,7 +525,35 @@
};
const addEntry = () => {
  form.entries.push({ subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 });
  if (isViewMode.value) {
    return;
  }
  form.entries.push(createEmptyEntry());
};
const handleAttachmentChange = (fileList) => {
  form.attachmentCount = fileList?.length || 0;
};
// ä½¿ç”¨é¡¹ç›®å°è£…çš„ filePreview ç»„件预览文件
const previewFile = (row) => {
  const url = row.previewURL || row.previewUrl || row.url;
  if (url && filePreviewRef.value) {
    filePreviewRef.value.open(url);
  } else {
    ElMessage.warning('文件地址无效,无法预览');
  }
};
// ä½¿ç”¨é¡¹ç›®å°è£…çš„ download æ’件下载文件
const downloadFile = (row) => {
  const url = row.downloadURL || row.downloadUrl || row.url;
  if (url) {
    const filename = row.originalFilename || row.name || row.fileName || 'download';
    download.byUrl(url, filename);
  } else {
    ElMessage.warning('文件地址无效,无法下载');
  }
};
const selectRow = (index) => {
@@ -356,6 +561,9 @@
};
const openAmountInput = (index, type) => {
  if (isViewMode.value) {
    return;
  }
  editingCell.row = index;
  editingCell.type = type;
  nextTick(() => {
@@ -402,65 +610,86 @@
};
const removeEntry = (index) => {
  if (isViewMode.value) {
    return;
  }
  if (form.entries.length <= 2) {
    return;
  }
  form.entries.splice(index, 1);
  calculateTotal();
};
const handleSubjectChange = (val, index) => {
  const subject = subjectList.find(item => item.code === val);
  const subject = subjectList.value.find(item => item.code === val);
  if (subject) {
    form.entries[index].subjectName = subject.name;
    form.entries[index].balanceDirection = subject.balanceDirection || "";
  } else {
    form.entries[index].subjectName = "";
    form.entries[index].balanceDirection = "";
  }
};
const calculateTotal = () => {
  // è‡ªåŠ¨è®¡ç®—ï¼Œç”±computed属性处理
};
const add = () => {
  dialogMode.value = "add";
  isEdit.value = false;
  currentId.value = null;
  dialogTitle.value = "新增凭证";
  const nextNum = String(mockData.length + 1).padStart(2, "0");
  Object.assign(form, {
    voucherNo: "è®°-" + nextNum,
  const nextNum = String((pagination.total || 0) + 1).padStart(4, "0");
  Object.assign(form, createDefaultForm(), {
    voucherPrefix: "è®°",
    voucherNum: nextNum,
    voucherNo: `è®°-${nextNum}`,
    voucherDate: new Date().toISOString().split('T')[0],
    attachmentCount: 0,
    entries: [
      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
      { subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 },
    ],
    creator: "张三",
    remark: "",
  });
  selectedRowIndex.value = 0;
  dialogVisible.value = true;
};
const edit = (row) => {
  isEdit.value = true;
  currentId.value = row.id;
  dialogTitle.value = "编辑凭证";
  const parts = row.voucherNo.split('-');
  Object.assign(form, {
    ...row,
    voucherPrefix: parts[0] || 'è®°',
    voucherNum: parts[1] || '',
  });
  if (form.entries.length < 4) {
    while (form.entries.length < 4) {
      form.entries.push({ subjectCode: "", subjectName: "", summary: "", debit: 0, credit: 0 });
const openVoucherDialog = async (row, mode = "edit") => {
  try {
    dialogMode.value = mode;
    isEdit.value = mode === "edit";
    currentId.value = row.id;
    dialogTitle.value = mode === "view" ? "查看凭证" : "编辑凭证";
    const { data } = await getVoucherDetail(row.id);
    const detail = data || row;
    const parts = (detail.voucherNo || "").split("-");
    const attachments = detail.storageBlobVOList || detail.storageBlobDTOs || detail.attachments || [];
    Object.assign(form, createDefaultForm(), {
      ...detail,
      voucherPrefix: parts[0] || "è®°",
      voucherNum: parts[1] || "",
      creator: detail.creator || getDefaultCreator(),
      attachments,
      entries:
        detail.entries?.map(item => ({
          subjectCode: item.subjectCode || "",
          subjectName: item.subjectName || "",
          balanceDirection: item.balanceDirection || "",
          summary: item.summary || "",
          debit: Number(item.debit || 0),
          credit: Number(item.credit || 0),
        })) || [],
    });
    if (form.entries.length < 2) {
      while (form.entries.length < 2) {
        form.entries.push(createEmptyEntry());
      }
    }
    selectedRowIndex.value = 0;
    dialogVisible.value = true;
  } catch (error) {
    // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
  }
  selectedRowIndex.value = 0;
  dialogVisible.value = true;
};
const view = (row) => {
  ElMessage.info(`查看凭证: ${row.voucherNo}`);
const edit = async row => {
  await openVoucherDialog(row, "edit");
};
const view = async row => {
  await openVoucherDialog(row, "view");
};
const handlePost = (row) => {
@@ -468,13 +697,10 @@
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "info",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData[index].status = "posted";
    }
  }).then(async () => {
    await postVoucher({ id: row.id });
    ElMessage.success("过账成功");
    getTableData();
    await getTableData();
  });
};
@@ -483,13 +709,10 @@
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  }).then(() => {
    const index = mockData.findIndex(item => item.id === row.id);
    if (index !== -1) {
      mockData[index].status = "cancelled";
    }
  }).then(async () => {
    await cancelVoucher({ id: row.id });
    ElMessage.success("作废成功");
    getTableData();
    await getTableData();
  });
};
@@ -502,45 +725,80 @@
};
const submitForm = () => {
  formRef.value.validate((valid) => {
  if (isViewMode.value) {
    dialogVisible.value = false;
    return;
  }
  formRef.value.validate(async valid => {
    if (valid) {
      // å‰ç½®æ ¡éªŒï¼šä¸ŽåŽç«¯è§„则对齐,减少无效请求
      if (!isBalanced.value) {
        ElMessage.error("借贷不平衡,请检查分录");
        return;
      }
      const validEntries = form.entries.filter(e => e.subjectCode && (e.debit > 0 || e.credit > 0));
      const validEntries = form.entries.filter(
        entry => entry.subjectCode && (Number(entry.debit) > 0 || Number(entry.credit) > 0)
      );
      if (validEntries.length === 0) {
        ElMessage.error("请至少填写一条有效分录");
        return;
      }
      const invalidEntry = validEntries.find(
        entry => Number(entry.debit) > 0 && Number(entry.credit) > 0
      );
      if (invalidEntry) {
        ElMessage.error("同一分录不能同时填写借方和贷方");
        return;
      }
      const summary = validEntries.find(e => e.debit > 0)?.summary || "";
      const voucherNo = `${form.voucherPrefix}-${form.voucherNum}`;
      const dataToSave = {
        ...form,
        voucherNo,
        voucherDate: form.voucherDate,
        summary,
        creator: form.creator,
        attachmentCount: Number(form.attachmentCount || 0),
        remark: form.remark,
        debit: totalDebitEntry.value,
        credit: totalCreditEntry.value,
        entries: validEntries,
        storageBlobDTOs: form.attachments || [],
        entries: validEntries.map(entry => ({
          subjectCode: entry.subjectCode,
          subjectName: entry.subjectName,
          summary: entry.summary,
          debit: Number(entry.debit || 0),
          credit: Number(entry.credit || 0),
        })),
      };
      if (isEdit.value) {
        const index = mockData.findIndex(item => item.id === currentId.value);
        if (index !== -1) {
          mockData[index] = { ...mockData[index], ...dataToSave };
      try {
        if (isEdit.value) {
          await updateVoucher({
            id: currentId.value,
            ...dataToSave,
          });
          ElMessage.success("编辑成功");
        } else {
          await addVoucher(dataToSave);
          ElMessage.success("新增成功");
        }
        ElMessage.success("编辑成功");
      } else {
        const newId = mockData.length > 0 ? Math.max(...mockData.map(item => item.id)) + 1 : 1;
        mockData.push({ id: newId, ...dataToSave, status: "unposted" });
        ElMessage.success("新增成功");
        dialogVisible.value = false;
        await getTableData();
      } catch (error) {
        // æç¤ºç”±å…¨å±€è¯·æ±‚拦截器处理,这里仅防止未捕获异常
      }
      dialogVisible.value = false;
      getTableData();
    }
  });
};
onMounted(() => {
  getTableData();
onMounted(async () => {
  await loadUserOptions();
  await loadSubjectList();
  await getTableData();
});
</script>
@@ -610,6 +868,21 @@
  .voucher-attachment-section {
    display: flex;
    align-items: center;
  }
}
.voucher-attachment-upload {
  margin-top: 15px;
  padding: 0 10px;
  .attachment-label {
    font-size: 14px;
    color: #606266;
    margin-bottom: 10px;
  }
  .attachment-table {
    border-radius: 4px;
  }
}
@@ -780,7 +1053,8 @@
    .col-subject {
      position: relative;
      .el-select {
      .el-select,
      .el-tree-select {
        .el-input input {
          font-size: 12px;
        }
src/views/index.vue
@@ -1,156 +1,321 @@
<template>
  <div class="dashboard">
    <!-- é¡¶éƒ¨æ¨ªå‘两栏 -->
    <div class="dashboard-top">
      <!-- å·¦ï¼šä¼ä¸šä¿¡æ¯+三大数据卡片(上下排列) -->
      <div class="top-left">
        <div class="company-info">
          <!-- é¡¶éƒ¨é—®å€™æ¡ -->
          <div class="welcome-banner">
            <div class="welcome-title">
              <span class="welcome-user">{{ userStore.nickName || '系统管理员' }}</span>
              <span> æ‚¨å¥½ï¼ç¥æ‚¨å¼€å¿ƒæ¯ä¸€å¤©</span>
            </div>
            <div class="welcome-time">登录于: {{ userStore.currentLoginTime }}</div>
  <div class="dashboard-cockpit">
    <section class="cockpit-panel welcome-panel">
      <div class="welcome-user">
        <el-avatar :src="welcomeAvatar" class="avatar" @error="handleWelcomeAvatarError">
          <el-icon><UserFilled /></el-icon>
        </el-avatar>
        <div class="welcome-text">
          <div class="welcome-title">
            {{ greetingText }},{{ userStore.nickName || userStore.name || "超级管理员" }} ðŸ‘‹
          </div>
          <div class="welcome-subtitle">专注工业数字化,助力智造升级</div>
        </div>
      </div>
      <div class="welcome-meta">
        <div class="meta-time digital-number">{{ nowTime }}</div>
        <div class="meta-tip">MES / MOM ç”Ÿäº§è¿è¥é©¾é©¶èˆ±</div>
      </div>
    </section>
          <!-- ç”¨æˆ·ä¿¡æ¯å¡ç‰‡ -->
          <div class="user-card">
            <img :src="userStore.avatar" class="avatar" alt="" />
            <div class="user-card-main">
              <div class="user-name">{{ userStore.name }}</div>
              <div class="user-role">{{ userStore.roleName }}</div>
              <div class="user-meta">
                <span>{{ userStore.phoneNumber || '123456789' }}</span>
                <span class="sep">|</span>
                <span>{{ userStore.deptName || '组织架构' }}</span>
                <span class="sep">|</span>
                <span>{{ userStore.postName || '岗位名' }}</span>
    <section v-if="dashboardCards.length > 0" class="top-row">
      <div class="stats-grid">
        <article
            v-for="card in dashboardCards"
            :key="card.key"
            class="stat-card"
            :class="card.key"
        >
          <div class="stat-header">
            <div class="stat-title-wrap">
              <div class="stat-title">{{ card.title }}</div>
              <div class="stat-desc">{{ card.desc }}</div>
            </div>
            <div class="stat-icon-orb">
              <el-icon>
                <component :is="card.icon" />
              </el-icon>
            </div>
          </div>
          <div class="stat-value digital-number">{{ card.value }}</div>
          <div class="stat-footer">
            <span>{{ card.subLabel }}</span>
            <strong class="digital-number">{{ card.subValue }}</strong>
          </div>
          <div class="stat-trend">{{ card.trend }}</div>
          <div class="stat-wave" aria-hidden="true"></div>
        </article>
      </div>
    </section>
    <section v-if="hasVisiblePanels" class="main-grid">
      <div v-if="hasLeftPanels" class="left-column">
        <div v-if="visiblePanels.process" class="cockpit-panel process-panel">
          <div class="panel-title-row">
            <div class="panel-title">工序数据生产统计明细</div>
            <div class="panel-actions">
              <el-button type="primary" size="small" plain @click="openProcessDialog">选择工序</el-button>
              <el-button size="small" plain @click="resetProcessFilter">重置</el-button>
              <el-radio-group v-model="processRange" size="small" @change="refreshProcessStats">
                <el-radio-button :value="1">日</el-radio-button>
                <el-radio-button :value="2">周</el-radio-button>
                <el-radio-button :value="3">月</el-radio-button>
              </el-radio-group>
            </div>
          </div>
          <div class="process-body">
            <div class="process-chart" :class="{ empty: !hasProcessData }">
              <Echarts
                  :options="chartBaseOptions"
                  :chartStyle="{ width: '100%', height: '100%' }"
                  :grid="processGrid"
                  :series="processSeries"
                  :tooltip="processTooltip"
                  :xAxis="processXAxis"
                  :yAxis="processYAxis"
                  :style="{ height: hasProcessData ? '340px' : '280px' }"
                  @click="handleChartClick"
              />
              <div v-if="!hasProcessData" class="chart-empty">
                <el-icon><DataAnalysis /></el-icon>
                <div class="chart-empty-title">暂无工序数据</div>
                <div class="chart-empty-desc">等待生产报工数据接入后自动生成统计图表</div>
                <div class="chart-empty-actions">
                  <el-button size="small" @click="refreshProcessStats">刷新数据</el-button>
                  <el-button size="small" type="primary" plain @click="openProcessDialog">选择工序</el-button>
                </div>
              </div>
            </div>
            <div class="process-aside">
              <div class="process-legend">
                <div class="process-name">{{ processAside.processName }}</div>
                <div class="process-legend-item"><span class="dot dot-blue"></span>投入量</div>
                <div class="process-legend-item"><span class="dot dot-orange"></span>报废量</div>
                <div class="process-legend-item"><span class="dot dot-cyan"></span>产出量</div>
              </div>
              <div class="process-card">
                <div class="process-label">累计总投入</div>
                <div class="process-value digital-number">{{ formatAmount(processAside.totalInput) }}</div>
              </div>
              <div class="process-card">
                <div class="process-label">累计总报废</div>
                <div class="process-value digital-number">{{ formatAmount(processAside.totalScrap) }}</div>
              </div>
              <div class="process-card">
                <div class="process-label">累计总产出</div>
                <div class="process-value digital-number">{{ formatAmount(processAside.totalOutput) }}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="data-cards">
        <div class="data-card sales">
          <div class="data-title">销售数据</div>
          <div class="data-num">
            <div>
              <div class="data-desc">本月销售额/元</div>
              <div class="data-value">{{ businessInfo.monthSaleMoney }}</div>
            </div>
            <div>
              <div class="data-desc">未开票金额/元</div>
              <div class="data-value">{{ businessInfo.monthSaleHaveMoney }}</div>
            </div>
          </div>
        </div>
        <div class="data-card purchase">
          <div class="data-title">采购数据</div>
          <div class="data-num">
            <div>
              <div class="data-desc">本月采购额/元</div>
              <div class="data-value">{{ businessInfo.monthPurchaseMoney }}</div>
            </div>
            <div>
              <div class="data-desc">待付款金额/元</div>
              <div class="data-value">{{ businessInfo.monthPurchaseHaveMoney }}</div>
            </div>
          </div>
        </div>
        <div class="data-card inventory">
          <div class="data-title">库存数据</div>
          <div class="data-num">
            <div>
              <div class="data-desc">当前库存总量/ä»¶</div>
              <div class="data-value">{{ businessInfo.inventoryNum }}</div>
            </div>
            <div>
              <div class="data-desc">今日入库/ä»¶</div>
              <div class="data-value">{{ businessInfo.todayInventoryNum }}</div>
            </div>
          </div>
        </div>
      </div>
      <!-- å³ï¼šå¾…办事项 -->
      <div class="todo-panel">
        <div class="section-title">待办事项</div>
        <ul class="todo-list" v-if="todoList.length > 0">
          <li v-for="item in todoList" :key="item.id">
            <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px">
              <div style="display: flex;justify-content: space-between;align-items: center;">
                <div class="todo-title">待办编号:{{ item.approveId }}</div>
                <div class="todo-division">部门:{{ item.approveDeptName }}</div>
                <div class="todo-time">{{ item.approveTime }}</div>
              </div>
              <div class="todo-division">待办事由:{{ item.approveReason }}</div>
            </div>
          </li>
        </ul>
        <div v-else style="text-align: center">
          æš‚无数据
        </div>
      </div>
    </div>
    <div class="dashboard-row">
      <div class="main-panel process-panel">
        <div class="process-panel__header">
          <div class="section-title">工序数据生产统计明细</div>
          <div style="display: flex; gap: 10px; align-items: center;">
            <el-button type="primary" size="small" plain icon="Filter" @click="openProcessDialog">选择工序</el-button>
            <el-button type="info" size="small" plain icon="Refresh" @click="resetProcessFilter">重置</el-button>
            <el-radio-group v-model="processRange" size="small" @change="refreshProcessStats">
              <el-radio-button :value="1">日</el-radio-button>
              <el-radio-button :value="2">周</el-radio-button>
              <el-radio-button :value="3">月</el-radio-button>
        <div v-if="visiblePanels.order" class="cockpit-panel order-panel">
          <div class="panel-title-row">
            <div class="panel-title">生产订单进度</div>
            <el-radio-group v-model="orderFilter" size="small">
              <el-radio-button label="all">全部({{ orderProgressMeta.total }})</el-radio-button>
              <el-radio-button label="waiting">待开始({{ orderProgressMeta.waitingCount }})</el-radio-button>
              <el-radio-button label="inProgress">进行中({{ orderProgressMeta.inProgressCount }})</el-radio-button>
              <el-radio-button label="completed">已完成({{ orderProgressMeta.completedCount }})</el-radio-button>
              <el-radio-button label="paused">已暂停({{ orderProgressMeta.pausedCount }})</el-radio-button>
            </el-radio-group>
          </div>
          <el-table :data="filteredOrders" stripe>
            <el-table-column prop="orderNo" label="订单编号" min-width="150" />
            <el-table-column prop="productName" label="产品名称" min-width="120" />
            <el-table-column prop="planQty" label="计划数量" min-width="90" />
            <el-table-column prop="completedQty" label="已完成" min-width="90" />
            <el-table-column label="完成率" min-width="180">
              <template #default="{ row }">
                <div class="table-progress">
                  <el-progress
                      :stroke-width="8"
                      :percentage="row.completionRate"
                      :show-text="false"
                      status="success"
                  />
                  <span>{{ row.completionRate }}%</span>
                </div>
              </template>
            </el-table-column>
            <el-table-column prop="deliveryDate" label="交期" min-width="110" />
            <el-table-column label="状态" min-width="90">
              <template #default="{ row }">
                <el-tag :type="getOrderStatusType(row.status)" effect="light">
                  {{ row.statusLabel || getOrderStatusText(row.status) }}
                </el-tag>
              </template>
            </el-table-column>
          </el-table>
        </div>
        <div class="process-panel__body">
          <div class="process-panel__chart">
            <Echarts :chartStyle="{ width: '100%', height: '100%' }" :grid="processGrid" :series="processSeries"
              :tooltip="processTooltip" :xAxis="processXAxis" :yAxis="processYAxis" style="height: 100%"
              @click="handleChartClick" />
          </div>
          <div class="process-panel__aside">
            <div class="process-legend">
              <div class="process-legend__item">
                <span class="dot dot-blue"></span><span>投入量</span>
              </div>
              <div class="process-legend__item">
                <span class="dot dot-yellow"></span><span>报废量</span>
              </div>
              <div class="process-legend__item">
                <span class="dot dot-teal"></span><span>产出量</span>
        <div v-if="visiblePanels.contract" class="cockpit-panel contract-panel">
          <div class="panel-title">客户合同金额分析</div>
          <div class="contract-summary">
            <div class="contract-card">
              <div class="contract-name">总合同金额(元)</div>
              <div class="contract-main digital-number">{{ formatNumber(sum) }}</div>
              <div class="contract-compare">
                åŒæ¯”
                <span class="rise">{{ trendText(yny) }}</span>
                çŽ¯æ¯”
                <span class="rise">{{ trendText(chain) }}</span>
              </div>
            </div>
            <div class="process-card process-card--name">{{ processAside.processName }}</div>
            <div class="process-card">
              <div class="process-card__label">累计总投入</div>
              <div class="process-card__value">{{ formatAmount(processAside.totalInput) }}
              </div>
            </div>
            <div class="process-card">
              <div class="process-card__label">累计总报废</div>
              <div class="process-card__value">{{ formatAmount(processAside.totalScrap) }}
              </div>
            </div>
            <div class="process-card">
              <div class="process-card__label">累计总产出</div>
              <div class="process-card__value">{{ formatAmount(processAside.totalOutput) }}
              </div>
            <div class="contract-chart-wrap">
              <Echarts
                  :options="chartBaseOptions"
                  :legend="pieLegend"
                  :chartStyle="chartStylePie"
                  :series="materialPieSeries"
                  :tooltip="pieTooltip"
              />
            </div>
          </div>
          <ul class="contract-list">
            <li v-for="item in materialPieSeries[0].data" :key="item.name">
              <span class="legend-dot" :style="{ backgroundColor: item.itemStyle?.color }"></span>
              <span class="contract-item-name">{{ item.name }}</span>
              <span class="contract-item-rate">{{ item.rate }}%</span>
              <span class="contract-item-value digital-number">Â¥{{ formatNumber(item.value) }}</span>
            </li>
          </ul>
        </div>
        <div v-if="visiblePanels.quality" class="cockpit-panel quality-panel">
          <div class="panel-title-row">
            <div class="panel-title">质量统计</div>
            <el-radio-group v-model="qualityRange" size="small" @change="qualityStatisticsInfo">
              <el-radio-button :value="1">周</el-radio-button>
              <el-radio-button :value="2">月</el-radio-button>
              <el-radio-button :value="3">季度</el-radio-button>
            </el-radio-group>
          </div>
          <div class="quality-cards">
            <div class="quality-card one">原材料已检数量 <span>{{ qualityStatisticsObject.supplierNum }}ä»¶</span></div>
            <div class="quality-card two">过程检验数量 <span>{{ qualityStatisticsObject.processNum }}ä»¶</span></div>
            <div class="quality-card three">出厂已检数量 <span>{{ qualityStatisticsObject.factoryNum }}ä»¶</span></div>
          </div>
          <Echarts
              :options="chartBaseOptions"
              :chartStyle="chartStyle"
              :grid="grid"
              :legend="barLegend"
              :series="barSeries1"
              :tooltip="tooltip"
              :xAxis="xAxis1"
              :yAxis="yAxis1"
              style="height: 270px"
          />
        </div>
      </div>
    </div>
    <!-- å·¥åºé€‰æ‹©å¼¹çª— -->
      <div v-if="hasRightPanels" class="right-column">
        <div v-if="visiblePanels.todo" class="cockpit-panel todo-panel">
          <div class="panel-title-row">
            <div class="panel-title">待办事项</div>
            <span class="panel-more">更多</span>
          </div>
          <ul class="todo-list" v-if="todoList.length > 0">
            <li v-for="item in todoList" :key="item.id" class="todo-item">
              <div class="todo-head">
                <span class="todo-no">待办编号:{{ item.approveId }}</span>
                <span class="todo-time">{{ item.approveTime }}</span>
              </div>
              <div class="todo-desc">部门:{{ item.approveDeptName }}</div>
              <div class="todo-desc">事由:{{ item.approveReason }}</div>
            </li>
          </ul>
          <div v-else class="panel-empty">暂无数据</div>
        </div>
        <div v-if="visiblePanels.realtime" class="cockpit-panel realtime-panel">
          <div class="panel-title-row">
            <div class="panel-title">生产实时看板</div>
            <span class="panel-more">更多</span>
          </div>
          <div class="realtime-grid">
            <div class="realtime-item" v-for="item in realtimeBoard" :key="item.key">
              <el-progress
                  type="circle"
                  :percentage="item.percent"
                  :stroke-width="10"
                  :width="94"
                  :color="item.color"
              >
                <template #default>
                  <div class="realtime-value digital-number">{{ item.display }}</div>
                </template>
              </el-progress>
              <div class="realtime-label">{{ item.label }}</div>
              <div class="realtime-delta" :class="item.trend">{{ item.delta }}</div>
            </div>
          </div>
        </div>
        <div v-if="visiblePanels.quick" class="cockpit-panel quick-panel">
          <div class="panel-title-row">
            <div class="panel-title">快捷功能</div>
          </div>
          <div class="quick-grid">
            <button
                v-for="item in quickEntries"
                :key="item.label"
                class="quick-item"
                type="button"
                @click="goToQuick(item.path)"
            >
              <span class="quick-icon">
                <el-icon>
                  <component :is="item.icon" />
                </el-icon>
              </span>
              <span>{{ item.label }}</span>
            </button>
          </div>
        </div>
        <div v-if="visiblePanels.plan" class="cockpit-panel plan-panel">
          <div class="panel-title-row">
            <div class="panel-title">今日生产计划</div>
            <span class="panel-more">{{ todayPlanTotal }}项</span>
          </div>
          <ul class="plan-list">
            <li v-for="item in todayPlanList" :key="item.orderNo" class="plan-item">
              <div class="plan-main">
                <span class="plan-order">{{ item.orderNo }}</span>
                <span class="plan-name">{{ item.productName }}</span>
              </div>
              <div class="plan-meta">
                <span>计划 {{ item.planQty }}</span>
                <span>交期 {{ item.deliveryDate }}</span>
              </div>
            </li>
          </ul>
        </div>
        <div v-if="visiblePanels.receipt" class="cockpit-panel receipt-panel">
          <div class="panel-title">回款与开票分析</div>
          <Echarts
              :options="chartBaseOptions"
              :chartStyle="chartStyle"
              :grid="grid"
              :legend="lineLegend"
              :series="lineSeries"
              :tooltip="tooltipLine"
              :xAxis="xAxis2"
              :yAxis="yAxis2"
              style="height: 300px"
          />
        </div>
      </div>
    </section>
    <section v-else class="cockpit-panel empty-home-panel">
      å½“前账号没有可展示的首页模块
    </section>
    <el-dialog v-model="processDialogVisible" title="选择工序" width="500px" append-to-body>
      <div class="process-selection-wrapper">
        <el-checkbox-group v-model="tempProcessIds">
@@ -168,105 +333,99 @@
        </span>
      </template>
    </el-dialog>
    <!-- ä¸­éƒ¨æ¨ªå‘两栏 -->
    <div class="dashboard-row">
      <div class="main-panel">
        <div class="section-title">客户合同金额分析</div>
        <div class="contract-summary">
          <div class="contract-info">
            <img src="../assets/images/khtitle.png" alt="" style="width: 42px" />
            <div class="contract-card">
              <div class="contract-name">总合同金额(元)</div>
              <div class="contract-meta">
                <div class="main-amount">{{ sum }}</div>
                <div>周同比: <span class="up">{{ yny }}% </span> æ—¥çŽ¯æ¯”: <span class="up">{{ chain }}% </span></div>
              </div>
            </div>
          </div>
        </div>
        <div
          style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 180px;margin-top: 20px">
          <div>
            <Echarts ref="chart" :legend="pieLegend" :chartStyle="chartStylePie" :series="materialPieSeries"
              :tooltip="pieTooltip"></Echarts>
          </div>
          <ul class="contract-list">
            <li v-for="item in materialPieSeries[0].data" :key="item.name">
              <div style="display: flex;align-items: center;justify-content: space-between;width: 100%">
                <div class="line" :style="{ color: item.itemStyle.color }">●{{ item.name }}</div>
                <div style="width: 70px">{{ item.rate }}%</div>
                <div>ï¿¥{{ item.value }}</div>
              </div>
            </li>
          </ul>
        </div>
      </div>
      <div class="main-panel">
        <div style="display: flex;justify-content: space-between;">
          <div class="section-title">应收应付统计</div>
          <!--                    <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable">-->
          <!--                        <el-radio-button label="按周" :value="1" />-->
          <!--                        <el-radio-button label="按月" :value="2" />-->
          <!--                        <el-radio-button label="按季度" :value="3" />-->
          <!--                    </el-radio-group>-->
        </div>
        <Echarts ref="chart" :color="barColors2" :chartStyle="chartStyle" :grid="grid" :series="barSeries"
          :tooltip="tooltip" :xAxis="xAxis" :yAxis="yAxis" style="height: 260px"></Echarts>
      </div>
    </div>
    <!-- åº•部横向两栏 -->
    <div class="dashboard-row">
      <div class="main-panel">
        <div style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;">
          <div class="section-title" style="margin-bottom: 0;">质量统计</div>
          <el-radio-group v-model="qualityRange" size="small" @change="qualityStatisticsInfo">
            <el-radio-button :value="1">周</el-radio-button>
            <el-radio-button :value="2">月</el-radio-button>
            <el-radio-button :value="3">季度</el-radio-button>
          </el-radio-group>
        </div>
        <div class="quality-cards">
          <div class="quality-card one">原材料已检测数 <span>{{ qualityStatisticsObject.supplierNum }}ä»¶</span></div>
          <div class="quality-card two">过程检验数量 <span>{{ qualityStatisticsObject.processNum }}ä»¶</span></div>
          <div class="quality-card three">出厂已检数量 <span>{{ qualityStatisticsObject.factoryNum }}ä»¶</span></div>
        </div>
        <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="barLegend" :series="barSeries1"
          :tooltip="tooltip" :xAxis="xAxis1" :yAxis="yAxis1" style="height: 260px"></Echarts>
      </div>
      <div class="main-panel">
        <div class="section-title">回款与开票分析</div>
        <Echarts ref="invoiceChart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries"
          :tooltip="tooltipLine" :xAxis="xAxis2" :yAxis="yAxis2" style="height: 270px;" />
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted, computed, reactive } from 'vue'
import { ref, onMounted, onUnmounted, computed, reactive, watch } from "vue";
import { useRouter } from "vue-router";
import dayjs from "dayjs";
import * as echarts from "echarts";
import {
  Box,
  Calendar,
  Checked,
  DataAnalysis,
  DataLine,
  EditPen,
  Operation,
  Search,
  ShoppingCartFull,
  Tickets,
  Tools,
  UserFilled,
} from "@element-plus/icons-vue";
import Echarts from "@/components/Echarts/echarts.vue";
import * as echarts from 'echarts';
import usePermissionStore from "@/store/modules/permission";
import useUserStore from "@/store/modules/user.js";
import {
  analysisCustomerContractAmounts, getAmountHalfYear,
  analysisCustomerContractAmounts,
  getAmountHalfYear,
  getBusiness,
  homeTodos,
  processDataProductionStatistics,
  productionOrderProgress,
  productionOverview,
  productionRealtimeBoard,
  qualityInspectionStatistics,
  statisticsReceivablePayable,
  qualityInspectionStatistics
  todayProductionPlan,
} from "@/api/viewIndex.js";
import { list } from '@/api/productionManagement/productionProcess';
import { list } from "@/api/productionManagement/productionProcess";
const router = useRouter();
const userStore = useUserStore();
const permissionStore = usePermissionStore();
const defaultWelcomeAvatar = new URL("../assets/images/profile.jpg", import.meta.url).href;
const userStore = useUserStore()
const nowTime = ref("");
const welcomeAvatarLoadFailed = ref(false);
let clockTimer = null;
const weatherText = "多云 28°C";
const processOptions = ref([])
const selectedProcessIds = ref([])
const tempProcessIds = ref([])
const processDialogVisible = ref(false)
const activeProcessIndex = ref(0)
const nowDate = computed(() => (nowTime.value ? nowTime.value.slice(0, 10) : dayjs().format("YYYY-MM-DD")));
const greetingText = computed(() => {
  const hour = dayjs().hour();
  if (hour < 6) return "凌晨好";
  if (hour < 9) return "早上好";
  if (hour < 12) return "上午好";
  if (hour < 14) return "中午好";
  if (hour < 18) return "下午好";
  return "晚上好";
});
const welcomeAvatar = computed(() =>
    welcomeAvatarLoadFailed.value || !userStore.avatar ? defaultWelcomeAvatar : userStore.avatar
);
const handleWelcomeAvatarError = () => {
  if (welcomeAvatar.value !== defaultWelcomeAvatar) {
    welcomeAvatarLoadFailed.value = true;
  }
};
watch(
    () => userStore.avatar,
    () => {
      welcomeAvatarLoadFailed.value = false;
    }
);
const axisTextColor = "#5f6f86";
const axisLineColor = "rgba(148, 163, 184, 0.45)";
const splitLineColor = "rgba(148, 163, 184, 0.18)";
const chartBaseOptions = reactive({
  backgroundColor: "transparent",
  textStyle: { color: axisTextColor },
});
const processOptions = ref([]);
const selectedProcessIds = ref([]);
const tempProcessIds = ref([]);
const processDialogVisible = ref(false);
const activeProcessIndex = ref(0);
const businessInfo = ref({
  inventoryNum: 0,
@@ -275,988 +434,2033 @@
  monthSaleHaveMoney: 0,
  monthSaleMoney: 0,
  todayInventoryNum: 0,
})
});
const qualityStatisticsObject = ref({
  supplierNum: 0,
  processNum: 0,
  factoryNum: 0,
})
const sum = ref(0)
const yny = ref(0)
const chain = ref(0)
});
const pieLegend = reactive({
  show: false,
})
const productionOverviewData = ref({
  totalOutput: 0,
  totalScrap: 0,
  yieldRate: 0,
});
const realtimeBoardData = ref({
  deviceOee: { value: 0, compareYesterday: 0 },
  orderAchievementRate: { value: 0, compareYesterday: 0 },
  defectRate: { value: 0, compareYesterday: 0 },
});
const orderProgressMeta = ref({
  status: "all",
  tab: "all",
  bizDate: null,
  total: 0,
  pageNum: 1,
  pageSize: 10,
  waitingCount: 0,
  inProgressCount: 0,
  completedCount: 0,
  pausedCount: 0,
});
const todayPlanList = ref([]);
const todayPlanTotal = ref(0);
const sum = ref(0);
const yny = ref(0);
const chain = ref(0);
const pieLegend = reactive({ show: false });
const piePalette = ["#2563eb", "#14b8a6", "#7c3aed", "#f97316", "#38bdf8", "#f43f5e"];
const chartStyle = {
  width: "100%",
  height: "100%",
};
const chartStylePie = {
  width: "100%",
  height: "200px",
};
const grid = {
  left: "3%",
  right: "4%",
  bottom: "2%",
  top: "12%",
  containLabel: true,
};
const tooltip = {
  trigger: "axis",
  axisPointer: { type: "shadow" },
  backgroundColor: "rgba(255, 255, 255, 0.97)",
  borderColor: "rgba(148, 163, 184, 0.26)",
  textStyle: { color: "#334155" },
};
const barColors2 = ["#2563eb", "#14b8a6"];
const xAxis = [
  {
    type: "value",
    axisLine: { lineStyle: { color: axisLineColor } },
    splitLine: { lineStyle: { color: splitLineColor } },
    axisLabel: { color: axisTextColor },
  },
];
const yAxis = [
  {
    type: "category",
    data: ["应付账款", "应收账款"],
    axisTick: { show: false },
    axisLine: { lineStyle: { color: axisLineColor } },
    axisLabel: { color: axisTextColor },
  },
];
const barSeries = ref([
  {
    type: 'bar',
    type: "bar",
    barWidth: 22,
    itemStyle: { borderRadius: [0, 8, 8, 0] },
    label: { show: true, position: "right", color: "#334155" },
    data: [],
    label: {
      show: true,
    }
  },
])
]);
const barLegend = {
  show: true,
  textStyle: { color: axisTextColor },
  data: ["原材料不合格数", "过程不合格数", "出厂不合格数"],
};
const xAxis1 = ref([
  {
    type: "category",
    axisTick: { show: false },
    axisLine: { lineStyle: { color: axisLineColor } },
    axisLabel: { color: axisTextColor },
    data: [],
  },
]);
const yAxis1 = [
  {
    type: "value",
    splitLine: { lineStyle: { color: splitLineColor } },
    axisLine: { lineStyle: { color: axisLineColor } },
    axisLabel: { color: axisTextColor },
  },
];
const barSeries1 = ref([
  {
    name: '原材料不合格数',
    type: 'bar',
    name: "原材料不合格数",
    type: "bar",
    barGap: 0,
    emphasis: {
      focus: 'series'
    },
    data: []
    itemStyle: { color: "#2563eb", borderRadius: [6, 6, 0, 0] },
    emphasis: { focus: "series" },
    data: [],
  },
  {
    name: '过程不合格数',
    type: 'bar',
    emphasis: {
      focus: 'series'
    },
    data: []
    name: "过程不合格数",
    type: "bar",
    itemStyle: { color: "#14b8a6", borderRadius: [6, 6, 0, 0] },
    emphasis: { focus: "series" },
    data: [],
  },
  {
    name: '出厂不合格数',
    type: 'bar',
    emphasis: {
      focus: 'series'
    },
    data: []
    name: "出厂不合格数",
    type: "bar",
    itemStyle: { color: "#f59e0b", borderRadius: [6, 6, 0, 0] },
    emphasis: { focus: "series" },
    data: [],
  },
])
const chartStyle = {
  width: '100%',
  height: '100%' // è®¾ç½®å›¾è¡¨å®¹å™¨çš„高度
}
const chartStylePie = {
  width: '140%',
  height: '140%' // è®¾ç½®å›¾è¡¨å®¹å™¨çš„高度
}
const grid = {
  left: '3%',
  right: '4%',
  bottom: '3%',
  containLabel: true
}
const barLegend = {
  show: true,
  data: ['原材料不合格数', '过程不合格数', '出厂不合格数']
}
const barLegend1 = {
  show: true,
  data: ['预付账款', '应付账款', '预收账款', '应收账款']
}
]);
const lineLegend = {
  show: true,
  data: ['开票', '回款']
}
const tooltip = {
  trigger: 'axis',
  axisPointer: {
    type: 'shadow'
  }
}
const xAxis = [{
  type: 'value',
}]
const xAxis1 = ref([{
  type: 'category',
  axisTick: { show: false },
  data: []
}])
const yAxis = [{
  type: 'category',
  data: ['应付账款', '应收账款',]
}]
const yAxis1 = [{
  type: 'value'
}]
const pieTooltip = reactive({
  trigger: 'item',
  formatter: function (params) {
    // åŠ¨æ€ç”Ÿæˆæç¤ºä¿¡æ¯ï¼ŒåŸºäºŽæ•°æ®é¡¹çš„ name å±žæ€§
    const description = params.name === '本月回款金额' ? '本月回款金额' : '应收款金额';
    return `${description} ${formatNumber(params.value)}元 ${params.percent}%`;
  },
  position: 'right'
})
const materialPieSeries = ref([
  {
    type: 'pie',
    radius: ['66%', '90%'],
    avoidLabelOverlap: false,
    itemStyle: {
      borderColor: '#fff',
      borderWidth: 2
    },
    label: {
      show: false
    },
    data: []
  }
])
const lineSeries = ref([
  {
    type: 'line',
    data: [],
    label: {
      show: true
    },
    showSymbol: true, // æ˜¾ç¤ºåœ†ç‚¹
  },
])
const tooltipLine = {
  trigger: 'axis',
}
const yAxis2 = ref([
  {
    type: 'value',
  }
])
  textStyle: { color: axisTextColor },
  data: ["开票", "回款"],
};
const xAxis2 = ref([
  {
    type: 'category',
    type: "category",
    data: [],
    axisLine: { lineStyle: { color: axisLineColor } },
    axisLabel: {
      color: axisTextColor,
      interval: 0,
      formatter: function (value) {
        return value.replace(/~/g, '\n');
      },
    }
  }
])
// å¾…办事项
const todoList = ref([])
const radio1 = ref(1)
const qualityRange = ref(1)
// å›¾è¡¨å¼•用
const barChart = ref(null)
const lineChart = ref(null)
const barColors2 = ['#5181DB', '#D369E0', '#F2CA6D', '#60CCA8']
// éšæœºé¢œè‰²ç”Ÿæˆå‡½æ•°
const getRandomColor = () => {
  return '#' + Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0');
}
onMounted(() => {
  getBusinessData()
  analysisCustomer()
  todoInfoS()
  statisticsReceivable()
  qualityStatisticsInfo()
  getAmountHalfYearNum()
  getProcessList()
})
// æ•°æ®ç»Ÿè®¡
const getBusinessData = () => {
  getBusiness().then((res) => {
    businessInfo.value = { ...res.data }
  })
}
// åˆåŒé‡‘额
const analysisCustomer = () => {
  analysisCustomerContractAmounts().then((res) => {
    sum.value = res.data.sum
    yny.value = res.data.yny
    chain.value = res.data.chain
    // ä¸ºæ¯ä¸ªæ•°æ®é¡¹åˆ†é…éšæœºé¢œè‰²
    materialPieSeries.value[0].data = res.data.item.map(item => ({
      ...item,
      itemStyle: { color: getRandomColor() }
    }))
  })
}
// å¾…办事项
const todoInfoS = () => {
  homeTodos().then((res) => {
    todoList.value = res.data
  })
}
// èŽ·å–å·¥åºåˆ—è¡¨
const getProcessList = () => {
  list().then(res => {
    processOptions.value = res.data
  })
}
const openProcessDialog = () => {
  tempProcessIds.value = [...selectedProcessIds.value]
  processDialogVisible.value = true
}
const handleProcessDialogConfirm = () => {
  selectedProcessIds.value = [...tempProcessIds.value]
  processDialogVisible.value = false
  refreshProcessStats()
}
const resetProcessFilter = () => {
  selectedProcessIds.value = []
  tempProcessIds.value = []
  refreshProcessStats()
}
const handleChartClick = (params) => {
  if (params && params.dataIndex !== undefined) {
    activeProcessIndex.value = params.dataIndex
  }
}
// åº”付应收统计
const statisticsReceivable = () => {
  statisticsReceivablePayable({ type: radio1.value }).then((res) => {
    barSeries.value[0].data = [
      // { value: res.data.prepayMoney, itemStyle: { color: barColors2[0] } },
      { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } },
      // { value: res.data.advanceMoney, itemStyle: { color: barColors2[2] } },
      { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } }
    ]
  })
}
// è´¨æ£€ç»Ÿè®¡
const qualityStatisticsInfo = () => {
  qualityInspectionStatistics({ type: qualityRange.value }).then((res) => {
    xAxis1.value[0].data = []
    barSeries1.value[0].data = []
    barSeries1.value[1].data = []
    barSeries1.value[2].data = []
    res.data.item.forEach(item => {
      xAxis1.value[0].data.push(item.date)
      barSeries1.value[0].data.push(item.supplierNum)
      barSeries1.value[1].data.push(item.processNum)
      barSeries1.value[2].data.push(item.factoryNum)
    })
    qualityStatisticsObject.value.supplierNum = res.data.supplierNum
    qualityStatisticsObject.value.processNum = res.data.processNum
    qualityStatisticsObject.value.factoryNum = res.data.factoryNum
  })
}
const getAmountHalfYearNum = async () => {
  const res = await getAmountHalfYear()
  console.log(res)
  const monthName = []
  const receiptAmount = []
  const invoiceAmount = []
  res.data.forEach(item => {
    monthName.push(item.month)
    receiptAmount.push(item.receiptAmount)
    invoiceAmount.push(item.invoiceAmount)
  })
  // æ­£ç¡®å“åº”式赋值:创建新的 xAxis å’Œ series å¯¹è±¡
  xAxis2.value[0].data = monthName
  xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~'));
  lineSeries.value = [
    {
      name: '开票',
      type: 'line',
      data: invoiceAmount,
      stack: 'Total',
      areaStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          {
            offset: 0,
            color: 'rgba(131, 207, 255, 1)'
          },
          {
            offset: 1,
            color: 'rgba(186, 228, 255, 1)'
          }
        ])
      },
      itemStyle: {
        color: '#2D99FF',
        borderColor: '#2D99FF'
      },
      emphasis: {
        focus: 'series'
      },
      lineStyle: {
        width: 0
      },
      showSymbol: true,
      formatter: (value) => value.replace(/~/g, "\n"),
    },
    {
      name: '回款',
      type: 'line',
      data: receiptAmount,
      stack: 'Total',
      lineStyle: {
        width: 0
      },
      itemStyle: {
        color: '#83CFFF',
        borderColor: '#83CFFF'
      },
      showSymbol: true,
      areaStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          {
            offset: 0,
            color: 'rgba(54, 153, 255, 1)'
          },
          {
            offset: 1,
            color: 'rgba(89, 169, 254, 1)'
          }
        ])
      },
      emphasis: {
        focus: 'series'
      },
    }
  ]
}
  },
]);
// å·¥åºæ•°æ®ç”Ÿäº§ç»Ÿè®¡æ˜Žç»†ï¼ˆå‡æ•°æ® + å›¾è¡¨ï¼‰
const processRange = ref(1)
const processChartData = ref([])
const yAxis2 = ref([
  {
    type: "value",
    splitLine: { lineStyle: { color: splitLineColor } },
    axisLine: { lineStyle: { color: axisLineColor } },
    axisLabel: { color: axisTextColor },
  },
]);
const tooltipLine = {
  trigger: "axis",
  backgroundColor: "rgba(255, 255, 255, 0.97)",
  borderColor: "rgba(148, 163, 184, 0.26)",
  textStyle: { color: "#334155" },
};
const lineSeries = ref([
  {
    name: "开票",
    type: "line",
    data: [],
    smooth: true,
    itemStyle: { color: "#2563eb" },
    lineStyle: { width: 2, color: "#2563eb" },
    showSymbol: true,
    areaStyle: {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        { offset: 0, color: "rgba(37, 99, 235, 0.24)" },
        { offset: 1, color: "rgba(37, 99, 235, 0.02)" },
      ]),
    },
  },
  {
    name: "回款",
    type: "line",
    data: [],
    smooth: true,
    itemStyle: { color: "#14b8a6" },
    lineStyle: { width: 2, color: "#14b8a6" },
    showSymbol: true,
    areaStyle: {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        { offset: 0, color: "rgba(20, 184, 166, 0.2)" },
        { offset: 1, color: "rgba(20, 184, 166, 0.02)" },
      ]),
    },
  },
]);
const pieTooltip = reactive({
  trigger: "item",
  backgroundColor: "rgba(255, 255, 255, 0.97)",
  borderColor: "rgba(148, 163, 184, 0.26)",
  textStyle: { color: "#334155" },
  formatter: (params) => `${params.name} ${formatNumber(params.value)}元 ${params.percent}%`,
});
const materialPieSeries = ref([
  {
    type: "pie",
    radius: ["62%", "88%"],
    avoidLabelOverlap: false,
    itemStyle: {
      borderColor: "rgba(255, 255, 255, 0.95)",
      borderWidth: 2,
    },
    label: { show: false },
    data: [],
  },
]);
const todoList = ref([]);
const qualityRange = ref(1);
const processRange = ref(1);
const processChartData = ref([]);
const processXAxis = ref([
  {
    nameTextStyle: { color: 'rgba(0,0,0,0.35)', fontSize: 12 },
    axisLabel: { color: 'rgba(0,0,0,0.35)' },
    splitLine: { lineStyle: { color: 'rgba(0,0,0,0.06)', type: 'dashed' } },
    type: "value",
    axisLine: { lineStyle: { color: axisLineColor } },
    splitLine: { lineStyle: { color: splitLineColor, type: "dashed" } },
    axisLabel: { color: axisTextColor },
  },
])
]);
const processYAxis = ref([
  {
    type: 'category',
    type: "category",
    axisTick: { show: false },
    axisLine: { show: false },
    axisLabel: { color: 'rgba(0,0,0,0.45)' },
    axisLabel: { color: axisTextColor },
    data: [],
  },
])
]);
const processGrid = reactive({ left: 0, right: 100, top: 30, bottom: 20, containLabel: true })
const processGrid = reactive({ left: "4%", right: "4%", top: 20, bottom: 18, containLabel: true });
const processTooltip = reactive({
  trigger: 'axis',
  axisPointer: { type: 'shadow' },
  trigger: "axis",
  axisPointer: { type: "shadow" },
  backgroundColor: "rgba(255, 255, 255, 0.97)",
  borderColor: "rgba(148, 163, 184, 0.26)",
  textStyle: { color: "#334155" },
  formatter: (params) => {
    const name = params?.[0]?.name ?? ''
    const list = Array.isArray(params) ? params : []
    const name = params?.[0]?.name ?? "";
    const list = Array.isArray(params) ? params : [];
    const lines = list
      .map((p) => {
        const colorBox = `<span style="display:inline-block;margin-right:6px;border-radius:2px;width:10px;height:10px;background:${p.color}"></span>`
        return `${colorBox}${p.seriesName} <b style="float:right;">${Number(p.value || 0).toFixed(2)}</b>`
      })
      .join('<br/>')
    return `<div style="min-width:140px;"><div style="font-weight:700;margin-bottom:6px;">${name}</div>${lines}</div>`
        .map((p) => {
          const colorBox = `<span style="display:inline-block;margin-right:6px;border-radius:2px;width:10px;height:10px;background:${p.color}"></span>`;
          return `${colorBox}${p.seriesName}<b style="float:right;">${Number(p.value || 0).toFixed(2)}</b>`;
        })
        .join("<br/>");
    return `<div style="min-width:140px;"><div style="font-weight:700;margin-bottom:6px;">${name}</div>${lines}</div>`;
  },
})
});
const processSeries = computed(() => {
  const input = processChartData.value.map((i) => i.input)
  const scrap = processChartData.value.map((i) => i.scrap)
  const output = processChartData.value.map((i) => i.output)
  const input = processChartData.value.map((item) => item.input);
  const scrap = processChartData.value.map((item) => item.scrap);
  const output = processChartData.value.map((item) => item.output);
  return [
    {
      name: '投入量',
      type: 'bar',
      stack: 'total',
      barWidth: 22,
      itemStyle: { color: '#1E5BFF', borderRadius: [6, 0, 0, 6] },
      name: "投入量",
      type: "bar",
      stack: "total",
      barWidth: 18,
      itemStyle: { color: "#2563eb", borderRadius: [8, 0, 0, 8] },
      data: input,
    },
    {
      name: '报废量',
      type: 'bar',
      stack: 'total',
      barWidth: 22,
      itemStyle: { color: '#F7B500' },
      name: "报废量",
      type: "bar",
      stack: "total",
      barWidth: 18,
      itemStyle: { color: "#f59e0b" },
      data: scrap,
    },
    {
      name: '产出量',
      type: 'bar',
      stack: 'total',
      barWidth: 22,
      itemStyle: { color: '#19C6C6', borderRadius: [0, 6, 6, 0] },
      name: "产出量",
      type: "bar",
      stack: "total",
      barWidth: 18,
      itemStyle: { color: "#14b8a6", borderRadius: [0, 8, 8, 0] },
      data: output,
    },
  ]
})
  ];
});
const processAside = computed(() => {
  const list = processChartData.value
  const item = list[activeProcessIndex.value] || {}
  const listData = processChartData.value;
  const item = listData[activeProcessIndex.value] || {};
  return {
    processName: item.name || '暂无数据',
    processName: item.name || "暂无数据",
    totalInput: item.input || 0,
    totalScrap: item.scrap || 0,
    totalOutput: item.output || 0,
  };
});
const processTotals = computed(() =>
    processChartData.value.reduce(
        (acc, cur) => {
          acc.input += Number(cur.input || 0);
          acc.scrap += Number(cur.scrap || 0);
          acc.output += Number(cur.output || 0);
          return acc;
        },
        { input: 0, scrap: 0, output: 0 }
    )
);
const hasProcessData = computed(() => {
  if (!processChartData.value.length) return false;
  return processChartData.value.some((item) => {
    const input = Number(item.input || 0);
    const scrap = Number(item.scrap || 0);
    const output = Number(item.output || 0);
    return input > 0 || scrap > 0 || output > 0;
  });
});
const dashboardCards = computed(() => [
  {
    key: "sales",
    title: "销售数据",
    desc: "本月销售额(元)",
    value: formatNumber(businessInfo.value.monthSaleMoney),
    subLabel: "未开票金额",
    subValue: formatNumber(businessInfo.value.monthSaleHaveMoney),
    trend: `占比 ${ratioText(businessInfo.value.monthSaleHaveMoney, businessInfo.value.monthSaleMoney)}`,
    icon: DataLine,
    visible: visibleModules.value.sales,
  },
  {
    key: "purchase",
    title: "采购数据",
    desc: "本月采购额(元)",
    value: formatNumber(businessInfo.value.monthPurchaseMoney),
    subLabel: "待付款金额",
    subValue: formatNumber(businessInfo.value.monthPurchaseHaveMoney),
    trend: `占比 ${ratioText(
        businessInfo.value.monthPurchaseHaveMoney,
        businessInfo.value.monthPurchaseMoney
    )}`,
    icon: ShoppingCartFull,
    visible: visibleModules.value.procurement,
  },
  {
    key: "inventory",
    title: "库存数据",
    desc: "当前库存总量(ä»¶)",
    value: formatNumber(businessInfo.value.inventoryNum),
    subLabel: "今日入库",
    subValue: formatNumber(businessInfo.value.todayInventoryNum),
    trend: "库存结构持续优化",
    icon: Box,
    visible: visibleModules.value.inventory,
  },
  {
    key: "production",
    title: "生产总览",
    desc: "累计产出(ä»¶)",
    value: formatNumber(productionOverviewData.value.totalOutput),
    subLabel: "累计报废",
    subValue: formatNumber(productionOverviewData.value.totalScrap),
    trend: `良率 ${Number(productionOverviewData.value.yieldRate || 0).toFixed(2)}%`,
    icon: Operation,
    visible: visibleModules.value.production,
  },
].filter((item) => item.visible));
const productionOrders = ref([]);
const orderFilterOptions = ["all", "waiting", "inProgress", "completed", "paused"];
const orderFilterAliasMap = {
  1: "waiting",
  2: "inProgress",
  3: "completed",
  4: "paused",
};
const orderFilter = ref("all");
const filteredOrders = computed(() => productionOrders.value);
const normalizeOrderFilter = (value, fallback = "all") => {
  const safeFallback = orderFilterOptions.includes(fallback) ? fallback : "all";
  const text = String(value ?? "").trim();
  if (orderFilterAliasMap[text]) {
    return orderFilterAliasMap[text];
  }
})
  return orderFilterOptions.includes(text) ? text : safeFallback;
};
const formatAmount = (n) => {
  const num = Number(n || 0)
  return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}
const parseCount = (value) => {
  if (value === null || value === undefined || value === "") return null;
  const num = Number(value);
  return Number.isFinite(num) ? num : null;
};
const refreshProcessStats = () => {
  processDataProductionStatistics({
const resolveProgressCount = (rawValue, currentStatus, targetStatus, total) => {
  const count = parseCount(rawValue);
  if (count !== null) return count;
  return currentStatus === targetStatus ? total : 0;
};
const getCompareTrend = (value) => {
  const num = Number(value || 0);
  if (num > 0) return "up";
  if (num < 0) return "down";
  return "flat";
};
const getCompareText = (value) => {
  const num = Number(value || 0);
  const abs = Math.abs(num).toFixed(2);
  if (num > 0) return `较昨日 â†‘ ${abs}%`;
  if (num < 0) return `较昨日 â†“ ${abs}%`;
  return "较昨日 æŒå¹³";
};
const realtimeBoard = computed(() => {
  const oee = Number(realtimeBoardData.value.deviceOee?.value || 0);
  const orderAchievement = Number(realtimeBoardData.value.orderAchievementRate?.value || 0);
  const defectRate = Number(realtimeBoardData.value.defectRate?.value || 0);
  const oeeCompare = Number(realtimeBoardData.value.deviceOee?.compareYesterday || 0);
  const orderCompare = Number(realtimeBoardData.value.orderAchievementRate?.compareYesterday || 0);
  const defectCompare = Number(realtimeBoardData.value.defectRate?.compareYesterday || 0);
  return [
    {
      key: "oee",
      label: "设备 OEE",
      percent: clampPercent(oee),
      display: `${oee.toFixed(2)}%`,
      delta: getCompareText(oeeCompare),
      trend: getCompareTrend(oeeCompare),
      color: "#2d8cff",
    },
    {
      key: "order",
      label: "订单达成率",
      percent: clampPercent(orderAchievement),
      display: `${orderAchievement.toFixed(2)}%`,
      delta: getCompareText(orderCompare),
      trend: getCompareTrend(orderCompare),
      color: "#31d2ff",
    },
    {
      key: "defect",
      label: "不良率",
      percent: clampPercent(defectRate),
      display: `${defectRate.toFixed(2)}%`,
      delta: getCompareText(defectCompare),
      trend: getCompareTrend(defectCompare),
      color: "#f6a23f",
    },
  ];
});
const warningList = ref([
  {
    id: 1,
    level: "device",
    title: "设备预警",
    desc: "CNC-001 è®¾å¤‡æŒ¯åЍ异叏",
    time: "10:24:32",
  },
  {
    id: 2,
    level: "quality",
    title: "质量预警",
    desc: "订单 SO-20260517 ä¸è‰¯çŽ‡è¶…æ ‡",
    time: "09:15:47",
  },
  {
    id: 3,
    level: "material",
    title: "物料预警",
    desc: "物料 1002001 åº“存不足",
    time: "08:47:21",
  },
]);
const quickEntryConfigs = [
  { label: "主生产计划", icon: Calendar, titles: ["主生产计划"], fallbackPath: "/productionPlan/productionPlan" },
  { label: "生产订单", icon: Tickets, titles: ["生产订单"], fallbackPath: "/productionManagement/productionOrder" },
  { label: "生产报工", icon: EditPen, titles: ["生产报工"], fallbackPath: "/productionManagement/productionReporting" },
  { label: "设备台账", icon: Tools, titles: ["设备台账"], fallbackPath: "/equipmentManagement/ledger" },
  { label: "销售台账", icon: DataLine, titles: ["销售台账"], fallbackPath: "/salesManagement/salesLedger" },
  { label: "采购台账", icon: ShoppingCartFull, titles: ["采购台账"], fallbackPath: "/procurementManagement/procurementLedger" },
  { label: "员工台账", icon: UserFilled, titles: ["员工台账", "在职员工台账"], fallbackPath: "/personnelManagement/employeeRecord" },
  { label: "库存管理", icon: Box, titles: ["库存管理"], fallbackPath: "/inventoryManagement/stockManage" },
];
const normalizeMenuTitle = (title) => String(title || "").replace(/\s+/g, "").trim();
const normalizeRoutePath = (path) =>
    String(path || "")
        .trim()
        .replace(/\/+/g, "/")
        .replace(/\/$/, "")
        .toLowerCase();
const resolveRoutePath = (route, parentPath = "") => {
  const currentPath = String(route?.path || "").trim();
  if (!currentPath) return parentPath || "";
  if (/^(https?:)?\/\//.test(currentPath)) return currentPath;
  if (currentPath.startsWith("/")) return currentPath;
  const basePath = parentPath && parentPath !== "/" ? parentPath.replace(/\/$/, "") : "";
  return `${basePath}/${currentPath}`.replace(/\/+/g, "/");
};
const collectAccessibleRoutes = (routes = [], parentPath = "") => {
  const items = [];
  (routes || []).forEach((route) => {
    if (!route) return;
    const fullPath = resolveRoutePath(route, parentPath);
    const title = route.meta?.title ?? route.title ?? "";
    if (title && fullPath && !String(route.redirect || "").includes("noRedirect")) {
      items.push({
        title: normalizeMenuTitle(title),
        path: normalizeRoutePath(fullPath),
      });
    }
    if (Array.isArray(route.children) && route.children.length > 0) {
      items.push(...collectAccessibleRoutes(route.children, fullPath));
    }
  });
  return items;
};
const accessibleMenuRoutes = computed(() => {
  const routePool =
      permissionStore.defaultRoutes?.length > 0
          ? permissionStore.defaultRoutes
          : permissionStore.sidebarRouters?.length > 0
              ? permissionStore.sidebarRouters
              : permissionStore.routes;
  return collectAccessibleRoutes(routePool || []);
});
const moduleAccessConfig = {
  sales: {
    titles: ["销售管理", "销售台账"],
    pathPrefixes: ["/salesmanagement"],
  },
  procurement: {
    titles: ["采购管理", "采购台账"],
    pathPrefixes: ["/procurementmanagement"],
  },
  inventory: {
    titles: ["库存管理"],
    pathPrefixes: ["/inventorymanagement"],
  },
  production: {
    titles: ["生产管理", "主生产计划", "生产订单", "生产报工"],
    pathPrefixes: ["/productionmanagement", "/productionplan"],
  },
  quality: {
    titles: ["质量管理"],
    pathPrefixes: ["/qualitymanagement"],
  },
  equipment: {
    titles: ["设备管理", "设备台账"],
    pathPrefixes: ["/equipmentmanagement"],
  },
  personnel: {
    titles: ["人事管理", "员工台账", "在职员工台账"],
    pathPrefixes: ["/personnelmanagement"],
  },
  approval: {
    titles: ["协同审批", "待办事项"],
    pathPrefixes: ["/collaborativeapproval"],
  },
  finance: {
    titles: ["财务管理", "财务分析", "回款管理", "开票管理"],
    pathPrefixes: ["/financesuite", "/financialmanagement"],
  },
};
const hasModuleAccess = (config) =>
    accessibleMenuRoutes.value.some((route) => {
      const matchedTitle = (config.titles || []).some((title) => route.title === normalizeMenuTitle(title));
      const matchedPath = (config.pathPrefixes || []).some(
          (prefix) => route.path === prefix || route.path.startsWith(`${prefix}/`)
      );
      return matchedTitle || matchedPath;
    });
const visibleModules = computed(() => ({
  sales: hasModuleAccess(moduleAccessConfig.sales),
  procurement: hasModuleAccess(moduleAccessConfig.procurement),
  inventory: hasModuleAccess(moduleAccessConfig.inventory),
  production: hasModuleAccess(moduleAccessConfig.production),
  quality: hasModuleAccess(moduleAccessConfig.quality),
  equipment: hasModuleAccess(moduleAccessConfig.equipment),
  personnel: hasModuleAccess(moduleAccessConfig.personnel),
  approval: hasModuleAccess(moduleAccessConfig.approval),
  finance: hasModuleAccess(moduleAccessConfig.finance),
}));
const visiblePanels = computed(() => ({
  process: visibleModules.value.production,
  order: visibleModules.value.production,
  contract: visibleModules.value.sales,
  quality: visibleModules.value.quality,
  todo: visibleModules.value.approval,
  realtime: visibleModules.value.production,
  quick: quickEntries.value.length > 0,
  plan: visibleModules.value.production,
  receipt: visibleModules.value.sales || visibleModules.value.finance,
}));
const hasLeftPanels = computed(
    () => visiblePanels.value.process || visiblePanels.value.order || visiblePanels.value.contract || visiblePanels.value.quality
);
const hasRightPanels = computed(
    () => visiblePanels.value.todo || visiblePanels.value.realtime || visiblePanels.value.quick || visiblePanels.value.plan || visiblePanels.value.receipt
);
const hasVisiblePanels = computed(() => hasLeftPanels.value || hasRightPanels.value);
const quickEntries = computed(() =>
    quickEntryConfigs
        .map((item) => {
          const targetRoute = accessibleMenuRoutes.value.find((route) =>
              item.titles.some((title) => route.title === normalizeMenuTitle(title))
          );
          const resolvedPath = targetRoute?.path || "";
          return resolvedPath
              ? {
                label: item.label,
                icon: item.icon,
                path: resolvedPath,
              }
              : null;
        })
        .filter(Boolean)
);
const updateNowTime = () => {
  nowTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
};
const formatNumber = (value) => {
  const num = Number(value || 0);
  return num.toLocaleString(undefined, {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });
};
const formatAmount = (value) => {
  const num = Number(value || 0);
  return num.toLocaleString(undefined, {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });
};
const trendText = (value) => {
  const num = Number(value || 0);
  const flag = num >= 0 ? "↑" : "↓";
  return `${flag} ${Math.abs(num).toFixed(1)}%`;
};
const ratioNumber = (numerator, denominator) => {
  const n = Number(numerator || 0);
  const d = Number(denominator || 0);
  if (!d) return 0;
  return (n / d) * 100;
};
const ratioText = (numerator, denominator) => `${ratioNumber(numerator, denominator).toFixed(1)}%`;
const clampPercent = (val) => Math.max(0, Math.min(100, Number(val || 0)));
const getOrderStatusText = (status) => {
  const mapping = {
    1: "待开始",
    2: "进行中",
    3: "已完成",
    4: "已暂停",
  };
  return mapping[status] || "未知";
};
const getOrderStatusType = (status) => {
  const mapping = {
    1: "info",
    2: "success",
    3: "primary",
    4: "warning",
  };
  return mapping[status] || "info";
};
const formatDueDate = (value) => {
  if (!value) return "--";
  const date = dayjs(value);
  return date.isValid() ? date.format("YYYY-MM-DD") : "--";
};
const mapOrderProgressRecord = (item = {}) => ({
  orderNo: item.orderNo || "--",
  productName: item.productName || "--",
  planQty: Number(item.plannedQuantity || 0),
  completedQty: Number(item.completedQuantity || 0),
  completionRate: clampPercent(Number(item.completionRate || 0)),
  deliveryDate: formatDueDate(item.dueDate),
  status: Number(item.status || 0),
  statusLabel: item.statusLabel || "",
});
const mapTodayPlanRecord = (item = {}) => ({
  orderNo: item.orderNo || "--",
  productName: item.productName || "--",
  planQty: Number(item.plannedQuantity || 0),
  deliveryDate: formatDueDate(item.dueDate),
  status: Number(item.status || 0),
  statusLabel: item.statusLabel || "",
});
const refreshProductionOverview = async () => {
  try {
    const res = await productionOverview();
    const data = res?.data || {};
    productionOverviewData.value = {
      totalOutput: Number(data.totalOutput || 0),
      totalScrap: Number(data.totalScrap || 0),
      yieldRate: Number(data.yieldRate || 0),
    };
  } catch {
    productionOverviewData.value = {
      totalOutput: 0,
      totalScrap: 0,
      yieldRate: 0,
    };
  }
};
const refreshProductionRealtimeBoard = async () => {
  try {
    const res = await productionRealtimeBoard();
    const data = res?.data || {};
    realtimeBoardData.value = {
      deviceOee: {
        value: Number(data.deviceOee?.value || 0),
        compareYesterday: Number(data.deviceOee?.compareYesterday || 0),
      },
      orderAchievementRate: {
        value: Number(data.orderAchievementRate?.value || 0),
        compareYesterday: Number(data.orderAchievementRate?.compareYesterday || 0),
      },
      defectRate: {
        value: Number(data.defectRate?.value || 0),
        compareYesterday: Number(data.defectRate?.compareYesterday || 0),
      },
    };
  } catch {
    realtimeBoardData.value = {
      deviceOee: { value: 0, compareYesterday: 0 },
      orderAchievementRate: { value: 0, compareYesterday: 0 },
      defectRate: { value: 0, compareYesterday: 0 },
    };
  }
};
const refreshProductionOrderProgress = async () => {
  try {
    const res = await productionOrderProgress({
      status: orderFilter.value,
      tab: orderFilter.value,
      pageNum: 1,
      pageSize: 10,
    });
    const data = res?.data || {};
    const statusValue = normalizeOrderFilter(data.status, orderFilter.value);
    const total = Number(data.total || 0);
    orderProgressMeta.value = {
      status: statusValue,
      tab: data.tab || orderFilter.value,
      bizDate: data.bizDate || null,
      total,
      pageNum: Number(data.pageNum || 1),
      pageSize: Number(data.pageSize || 10),
      waitingCount: resolveProgressCount(data.waitingCount, statusValue, "waiting", total),
      inProgressCount: resolveProgressCount(data.inProgressCount, statusValue, "inProgress", total),
      completedCount: resolveProgressCount(data.completedCount, statusValue, "completed", total),
      pausedCount: resolveProgressCount(data.pausedCount, statusValue, "paused", total),
    };
    productionOrders.value = (data.records || []).map(mapOrderProgressRecord);
  } catch {
    orderProgressMeta.value = {
      status: orderFilter.value,
      tab: orderFilter.value,
      bizDate: null,
      total: 0,
      pageNum: 1,
      pageSize: 10,
      waitingCount: 0,
      inProgressCount: 0,
      completedCount: 0,
      pausedCount: 0,
    };
    productionOrders.value = [];
  }
};
const refreshTodayProductionPlan = async () => {
  try {
    const res = await todayProductionPlan({
      limit: 4,
      planDate: nowDate.value,
    });
    const data = res?.data || {};
    todayPlanTotal.value = Number(data.total || 0);
    todayPlanList.value = (data.records || []).map(mapTodayPlanRecord);
  } catch {
    todayPlanTotal.value = 0;
    todayPlanList.value = [];
  }
};
const getBusinessData = async () => {
  const res = await getBusiness();
  businessInfo.value = { ...res.data };
};
const analysisCustomer = async () => {
  const res = await analysisCustomerContractAmounts();
  sum.value = res.data.sum;
  yny.value = res.data.yny;
  chain.value = res.data.chain;
  materialPieSeries.value[0].data = (res.data.item || []).map((item, index) => ({
    ...item,
    rate: Number(item.rate || 0),
    itemStyle: { color: piePalette[index % piePalette.length] },
  }));
};
const todoInfoS = async () => {
  const res = await homeTodos();
  todoList.value = res.data || [];
};
const statisticsReceivable = async () => {
  const res = await statisticsReceivablePayable({ type: 1 });
  barSeries.value[0].data = [
    { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } },
    { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } },
  ];
};
const qualityStatisticsInfo = async () => {
  const res = await qualityInspectionStatistics({ type: qualityRange.value });
  xAxis1.value[0].data = [];
  barSeries1.value[0].data = [];
  barSeries1.value[1].data = [];
  barSeries1.value[2].data = [];
  (res.data.item || []).forEach((item) => {
    xAxis1.value[0].data.push(item.date);
    barSeries1.value[0].data.push(item.supplierNum);
    barSeries1.value[1].data.push(item.processNum);
    barSeries1.value[2].data.push(item.factoryNum);
  });
  qualityStatisticsObject.value.supplierNum = res.data.supplierNum;
  qualityStatisticsObject.value.processNum = res.data.processNum;
  qualityStatisticsObject.value.factoryNum = res.data.factoryNum;
};
const getAmountHalfYearNum = async () => {
  const res = await getAmountHalfYear();
  const monthName = [];
  const receiptAmount = [];
  const invoiceAmount = [];
  (res.data || []).forEach((item) => {
    monthName.push(item.month);
    receiptAmount.push(item.receiptAmount);
    invoiceAmount.push(item.invoiceAmount);
  });
  xAxis2.value[0].data = monthName.map((item) => item.replace(/~/g, "\n~"));
  lineSeries.value[0].data = invoiceAmount;
  lineSeries.value[1].data = receiptAmount;
};
const getProcessList = async () => {
  const res = await list();
  processOptions.value = res.data.records || [];
};
const refreshProcessStats = async () => {
  const res = await processDataProductionStatistics({
    type: processRange.value,
    processIds: selectedProcessIds.value.length > 0 ? selectedProcessIds.value.join(',') : null
  }).then(res => {
    processChartData.value = res.data.map(item => ({
      name: item.processName,
      input: item.totalInput,
      scrap: item.totalScrap,
      output: item.totalOutput
    }))
    processYAxis.value[0].data = processChartData.value.map((i) => i.name)
    activeProcessIndex.value = 0
  })
}
    processIds: selectedProcessIds.value.length > 0 ? selectedProcessIds.value.join(",") : null,
  });
  processChartData.value = (res.data || []).map((item) => ({
    name: item.processName,
    input: item.totalInput,
    scrap: item.totalScrap,
    output: item.totalOutput,
  }));
  processYAxis.value[0].data = processChartData.value.map((item) => item.name);
  activeProcessIndex.value = 0;
};
const openProcessDialog = () => {
  tempProcessIds.value = [...selectedProcessIds.value];
  processDialogVisible.value = true;
};
const handleProcessDialogConfirm = () => {
  selectedProcessIds.value = [...tempProcessIds.value];
  processDialogVisible.value = false;
  refreshProcessStats();
};
const resetProcessFilter = () => {
  selectedProcessIds.value = [];
  tempProcessIds.value = [];
  refreshProcessStats();
};
const handleChartClick = (params) => {
  if (params && params.dataIndex !== undefined) {
    activeProcessIndex.value = params.dataIndex;
  }
};
const goToQuick = (path) => {
  if (!path) return;
  router.push(path).catch(() => {});
};
watch(orderFilter, () => {
  if (visiblePanels.value.order) {
    refreshProductionOrderProgress();
  }
});
onMounted(() => {
  getBusinessData()
  analysisCustomer()
  todoInfoS()
  statisticsReceivable()
  qualityStatisticsInfo()
  getAmountHalfYearNum()
  refreshProcessStats()
})
  updateNowTime();
  clockTimer = setInterval(updateNowTime, 1000);
  if (dashboardCards.value.length > 0) {
    getBusinessData();
  }
  if (visibleModules.value.production) {
    refreshProductionOverview();
  }
  if (visiblePanels.value.contract) {
    analysisCustomer();
  }
  if (visiblePanels.value.todo) {
    todoInfoS();
  }
  if (visiblePanels.value.quality) {
    qualityStatisticsInfo();
  }
  if (visiblePanels.value.receipt) {
    statisticsReceivable();
    getAmountHalfYearNum();
  }
  if (visiblePanels.value.process) {
    getProcessList();
    refreshProcessStats();
  }
  if (visiblePanels.value.order) {
    refreshProductionOrderProgress();
  }
  if (visiblePanels.value.realtime) {
    refreshProductionRealtimeBoard();
  }
  if (visiblePanels.value.plan) {
    refreshTodayProductionPlan();
  }
});
onUnmounted(() => {
  if (clockTimer) {
    clearInterval(clockTimer);
  }
});
</script>
<style scoped>
.dashboard {
  min-height: 100vh;
  padding: 20px;
  box-sizing: border-box;
}
.dashboard-top {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  align-items: flex-start;
  justify-content: space-evenly;
}
.company-info {
.dashboard-cockpit {
  min-height: calc(100vh - var(--topbar-height) - var(--tagsbar-height));
  width: 100%;
  min-width: 0;
  padding: 0;
  overflow: hidden;
  border-radius: 12px;
  background: #fff;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow-x: clip;
  margin-top: 10px;
}
.welcome-banner {
  padding: 10px 10px;
  background: linear-gradient(135deg, rgba(229, 240, 255, 0.9), rgba(214, 232, 255, 0.7), rgba(207, 236, 255, 0.9));
.digital-number {
  font-family: "DIN Alternate Bold", "Segoe UI", "PingFang SC", sans-serif;
  letter-spacing: 0;
}
.welcome-title {
  font-size: 18px;
  font-weight: 700;
  color: #222;
  line-height: 1.3;
.cockpit-panel {
  position: relative;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(148, 163, 184, 0.18);
  border-radius: 16px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.06);
  backdrop-filter: blur(12px);
  padding: 16px;
}
.welcome-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 92px;
  padding: 18px 22px;
  background:
      radial-gradient(circle at 8% 20%, rgba(59, 130, 246, 0.12), transparent 32%),
      linear-gradient(135deg, rgba(255, 255, 255, 0.94), rgba(239, 246, 255, 0.88));
}
.welcome-user {
  margin-right: 6px;
}
.welcome-time {
  margin-top: 10px;
  font-size: 16px;
  color: rgba(0, 0, 0, 0.55);
}
.user-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px 22px;
}
.user-card-main {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}
.user-name {
  font-size: 16px;
  font-weight: bold;
  color: #111;
  letter-spacing: 1px;
}
.user-role {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 20px;
  padding: 5px 10px;
  background: rgba(245, 246, 248, 1);
  color: #333;
  width: fit-content;
  font-weight: 600;
}
.user-meta {
  font-size: 12px;
  color: rgba(0, 0, 0, 0.55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-meta .sep {
  margin: 0 10px;
  color: rgba(0, 0, 0, 0.25);
  gap: 12px;
}
.avatar {
  width: 90px;
  height: 90px;
  border-radius: 50%;
  width: 52px;
  height: 52px;
  border: 1px solid rgba(147, 197, 253, 0.42);
  background: linear-gradient(145deg, #ffffff, #eef5ff);
  box-shadow: 0 8px 20px rgba(37, 99, 235, 0.14);
}
.avatar :deep(img) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  flex: 0 0 auto;
}
.data-cards {
  width: 50%;
  display: flex;
  gap: 16px;
  justify-content: flex-start;
  background: #ffffff;
  border-radius: 12px;
  padding: 20px;
.avatar :deep(.el-icon) {
  font-size: 24px;
  color: #3b82f6;
}
.data-title {
.welcome-title {
  font-size: 28px;
  font-weight: 700;
  font-size: 26px;
  color: #FFFFFF;
  color: #1e3a5f;
  line-height: 1.08;
}
.data-num {
.welcome-subtitle {
  margin-top: 6px;
  color: #64748b;
  font-size: 14px;
}
.welcome-meta {
  text-align: right;
}
.meta-time {
  font-size: 28px;
  color: #1f3658;
  font-weight: 700;
}
.meta-extra {
  margin-top: 6px;
  display: flex;
  justify-content: flex-end;
  gap: 14px;
  color: #64748b;
  font-size: 13px;
}
.meta-tip {
  margin-top: 4px;
  color: #7a8ca6;
  font-size: 13px;
}
.top-row {
  display: block;
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}
.stat-card {
  position: relative;
  border-radius: 18px;
  padding: 18px 20px 22px;
  min-height: 182px;
  height: auto;
  overflow: hidden;
  border: 1px solid rgba(148, 163, 184, 0.2);
  box-shadow: 0 10px 26px rgba(15, 23, 42, 0.06);
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.stat-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 18px 40px rgba(37, 99, 235, 0.1);
}
.stat-card.sales {
  background: linear-gradient(135deg, #ffffff 0%, #eaf3ff 100%);
}
.stat-card.purchase {
  background: linear-gradient(135deg, #ffffff 0%, #e8fffb 100%);
}
.stat-card.inventory {
  background: linear-gradient(135deg, #ffffff 0%, #f2edff 100%);
}
.stat-card.production {
  background: linear-gradient(135deg, #ffffff 0%, #fff4e6 100%);
}
.stat-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  position: relative;
  z-index: 2;
}
.stat-title {
  font-size: 16px;
  font-weight: 700;
}
.stat-card.sales .stat-title {
  color: #1d4ed8;
}
.stat-card.purchase .stat-title {
  color: #0f766e;
}
.stat-card.inventory .stat-title {
  color: #6d28d9;
}
.stat-card.production .stat-title {
  color: #c2410c;
}
.stat-desc {
  margin-top: 6px;
  color: #64748b;
  font-size: 13px;
}
.stat-icon-orb {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 20px;
  justify-content: center;
  font-size: 22px;
  color: #fff;
}
.data-card {
  background: #fff;
  border-radius: 12px;
  padding: 14px 10px 10px 10px;
  min-width: 160px;
  box-shadow: 0 2px 8px #eee;
  display: flex;
  flex-direction: column;
  width: 32%;
  height: 140px;
.stat-card.sales .stat-icon-orb {
  background: linear-gradient(135deg, #2563eb, #60a5fa);
  box-shadow: 0 10px 24px rgba(37, 99, 235, 0.32);
}
.data-card.sales {
  background-image: url("../assets/images/xioashoushuju.png");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
.stat-card.purchase .stat-icon-orb {
  background: linear-gradient(135deg, #14b8a6, #5eead4);
  box-shadow: 0 10px 24px rgba(20, 184, 166, 0.3);
}
.data-card.purchase {
  background-image: url("../assets/images/caigou.png");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
.stat-card.inventory .stat-icon-orb {
  background: linear-gradient(135deg, #7c3aed, #a78bfa);
  box-shadow: 0 10px 24px rgba(124, 58, 237, 0.28);
}
.data-card.inventory {
  background-image: url("../assets/images/kucun.png");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
.stat-card.production .stat-icon-orb {
  background: linear-gradient(135deg, #f97316, #fdba74);
  box-shadow: 0 10px 24px rgba(249, 115, 22, 0.3);
}
.data-desc {
  font-weight: 500;
.stat-value {
  margin-top: 14px;
  font-size: 30px;
  line-height: 1.08;
  font-weight: 700;
  color: #0f172a;
  position: relative;
  z-index: 2;
}
.stat-footer {
  margin-top: 8px;
  color: #64748b;
  font-size: 13px;
  color: #FFFFFF;
}
.data-value {
  font-size: 18px;
  font-weight: 500;
  margin: 10px 0;
  color: #FFFFFF;
}
.top-left {
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 180px;
  width: 20%;
  justify-content: space-between;
  align-items: center;
  position: relative;
  z-index: 2;
}
.stat-trend {
  margin-top: 6px;
  color: #0ea5a4;
  font-size: 13px;
  line-height: 1.25;
  font-weight: 600;
  position: relative;
  z-index: 2;
}
.stat-wave {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 6px;
  height: 30px;
  opacity: 0.62;
  z-index: 1;
  pointer-events: none;
  background:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 340 40' preserveAspectRatio='none'%3E%3Cpath d='M0 31C20 16 44 36 66 24C87 12 107 31 129 18C148 8 169 28 193 16C214 5 237 25 259 14C280 3 306 19 340 8' fill='none' stroke='%236ea4ee' stroke-width='1.5'/%3E%3C/svg%3E")
      center / 100% 100% no-repeat;
}
.todo-panel {
  background: #fff;
  border-radius: 12px;
  padding: 20px;
  height: 180px;
  width: 30%;
  padding: 12px;
}
.panel-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.panel-title {
  font-size: 18px;
  font-weight: 700;
  color: #1f3658;
  position: relative;
  padding-left: 12px;
}
.panel-title::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 18px;
  border-radius: 4px;
  background: linear-gradient(180deg, #2563eb, #38bdf8);
}
.panel-more {
  font-size: 14px;
  color: #2563eb;
  cursor: pointer;
}
.todo-list {
  height: 100px;
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  margin: 0;
  font-size: 15px;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 230px;
  overflow-y: auto;
}
.todo-list li {
  border-radius: 8px;
  margin-bottom: 12px;
  padding: 8px 20px;
  height: 74px;
.todo-item {
  border: 1px solid rgba(148, 163, 184, 0.2);
  border-radius: 12px;
  background: #f7fbff;
  padding: 10px 12px;
}
.todo-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: rgba(225, 227, 250, 0.62);
}
.todo-title {
  font-weight: 400;
  font-size: 12px;
  color: #000000;
  position: relative;
}
.todo-title::before {
  content: '';
  /* å¿…需,表示这里有一个内容 */
  position: absolute;
  left: -10px;
  /* å®šä½åˆ°å·¦ä¾§ */
  top: 50%;
  /* åž‚直居中 */
  transform: translateY(-50%);
  /* å¾®è°ƒåž‚直居中 */
  width: 6px;
  /* åœ†çš„直径 */
  height: 6px;
  /* åœ†çš„直径 */
  background: #498CEB;
  border-radius: 50%;
  /* è®©å…¶å˜æˆåœ†å½¢ */
}
.todo-division {
  font-weight: 400;
  font-size: 12px;
  color: #000000;
}
.todo-time {
  font-weight: 400;
  font-size: 12px;
  color: #000000;
}
.todo-meta {
  color: #888;
  gap: 10px;
  color: #334155;
  font-size: 13px;
}
.dashboard-row {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}
.main-panel {
  background: #fff;
  border-radius: 12px;
  padding: 20px;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.section-title {
  position: relative;
  font-size: 18px;
  color: #333;
  padding-left: 10px;
  margin-bottom: 10px;
  font-weight: 700;
}
.section-title::before {
  position: absolute;
  left: 0;
  top: 4px;
  content: '';
  width: 4px;
  height: 18px;
  background-color: #002FA7;
  border-radius: 2px;
}
.contract-info {
  display: flex;
  align-items: center;
  gap: 20px;
  height: 90px;
  background: rgba(245, 245, 245, 0.59);
  width: 100%;
  border-radius: 10px;
  padding: 10px 30px;
}
.contract-summary {
  display: flex;
  align-items: center;
  gap: 30px;
}
.contract-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.contract-name {
  font-weight: 400;
  font-size: 14px;
  color: #050505;
}
.contract-meta {
  display: flex;
  align-items: center;
  width: 100%;
  gap: 80px;
}
.main-amount {
  font-size: 24px;
  color: rgba(51, 50, 50, 0.85);
}
.up {
  color: #e57373;
}
.contract-list {
  margin-top: 16px;
  font-size: 14px;
  color: #666;
  list-style: none;
  padding: 0;
  height: 190px;
  overflow-y: auto;
  width: 460px;
}
.line {
  position: relative;
  width: 230px;
}
.line::after {
  content: '';
  position: absolute;
  right: 2px;
  top: 0;
  bottom: 0;
  width: 1px;
  background-color: #C9C5C5;
  border-radius: 2px;
}
.contract-list li {
  margin-top: 10px;
}
.quality-cards {
  display: flex;
  gap: 12px;
  margin-bottom: 12px;
}
.quality-card {
  border-radius: 8px;
  padding: 15px 10px 10px 50px;
  font-weight: 400;
.todo-desc {
  margin-top: 6px;
  color: #64748b;
  font-size: 12px;
  color: rgba(0, 0, 0, 0.67);
  width: 236px;
  height: 49px;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  line-height: 1.45;
}
.quality-card.one {
  background-image: url("../assets/images/yuancailiao.png");
.todo-no {
  color: #1f3658;
  font-weight: 600;
}
.quality-card.two {
  background-image: url("../assets/images/guocheng.png");
.panel-empty {
  min-height: 140px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
}
.quality-card.three {
  background-image: url("../assets/images/chuchang.png");
.empty-home-panel {
  min-height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #64748b;
  font-size: 14px;
}
.quality-card span {
  color: #4fc3f7;
  font-weight: bold;
  margin-left: 6px;
.main-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 400px;
  gap: 16px;
  align-items: start;
}
.chart {
  width: 100%;
  height: 220px;
  margin-top: 10px;
.left-column,
.right-column {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}
.process-panel {
  padding-bottom: 10px;
  padding-bottom: 12px;
}
.process-panel__header {
.panel-actions {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.process-panel__body {
  display: flex;
  gap: 24px;
  align-items: stretch;
.process-body {
  margin-top: 10px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 232px;
  gap: 12px;
  align-items: stretch;
  min-height: 0;
}
.process-panel__chart {
  flex: 1;
  min-width: 0;
  padding: 6px 0;
.process-chart {
  position: relative;
  border: 1px solid rgba(148, 163, 184, 0.24);
  border-radius: 14px;
  background:
      linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(244, 249, 255, 0.9)),
      repeating-linear-gradient(
          to right,
          rgba(148, 163, 184, 0.07) 0,
          rgba(148, 163, 184, 0.07) 1px,
          transparent 1px,
          transparent 48px
      ),
      repeating-linear-gradient(
          to bottom,
          rgba(148, 163, 184, 0.06) 0,
          rgba(148, 163, 184, 0.06) 1px,
          transparent 1px,
          transparent 34px
      );
  overflow: hidden;
  padding: 10px;
}
.process-panel__aside {
  width: 260px;
.process-chart.empty :deep(canvas) {
  opacity: 0.2;
}
.chart-empty {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: #64748b;
  font-size: 14px;
  text-align: center;
  pointer-events: auto;
  padding: 12px;
}
.chart-empty .el-icon {
  color: #2563eb;
  font-size: 28px;
}
.chart-empty-title {
  font-size: 16px;
  font-weight: 700;
  color: #334155;
}
.chart-empty-desc {
  font-size: 13px;
  color: #64748b;
}
.chart-empty-actions {
  margin-top: 4px;
  display: flex;
  gap: 8px;
}
.process-aside {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.process-legend,
.process-card {
  border: 1px solid rgba(148, 163, 184, 0.22);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.84);
  padding: 10px 12px;
}
.process-card {
  min-height: 74px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.process-legend {
  min-height: 74px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
  padding: 8px 6px;
  gap: 6px;
  justify-content: center;
}
.process-legend__item {
.process-legend-item {
  color: #475569;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: rgba(0, 0, 0, 0.55);
}
.dot {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  border-radius: 3px;
  display: inline-block;
}
.dot-blue {
  background: #1E5BFF;
  background: #2563eb;
}
.dot-yellow {
  background: #F7B500;
.dot-orange {
  background: #f59e0b;
}
.dot-teal {
  background: #19C6C6;
.dot-cyan {
  background: #14b8a6;
}
.process-card {
  background: rgba(245, 247, 250, 0.9);
  border-radius: 10px;
  padding: 16px 16px;
}
.process-card--name {
  background: rgba(235, 242, 255, 1);
  color: #1E5BFF;
  font-weight: 800;
.process-name {
  color: #2563eb;
  font-weight: 700;
  font-size: 14px;
  line-height: 1.2;
  margin-bottom: 2px;
}
.process-card__label {
  font-size: 13px;
  color: rgba(0, 0, 0, 0.55);
  margin-bottom: 10px;
}
.process-card__value {
  font-size: 24px;
  font-weight: 800;
  color: rgba(0, 0, 0, 0.8);
}
.process-card__value .unit {
.process-label {
  font-size: 12px;
  color: #64748b;
}
.process-value {
  margin-top: 4px;
  font-size: 24px;
  color: #0f172a;
  font-weight: 700;
}
.chart-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.contract-summary {
  display: grid;
  grid-template-columns: 1fr 190px;
  gap: 12px;
  align-items: center;
  margin-top: 8px;
}
.contract-card {
  border-radius: 14px;
  border: 1px solid rgba(148, 163, 184, 0.2);
  background: #f8fbff;
  padding: 12px;
}
.contract-name {
  color: #64748b;
  font-size: 13px;
}
.contract-main {
  margin-top: 8px;
  font-size: 34px;
  font-weight: 700;
  color: #0f172a;
}
.contract-compare {
  margin-top: 8px;
  font-size: 13px;
  color: #64748b;
  display: flex;
  gap: 10px;
}
.rise {
  color: #0ea5a4;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.45);
}
.contract-list {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.contract-list li {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) 56px auto;
  align-items: center;
  gap: 8px;
  color: #475569;
  font-size: 13px;
}
.legend-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.contract-item-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contract-item-rate {
  text-align: right;
  color: #64748b;
}
.contract-item-value {
  color: #1f3658;
  text-align: right;
}
.quality-cards {
  margin: 8px 0 10px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.quality-card {
  border-radius: 12px;
  border: 1px solid rgba(148, 163, 184, 0.2);
  padding: 10px 12px;
  color: #475569;
  font-size: 13px;
}
.quality-card.one {
  background: linear-gradient(135deg, #ffffff, #edf4ff);
}
.quality-card.two {
  background: linear-gradient(135deg, #ffffff, #ebfffc);
}
.quality-card.three {
  background: linear-gradient(135deg, #ffffff, #fff3e6);
}
.quality-card span {
  color: #0f172a;
  font-weight: 700;
  margin-left: 6px;
}
@media (max-width: 1200px) {
  .process-panel__body {
    flex-direction: column;
  }
.realtime-grid {
  margin-top: 10px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
  .process-panel__aside {
    width: 100%;
    flex-direction: row;
    flex-wrap: wrap;
  }
.realtime-item {
  border: 1px solid rgba(148, 163, 184, 0.2);
  border-radius: 12px;
  background: #f8fbff;
  padding: 10px 8px;
  text-align: center;
}
  .process-card {
    flex: 1;
    min-width: 220px;
  }
.realtime-value {
  font-size: 26px;
  color: #0f172a;
  font-weight: 700;
}
.realtime-label {
  margin-top: 8px;
  font-size: 12px;
  color: #475569;
}
.realtime-delta {
  margin-top: 4px;
  font-size: 12px;
}
.realtime-delta.up {
  color: #0ea5a4;
}
.realtime-delta.down {
  color: #f59e0b;
}
.realtime-delta.flat {
  color: #64748b;
}
.warning-list {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 300px;
  overflow-y: auto;
}
.warning-item {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) 72px;
  align-items: center;
  gap: 10px;
  border: 1px solid rgba(148, 163, 184, 0.2);
  border-radius: 12px;
  background: #f8fbff;
  padding: 10px;
}
.warning-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: block;
}
.warning-dot.device {
  background: #ef4444;
}
.warning-dot.quality {
  background: #f59e0b;
}
.warning-dot.material {
  background: #3b82f6;
}
.warning-title {
  color: #334155;
  font-size: 13px;
  font-weight: 600;
}
.warning-desc {
  color: #64748b;
  font-size: 12px;
  margin-top: 4px;
}
.warning-time {
  color: #64748b;
  font-size: 12px;
  text-align: right;
}
.order-panel {
  min-height: 0;
}
.quick-panel {
  min-height: 0;
}
.table-progress {
  display: flex;
  align-items: center;
  gap: 10px;
}
.table-progress span {
  font-size: 12px;
  color: #475569;
}
.quick-grid {
  margin-top: 10px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 58px;
  gap: 10px;
}
.quick-item {
  border: 1px solid rgba(148, 163, 184, 0.22);
  background: rgba(255, 255, 255, 0.92);
  border-radius: 12px;
  color: #334155;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  font-size: 12px;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.plan-panel {
  min-height: 236px;
}
.quality-panel {
  min-height: 0;
}
.receipt-panel {
  min-height: 340px;
}
.plan-list {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.plan-item {
  border: 1px solid rgba(148, 163, 184, 0.18);
  border-radius: 12px;
  background: #f8fbff;
  padding: 10px 12px;
}
.plan-main {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: center;
}
.plan-order {
  font-size: 13px;
  color: #1f3658;
  font-weight: 600;
}
.plan-name {
  font-size: 13px;
  color: #334155;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.plan-meta {
  margin-top: 6px;
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  color: #64748b;
}
.quick-item:hover {
  transform: translateY(-2px);
  border-color: rgba(96, 165, 250, 0.45);
  box-shadow: 0 14px 28px rgba(37, 99, 235, 0.1);
}
.quick-icon {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: linear-gradient(135deg, #2563eb, #38bdf8);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  color: #fff;
}
.quick-item:nth-child(2) .quick-icon,
.quick-item:nth-child(6) .quick-icon {
  background: linear-gradient(135deg, #14b8a6, #5eead4);
}
.quick-item:nth-child(3) .quick-icon,
.quick-item:nth-child(5) .quick-icon {
  background: linear-gradient(135deg, #7c3aed, #a78bfa);
}
.quick-item:nth-child(4) .quick-icon,
.quick-item:nth-child(7) .quick-icon {
  background: linear-gradient(135deg, #f97316, #fdba74);
}
.process-selection-wrapper {
  max-height: 400px;
  overflow-y: auto;
  padding: 10px;
  padding: 8px;
}
.process-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 12px;
  gap: 10px;
}
:deep(.el-checkbox.is-bordered) {
  margin-left: 0 !important;
  width: 100%;
}
</style>
:deep(.el-radio-button__inner) {
  border-radius: 10px !important;
  background: #f8fbff;
  border-color: rgba(148, 163, 184, 0.22) !important;
  color: #475569 !important;
}
:deep(.el-radio-button__original-radio:checked + .el-radio-button__inner) {
  background: linear-gradient(135deg, #2f80ff, #38bdf8) !important;
  border-color: transparent !important;
  color: #fff !important;
}
:deep(.el-progress-circle__track) {
  stroke: rgba(148, 163, 184, 0.3);
}
:deep(.el-progress-bar__outer) {
  background-color: rgba(148, 163, 184, 0.2);
}
:deep(.order-panel .el-progress-bar__inner) {
  background: linear-gradient(90deg, #2563eb, #38bdf8) !important;
}
:deep(.order-panel .el-table) {
  border-radius: 14px;
}
:deep(.order-panel .el-table th.el-table__cell) {
  background: #f2f7ff !important;
}
:deep(.order-panel .el-table__body tr:hover > td.el-table__cell) {
  background: #f8fbff !important;
}
:deep(.order-panel .el-tag--success) {
  color: #0f766e;
  background: #e9fdf7;
  border-color: #b7f2e0;
}
:deep(.order-panel .el-tag--warning) {
  color: #b45309;
  background: #fff6e8;
  border-color: #fde0b8;
}
:deep(.order-panel .el-tag--primary) {
  color: #2563eb;
  background: #eaf2ff;
  border-color: #b8d2ff;
}
@media (max-width: 1600px) {
  .main-grid {
    grid-template-columns: minmax(0, 1fr) 380px;
  }
}
@media (max-width: 1366px) {
  .main-grid {
    grid-template-columns: minmax(0, 1fr) 340px;
  }
  .stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 1200px) {
  .main-grid {
    grid-template-columns: 1fr;
  }
  .right-column {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
  }
  .chart-row {
    grid-template-columns: 1fr;
  }
  .process-body {
    grid-template-columns: 1fr;
  }
  .realtime-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .quality-cards {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 768px) {
  .welcome-panel {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  .welcome-meta {
    text-align: left;
  }
  .meta-extra {
    justify-content: flex-start;
  }
  .stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .right-column {
    grid-template-columns: 1fr;
  }
  .realtime-grid {
    grid-template-columns: 1fr;
  }
}
</style>
在上述文件截断后对比
src/views/inventoryManagement/dispatchLog/Record.vue src/views/inventoryManagement/receiptManagement/Record.vue src/views/inventoryManagement/stockManagement/BatchNoQtyDetail.vue src/views/inventoryManagement/stockManagement/Record.vue src/views/inventoryManagement/stockReport/index.vue src/views/lavorissue/ledger/filesDia.vue src/views/login.vue src/views/oaSystem/projectManagement/components/milestoneList.vue (已删除) src/views/oaSystem/projectManagement/components/phaseGoalList.vue (已删除) src/views/oaSystem/projectManagement/components/projectForm.vue (已删除) src/views/oaSystem/projectManagement/components/taskTree.vue (已删除) src/views/oaSystem/projectManagement/index.vue (已删除) src/views/oaSystem/projectManagement/projectDetail.vue (已删除) src/views/personnelManagement/contractManagement/filesDia.vue src/views/personnelManagement/contractManagement/index.vue src/views/personnelManagement/dimission/components/formDia.vue src/views/personnelManagement/employeeRecord/index.vue src/views/procurementManagement/procurementLedger/fileList.vue src/views/procurementManagement/procurementLedger/index.vue src/views/procurementManagement/purchaseReturnOrder/New.vue src/views/procurementManagement/purchaseReturnOrder/ProductList.vue src/views/procurementManagement/purchaseReturnOrder/index.vue src/views/productionManagement/processRoute/index.vue src/views/productionManagement/processRoute/processRouteItem/index.vue src/views/productionManagement/productStructure/Detail/index.vue src/views/productionManagement/productionCosting/index.vue src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue src/views/productionManagement/productionOrder/index.vue src/views/productionManagement/productionProcess/index.vue src/views/productionManagement/productionReporting/index.vue src/views/productionManagement/productionTraceability/index.vue src/views/productionManagement/workOrder/components/filesDia.vue src/views/productionManagement/workOrderEdit/index.vue src/views/productionManagement/workOrderManagement/components/filesDia.vue src/views/productionManagement/workOrderManagement/index.vue src/views/productionPlan/productionPlan/index.vue src/views/projectManagement/Management/components/formDia.vue src/views/projectManagement/Management/projectDetail.vue src/views/projectManagement/projectType/index.vue src/views/qualityManagement/finalInspection/components/filesDia.vue src/views/qualityManagement/finalInspection/components/formDia.vue src/views/qualityManagement/finalInspection/index.vue src/views/qualityManagement/nonconformingManagement/components/formDia.vue src/views/qualityManagement/nonconformingManagement/index.vue src/views/qualityManagement/processInspection/components/filesDia.vue src/views/qualityManagement/processInspection/components/formDia.vue src/views/qualityManagement/processInspection/index.vue src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue src/views/qualityManagement/rawMaterialInspection/components/formDia.vue src/views/qualityManagement/rawMaterialInspection/index.vue src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue src/views/reportAnalysis/PSIDataAnalysis/index.vue src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue src/views/reportAnalysis/dataDashboard/index.vue src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue src/views/reportAnalysis/productionAnalysis/components/center-center.vue src/views/reportAnalysis/productionAnalysis/components/center-top.vue src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue src/views/reportAnalysis/productionAnalysis/components/left-top.vue src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue src/views/reportAnalysis/productionAnalysis/components/right-top.vue src/views/reportAnalysis/productionAnalysis/index.vue src/views/safeProduction/safeWorkApproval/components/infoFormDia.vue src/views/safeProduction/safeWorkApproval/fileList.vue src/views/salesManagement/deliveryLedger/index.vue src/views/salesManagement/invoiceLedger/index.vue src/views/salesManagement/returnOrder/components/detailDia.vue src/views/salesManagement/returnOrder/components/formDia.vue src/views/salesManagement/returnOrder/index.vue src/views/salesManagement/salesLedger/fileList.vue src/views/salesManagement/salesLedger/index.vue src/views/salesManagement/salesQuotation/index.vue src/views/systemArchitecture/index.vue