gaoluyang
16 小时以前 076bb96b437258f0e8cdbe184040e1e302b60d4b
1.军泰伟业代码初始化
已添加11个文件
已修改93个文件
10971 ■■■■■ 文件已修改
multiple/config.json 322 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/equipmentManagement/calibration.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockIn.js 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockManage.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockOut.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/personnelManagement/employeeRecord.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/personnelManagement/payrollManagement.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/personnelManagement/scheduling.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productionOrder.js 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/publicApi/commonFile.js 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/user.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/viewIndex.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PIMTable/Pagination.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/customerFile/index.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/supplierManage/index.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue 131 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/fileList.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/approvalProcess/index.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/collaborativeApproval/noticeManagement/index.vue 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/customerService/expiryAfterSales/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/customerService/feedbackRegistration/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/calibration/index.vue 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/formDia.vue 382 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/index.vue 509 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/ledger/index.vue 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/components/formDia.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/measurementEquipment/index.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Form/MaintainForm.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Form/RepairForm.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Modal/RepairModal.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/MaintenanceForm.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Form/PlanForm.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/Modal/PlanModal.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/upkeep/index.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/expenseManagement/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/financialStatements/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/financialManagement/revenueManagement/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/dispatchLog/index.vue 399 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/issueManagement/index.vue 290 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/components/formDia.vue 399 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue 332 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/components/formDiaProduct.vue 302 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/index.vue 811 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/components/FormDiaProduction.vue 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/components/FormDiaPurchase.vue 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/stockManagement/index.vue 511 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/contractManagement/filesDia.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/contractManagement/index.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/dimission/components/formDia.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/employeeRecord/components/formDia.vue 166 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/onboarding/components/formDia.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/onboarding/components/formDiaXJHT.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/onboarding/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/payrollManagement/components/formDia.vue 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/payrollManagement/index.vue 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/scheduling/index.vue 307 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/components/Modal.vue 916 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/index.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/paymentEntry/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/paymentHistory/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementInvoiceLedger/Form/EditForm.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementInvoiceLedger/fileList.vue 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementInvoiceLedger/index.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/fileList.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementReport/index.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/operationScheduling/components/formDia.vue 121 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/operationScheduling/index.vue 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionCosting/index.vue 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionDispatching/components/autoDispatchDia.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionDispatching/components/formDia.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionDispatching/index.vue 464 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionReporting/components/formDia.vue 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionReporting/index.vue 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/filesDia.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/formDia.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/filesDia.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/formDia.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/dataDashboard/index.vue 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/projectProfit/index.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/indicatorStats/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/invoiceLedger/fileList.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/invoiceLedger/index.vue 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/invoiceRegistration/index.vue 1256 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/orderManagement/index.vue 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/paymentShipping/index.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/receiptPayment/index.vue 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/receiptPaymentHistory/index.vue 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/fileList.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 125 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesQuotation/index.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
multiple/config.json
@@ -14,9 +14,329 @@
      "VITE_JAVA_API": "http://114.132.189.42:9037"
    },
    "screen": "screen/HYSNView.png",
    "logo": "logo/ZGLTLogo.png",
    "logo": "logo/LCLogo.png",
    "favicon": "favicon/favicon.ico"
  },
  "WDSY": {
    "env": {
      "VITE_APP_TITLE": "伟德实业信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:8068",
      "VITE_JAVA_API": "http://114.132.189.42:8085"
    },
    "screen": "screen/WDSYView.png",
    "logo": "logo/WDSYLogo.png",
    "favicon": "favicon/WDSYico.ico"
  },
  "JZYJ": {
    "env": {
      "VITE_APP_TITLE": "基智油井信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:8078",
      "VITE_JAVA_API": "http://114.132.189.42:8086"
    },
    "screen": "screen/JZYJView.png",
    "logo": "logo/JZYJLogo.png",
    "favicon": "favicon/JZYJico.ico"
  },
  "ZQHX": {
    "env": {
      "VITE_APP_TITLE": "中强恒兴信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:1234",
      "VITE_JAVA_API": "http://114.132.189.42:8080"
    },
    "screen": "screen/ZQHXView.png",
    "logo": "logo/ZQHXLogo.png",
    "favicon": "favicon/ZQHXico.ico"
  },
  "XYHB": {
    "env": {
      "VITE_APP_TITLE": "宣屹环保信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9052",
      "VITE_JAVA_API": "http://114.132.189.42:9051"
    },
    "screen": "screen/XYHBView.png",
    "logo": "logo/XYHBLogo.png",
    "favicon": "favicon/XYHBico.ico"
  },
  "BHMY": {
    "env": {
      "VITE_APP_TITLE": "博宏煤业信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9070",
      "VITE_JAVA_API": "http://114.132.189.42:9069"
    },
    "screen": "screen/ZQHXView.png",
    "logo": "logo/BHMYLogo.png",
    "favicon": "favicon/BHMY.ico"
  },
  "HHKJ": {
    "env": {
      "VITE_APP_TITLE": "恒晖科技信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9046",
      "VITE_JAVA_API": "http://114.132.189.42:9047"
    },
    "screen": "screen/HHKJView.png",
    "logo": "logo/HHKJLogo.png",
    "favicon": "favicon/HHKJIco.ico"
  },
  "RZNY": {
    "env": {
      "VITE_APP_TITLE": "锐择能源信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9058",
      "VITE_JAVA_API": "http://114.132.189.42:9057"
    },
    "screen": "screen/RZNYView.png",
    "logo": "logo/RZNYLogo.png",
    "favicon": "favicon/RZNY.ico"
  },
  "TJXM": {
    "env": {
      "VITE_APP_TITLE": "泰江洗煤信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9064",
      "VITE_JAVA_API": "http://114.132.189.42:9063"
    },
    "screen": "screen/TJXMView.png",
    "logo": "logo/TJXMLogo.png",
    "favicon": "favicon/TJXM.ico"
  },
  "HYSN": {
    "env": {
      "VITE_APP_TITLE": "弘也水泥信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9034",
      "VITE_JAVA_API": "http://114.132.189.42:9035"
    },
    "screen": "screen/HYSNView.png",
    "logo": "logo/HYSNLogo.png",
    "favicon": "favicon/HYSNico.ico"
  },
  "JYHJ": {
    "env": {
      "VITE_APP_TITLE": "金鹰黄金信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9030",
      "VITE_JAVA_API": "http://114.132.189.42:9031"
    },
    "screen": "screen/HYSNView.png",
    "logo": "logo/JYHJLogo.png",
    "favicon": "favicon/JYHJico.ico"
  },
  "DHDC": {
    "env": {
      "VITE_APP_TITLE": "敦煌鼎诚信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9032",
      "VITE_JAVA_API": "http://114.132.189.42:9033"
    },
    "screen": "screen/DHDCView.png",
    "logo": "logo/DHDCLogo.png",
    "favicon": "favicon/DHDCico.ico"
  },
  "MXSC": {
    "env": {
      "VITE_APP_TITLE": "闽兴石材信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9048",
      "VITE_JAVA_API": "http://114.132.189.42:9049"
    },
    "screen": "screen/MXSCBack.png",
    "logo": "logo/MXSCLogo.png",
    "favicon": "favicon/MXSCIco.ico"
  },
  "CJNY": {
    "env": {
      "VITE_APP_TITLE": "创巨能源信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9038",
      "VITE_JAVA_API": "http://114.132.189.42:9039"
    },
    "screen": "screen/MXSCBack.png",
    "logo": "logo/CJNYLogo.png",
    "favicon": "favicon/CJNYico.ico"
  },
  "JSMY": {
    "env": {
      "VITE_APP_TITLE": "金石煤业信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9042",
      "VITE_JAVA_API": "http://114.132.189.42:9043"
    },
    "screen": "screen/MXSCBack.png",
    "logo": "logo/JSMYLogo.png",
    "favicon": "favicon/JSMYico.ico"
  },
  "JSYNY": {
    "env": {
      "VITE_APP_TITLE": "锦盛源能源信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9074",
      "VITE_JAVA_API": "http://114.132.189.42:9073"
    },
    "screen": "screen/HYSNView.png",
    "logo": "logo/JSYNYLogo.png",
    "favicon": "favicon/JSYNYico.ico"
  },
  "CMNY": {
    "env": {
      "VITE_APP_TITLE": "创铭能源信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9088",
      "VITE_JAVA_API": "http://114.132.189.42:9087"
    },
    "screen": "screen/DHDCView.png",
    "logo": "logo/CMNYLogo.png",
    "favicon": "favicon/CMNYico.ico"
  },
  "HCKX": {
    "env": {
      "VITE_APP_TITLE": "海川开心食品信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9090",
      "VITE_JAVA_API": "http://114.132.189.42:9089"
    },
    "screen": "screen/HCKXView.png",
    "logo": "logo/HCKXLogo.png",
    "favicon": "favicon/HCKXico.ico"
  },
  "JLSN": {
    "env": {
      "VITE_APP_TITLE": "锦龙水泥信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9094",
      "VITE_JAVA_API": "http://114.132.189.42:9093"
    },
    "screen": "screen/JLSNView.png",
    "logo": "logo/JLSNLogo.png",
    "favicon": "favicon/JLSNico.ico"
  },
  "BDSM": {
    "env": {
      "VITE_APP_TITLE": "博达商贸信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9096",
      "VITE_JAVA_API": "http://114.132.189.42:9095"
    },
    "screen": "screen/BDSMView.png",
    "logo": "logo/BDSMLogo.png",
    "favicon": "favicon/BDSMico.ico"
  },
  "HXGY": {
    "env": {
      "VITE_APP_TITLE": "汇星钙业信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9098",
      "VITE_JAVA_API": "http://114.132.189.42:9097"
    },
    "screen": "screen/HXGYView.png",
    "logo": "logo/HXGYLogo.png",
    "favicon": "favicon/HXGYico.ico"
  },
  "ZDXM": {
    "env": {
      "VITE_APP_TITLE": "昭德型煤信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9100",
      "VITE_JAVA_API": "http://114.132.189.42:9096"
    },
    "screen": "screen/ZDXMView.png",
    "logo": "logo/ZDXMLogo.png",
    "favicon": "favicon/ZDXMico.ico"
  },
  "HSX": {
    "env": {
      "VITE_APP_TITLE": "湟水峡农业发展信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9101",
      "VITE_JAVA_API": "http://114.132.189.42:9098"
    },
    "screen": "screen/HSXView.png",
    "logo": "logo/HSXLogo.png",
    "favicon": "favicon/HSXico.ico"
  },
  "NYDL": {
    "env": {
      "VITE_APP_TITLE": "南洋电缆产链通信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9036",
      "VITE_JAVA_API": "http://114.132.189.42:9037"
    },
    "screen": "screen/NYDLView.png",
    "logo": "logo/NYDLLogo.png",
    "favicon": "favicon/NYDLico.ico"
  },
  "HCMY": {
    "env": {
      "VITE_APP_TITLE": "浩成煤业信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9103",
      "VITE_JAVA_API": "http://114.132.189.42:9094"
    },
    "screen": "screen/HCMYView.png",
    "logo": "logo/HCMYLogo.png",
    "favicon": "favicon/HCMYico.ico"
  },
  "HGJJ": {
    "env": {
      "VITE_APP_TITLE": "汇国洁净型煤信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9107",
      "VITE_JAVA_API": "http://114.132.189.42:9090"
    },
    "screen": "screen/HGJJView.png",
    "logo": "logo/HGJJLogo.png",
    "favicon": "favicon/HGJJico.ico"
  },
  "MKZS": {
    "env": {
      "VITE_APP_TITLE": "模凯再生信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9111",
      "VITE_JAVA_API": "http://114.132.189.42:9086"
    },
    "screen": "screen/MKZSView.png",
    "logo": "logo/MKZSLogo.png",
    "favicon": "favicon/MKZSico.ico"
  },
  "HSMY": {
    "env": {
      "VITE_APP_TITLE": "华顺镁业信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9115",
      "VITE_JAVA_API": "http://114.132.189.42:9082"
    },
    "screen": "screen/HSMYView.png",
    "logo": "logo/HSMYLogo.png",
    "favicon": "favicon/HSMYico.ico"
  },
  "DHHB": {
    "env": {
      "VITE_APP_TITLE": "丹海环保信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9117",
      "VITE_JAVA_API": "http://114.132.189.42:9080"
    },
    "screen": "screen/DHHBView.png",
    "logo": "logo/DHHBLogo.png",
    "favicon": "favicon/DHHBico.ico"
  },
  "PHMK": {
    "env": {
      "VITE_APP_TITLE": "普禾煤矿信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9119",
      "VITE_JAVA_API": "http://114.132.189.42:9078"
    },
    "screen": "screen/PHMKView.png",
    "logo": "logo/PHMKLogo.png",
    "favicon": "favicon/PHMKico.ico"
  },
  "TYMK": {
    "env": {
      "VITE_APP_TITLE": "通源煤矿信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9121",
      "VITE_JAVA_API": "http://114.132.189.42:9076"
    },
    "screen": "screen/TYMKView.png",
    "logo": "logo/TYMKLogo.png",
    "favicon": "favicon/TYMKico.ico"
  },
  "LQM": {
    "env": {
      "VITE_APP_TITLE": "老琪麦食品信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9123",
      "VITE_JAVA_API": "http://114.132.189.42:9074"
    },
    "screen": "screen/LQMView.png",
    "logo": "logo/LQMLogo.png",
    "favicon": "favicon/LQMico.ico"
  },
  "ZYRQ": {
    "env": {
      "VITE_APP_TITLE": "众源燃气信息管理系统",
      "VITE_BASE_API": "http://114.132.189.42:9123",
      "VITE_JAVA_API": "http://114.132.189.42:9031"
    },
    "screen": "screen/ZYRQView.png",
    "logo": "logo/ZYRQLogo.png",
    "favicon": "favicon/ZYRQico.ico"
  },
  "screen": "/src/assets/images/login-background.png",
  "logo": "/src/assets/logo/logo.png",
  "favicon": "/public/favicon.ico"
src/api/equipmentManagement/calibration.js
@@ -24,4 +24,12 @@
    method: "post",
    data: query,
  });
}
// åˆ é™¤è®°å½•
export function ledgerRecordDelete(ids) {
  return request({
    url: "/measuringInstrumentLedgerRecord/delete",
    method: "delete",
    data: ids,
  });
}
src/api/inventoryManagement/stockIn.js
@@ -9,6 +9,41 @@
    });
};
// æŸ¥è¯¢ç”Ÿäº§å…¥åº“信息列表
export const getStockInPageByProduction = (params) => {
    return request({
        url: "/stockin/listPageByProduction",
        method: "get",
        params,
    });
};
// å‡ºåº“台账-查询自定义入库信息列表
export const getStockInPageByCustom = (params) => {
    return request({
        url: "/stockmanagement/listPageByCustom",
        method: "get",
        params,
    });
};
// å…¥åº“管理-查询自定义入库信息列表
export const getInPageByCustom = (params) => {
    return request({
        url: "/stockin/listPageByCustom",
        method: "get",
        params,
    });
};
// å‡ºåº“台账-查询生产出库信息列表
export const getStockInPageByProduct = (params) => {
    return request({
        url: "/stockmanagement/listPageByProduct",
        method: "get",
        params,
    });
};
// ä¿®æ”¹å…¥åº“存信息
export const updateStockIn = (data) => {
    return request({
@@ -26,6 +61,14 @@
        data,
    });
};
// ä¿®æ”¹ææ–™åº“存信息
export const updateManagementByCustom = (data) => {
    return request({
        url: "/stockin/updateManagementByCustom ",
        method: "post",
        data,
    });
};
// æ–°å¢žå•†å“å…¥åº“信息
export function addSutockIn(data) {
@@ -36,6 +79,32 @@
    })
}
// æ–°å¢žè‡ªå®šä¹‰å…¥åº“信息
export function addStockInCustom(data) {
    return request({
        url: '/stockin/addCustom',
        method: 'post',
        data: data
    })
}
// ç¼–辑自定义入库信息
export function updateStockInCustom(data) {
    return request({
        url: '/stockin/updateCustom',
        method: 'post',
        data: data
    })
}
// ç¼–辑成品入库信息
export function updateProduct(data) {
    return request({
        url: '/stockin/update',
        method: 'post',
        data: data
    })
}
// åˆ é™¤å…¥åº“信息
export function delStockIn(ids) {
    return request({
@@ -45,6 +114,15 @@
    })
}
// åˆ é™¤è‡ªå®šä¹‰å…¥åº“信息
export function delStockInCustom(ids) {
    return request({
        url: '/stockin/delteCustom',
        method: 'post',
        data: ids
    })
}
// å¯¼å‡ºå…¥åº“信息
export function exportStockIn(query) {
    return request({
src/api/inventoryManagement/stockManage.js
@@ -9,6 +9,24 @@
    });
};
// æŸ¥è¯¢ç”Ÿäº§å…¥åº“库存信息列表
export const getStockManagePageByProduction = (params) => {
    return request({
        url: "/stockin/listPageCopyByProduction",
        method: "get",
        params,
    });
};
// æŸ¥è¯¢è‡ªå®šä¹‰å…¥åº“库存信息列表
export const getStockManagePageByCustom = (params) => {
    return request({
        url: "/stockin/listPageCopyByCustom",
        method: "get",
        params,
    });
};
// ä¿®æ”¹åº“存信息
export const updateStockManage = (data) => {
@@ -38,7 +56,7 @@
    })
}
//出库接口
// å‡ºåº“管理-领用接口
export const stockOut = (data) => {
    return request({
        url: '/stockmanagement/stockout',
src/api/inventoryManagement/stockOut.js
@@ -1,6 +1,6 @@
import request from "@/utils/request";
//查询出库列表
// å‡ºåº“台账-采购出库查询出库列表
export const getStockOutPage = (params) => {
    return request({
        url: "/stockmanagement/listPage",
@@ -35,13 +35,3 @@
        data: ids
    })
}
//导出出库信息
export const exportStockOut = (query) => {
    return request({
        url: '/stockmanagement/export',
        method: 'get',
        params: query,
        responseType: 'blob'
    })
}
src/api/personnelManagement/employeeRecord.js
@@ -15,4 +15,13 @@
        method: 'get',
        params: query,
    })
}
// å¯¼å‡ºåˆåŒå‰¯æœ¬
export function staffOnJobExportCopy(data) {
    return request({
        url: '/staff/staffOnJob/exportCopy',
        method: 'post',
        data: data,
    })
}
src/api/personnelManagement/payrollManagement.js
@@ -32,4 +32,20 @@
    method: "delete",
    data: query,
  });
}
// å¯¼å…¥
export function importData(query) {
  return request({
    url: "/compensationPerformance/importData",
    method: "post",
    data: query,
  });
}
// ä¸‹è½½æ¨¡ç‰ˆ
export function exportTemplate(query) {
  return request({
    url: "/compensationPerformance/exportTemplate",
    method: "post",
    data: query,
  });
}
src/api/personnelManagement/scheduling.js
@@ -30,3 +30,10 @@
        data: data
    })
}
export function getCurrentUserLatestScheduling(){
    return request({
        url: "/staff/staffScheduling/getCurrentUserLatestScheduling",
        method: "get"
    })
}
src/api/productionManagement/productionOrder.js
@@ -9,6 +9,34 @@
    params: query,
  });
}
// èŽ·å–ç‚’æœºæ­£åœ¨å·¥ä½œé‡æ•°æ®
export function schedulingList(query) {
  return request({
    url: "/salesLedger/scheduling/list",
    method: "get",
    params: query,
  });
}
// ä¿å­˜ç‚’机设置
export function addSpeculatTrading(data) {
  return request({
    url: "/salesLedger/scheduling/addSpeculatTrading",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹ç‚’机设置
export function updateSpeculatTrading(data) {
  return request({
    url: "/salesLedger/scheduling/updateSpeculatTrading",
    method: "post",
    data: data,
  });
}
// ç”Ÿäº§æ´¾å·¥
export function productionDispatch(query) {
  return request({
@@ -16,4 +44,38 @@
    method: "post",
    data: query,
  });
}
// è‡ªåŠ¨æ´¾å·¥
export function productionDispatchList(query) {
  return request({
    url: "/salesLedger/scheduling/productionDispatchList",
    method: "post",
    data: query,
  });
}
// æŸ¥è¯¢æŸè€—率
export function getLossRate() {
  return request({
    url: "/salesLedger/scheduling/loss",
    method: "get",
  });
}
// æ–°å¢žæŸè€—率
export function addLossRate(data) {
  return request({
    url: "/salesLedger/scheduling/addLoss",
    method: "post",
    data: data,
  });
}
// ä¿®æ”¹æŸè€—率
export function updateLossRate(data) {
  return request({
    url: "/salesLedger/scheduling/updateLoss",
    method: "post",
    data: data,
  });
}
src/api/publicApi/commonFile.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
// å…¬å…±æ–‡ä»¶ç®¡ç†æŽ¥å£
import request from '@/utils/request'
// åˆ é™¤å…¬å…±æ–‡ä»¶
export function delCommonFile(ids) {
  return request({
    url: '/commonFile/delCommonFile',
    method: 'delete',
    data: ids
  })
}
// å¼€ç¥¨å°è´¦æ–‡ä»¶åˆ é™¤
export function delCommonFileInvoiceLedger(ids) {
  return request({
    url: '/invoiceLedger/delFile',
    method: 'delete',
    data: ids
  })
}
src/api/system/user.js
@@ -8,6 +8,13 @@
    method: 'get',
    params: query
  })
}// æŸ¥è¯¢ç”¨æˆ·åˆ—表
export function listAll(query) {
  return request({
    url: '/system/user//listAll',
    method: 'get',
    params: query
  })
}
// æŸ¥è¯¢ç”¨æˆ·è¯¦ç»†
src/api/viewIndex.js
@@ -44,4 +44,18 @@
        url: '/sales/ledger/getAmountHalfYear',
        method: 'get'
    })
}
}
// ååŒå¾…审批和报修待办事项
export const approveAndDeviceTodos = () => {
    return request({
        url: '/home/approveAndDeviceTodos',
        method: 'get'
    })
}
export const noticesCount = () => {
    return request({
        url: '/home/noticesCount',
        method: 'get'
    })
}
src/components/PIMTable/Pagination.vue
@@ -71,6 +71,7 @@
})
const handleSizeChange = (val) => {
    console.log('handleSizeChange', val)
  if (currentPage.value * val > props.total) {
    currentPage.value = 1
  }
@@ -81,6 +82,7 @@
}
const handleCurrentChange = (val) => {
    console.log('handleCurrentChange---', val)
  emit('pagination', { page: val, limit: pageSize.value })
  if (props.autoScroll) {
    scrollTo(0, 800)
src/views/basicData/customerFile/index.vue
@@ -147,8 +147,10 @@
              <el-select
                v-model="form.maintainer"
                placeholder="请选择"
                filterable
                default-first-option
                :reserve-keyword="false"
                clearable
                disabled
              >
                <el-option
                  v-for="item in userList"
@@ -305,10 +307,7 @@
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
        },
                disabled: (row) => {
                    return row.maintainer !== userStore.nickName
                }
        }
      },
    ],
  },
@@ -558,12 +557,6 @@
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    // æ£€æŸ¥æ˜¯å¦æœ‰ä»–人维护的数据
    const unauthorizedData = selectedRows.value.filter(item => item.maintainer !== userStore.nickName);
    if (unauthorizedData.length > 0) {
      proxy.$modal.msgWarning("不可删除他人维护的数据");
      return;
    }
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
src/views/basicData/product/index.vue
@@ -146,7 +146,19 @@
            <el-form-item label="规格型号:" prop="model">
              <el-input
                v-model="modelForm.model"
                placeholder="请输入规格型号"
                placeholder="请输入规格型号(g*袋数)"
                clearable
                @keydown.enter.prevent
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="其他规格型号:" prop="otherModel">
              <el-input
                v-model="modelForm.otherModel"
                placeholder="请输入其他规格型号"
                clearable
                @keydown.enter.prevent
              />
@@ -162,6 +174,24 @@
                clearable
                @keydown.enter.prevent
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="绑定机器:" prop="speculativeTradingName">
              <el-select
                v-model="modelForm.speculativeTradingName"
                placeholder="请选择绑定机器"
                multiple
                clearable
                style="width: 100%"
              >
                <el-option label="炒机1" value="炒机1" />
                <el-option label="炒机2" value="炒机2" />
                <el-option label="炒机3" value="炒机3" />
                <el-option label="炒机4" value="炒机4" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
@@ -213,6 +243,10 @@
    prop: "unit",
  },
  {
    label: "绑定机器",
    prop: "speculativeTradingName",
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
@@ -244,12 +278,22 @@
    productName: [{ required: true, message: "请输入", trigger: "blur" }],
  },
  modelForm: {
    otherModel:'',
    model: "",
    unit: "",
    speculativeTradingName: [],
  },
  modelRules: {
    model: [{ required: true, message: "请输入", trigger: "blur" }],
    unit: [{ required: true, message: "请输入", trigger: "blur" }],
    model: [
      // { required: true, message: "请输入", trigger: "blur" },
      {
        pattern: /^[0-9*]*$/,
        message: "只能输入数字和*号",
        trigger: "blur"
      }
    ],
    // unit: [{ required: true, message: "请输入", trigger: "blur" }],
    // speculativeTradingName: [{ required: false, message: "请选择绑定机器", trigger: "change" }],
  },
});
const { form, rules, modelForm, modelRules } = toRefs(data);
@@ -286,10 +330,15 @@
  modelOperationType.value = type;
  modelDia.value = true;
  modelForm.value.model = "";
  modelForm.value.model = "";
  modelForm.value.unit = "";
  modelForm.value.speculativeTradingName = [];
  modelForm.value.id = "";
  if (type === "edit") {
    modelForm.value = { ...data };
    // å¦‚果后端返回的是字符串,需要转换为数组
    if (data.speculativeTradingName && typeof data.speculativeTradingName === 'string') {
      modelForm.value.speculativeTradingName = data.speculativeTradingName.split(',');
    }
  }
};
// æäº¤äº§å“åç§°ä¿®æ”¹
@@ -358,8 +407,19 @@
const submitModelForm = () => {
  proxy.$refs.modelFormRef.validate((valid) => {
    if (valid) {
      modelForm.value.productId = currentId.value;
      addOrEditProductModel(modelForm.value).then((res) => {
      let _modelForm = { ...modelForm.value };
      if(_modelForm.otherModel){
        _modelForm.model = _modelForm.otherModel;
      }
      delete _modelForm.otherModel;
      // å°†é€‰ä¸­çš„æœºå™¨æ•°ç»„转换为逗号分隔的字符串
      const submitData = {
        ..._modelForm,
        productId: currentId.value,
        speculativeTradingName: modelForm.value.speculativeTradingName.join(',')
      };
      addOrEditProductModel(submitData).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeModelDia();
        getModelList();
src/views/basicData/supplierManage/index.vue
@@ -141,7 +141,9 @@
                v-model="form.maintainUserId"
                placeholder="请选择"
                clearable
                disabled
                filterable
                default-first-option
                :reserve-keyword="false"
              >
                <el-option
                  v-for="item in userList"
@@ -299,9 +301,6 @@
        clickFun: (row) => {
          openForm("edit", row);
        },
                disabled: (row) => {
                    return row.maintainUserName !== userStore.nickName
                }
      },
    ],
  },
@@ -496,12 +495,6 @@
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
        // æ£€æŸ¥æ˜¯å¦æœ‰ä»–人维护的数据
        const unauthorizedData = selectedRows.value.filter(item => item.maintainUserName !== userStore.nickName);
        if (unauthorizedData.length > 0) {
            proxy.$modal.msgWarning("不可删除他人维护的数据");
            return;
        }
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -121,33 +121,16 @@
      <template #footer v-if="operationType === 'approval'">
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm(2)">不通过</el-button>
          <el-button type="primary" @click="openSignatureDialog(1)">通过</el-button>
          <el-button type="primary" @click="submitForm(1)">通过</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- ç”µå­ç­¾åå¼¹çª—(vue3-signature-pad) -->
    <el-dialog v-model="signatureDialogVisible" title="电子签名" width="600px" append-to-body>
            <vueEsign
                ref="esign"
                class="mySign"
                :width="800"
                :height="300"
                :isCrop="isCrop"
                :lineWidth="lineWidth"
                :lineColor="lineColor"
            />
      <div style="margin-top:10px;">
        <el-button @click="clearSignature">清除</el-button>
        <el-button type="primary" @click="confirmSignature">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script setup>
import { getCurrentInstance, reactive, ref, toRefs } from "vue";
import vueEsign from "vue-esign";
import {
    approveProcessDetails,
    getDept,
@@ -156,7 +139,6 @@
import useUserStore from "@/store/modules/user.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
import { getToken } from "@/utils/auth";
const emit = defineEmits(['close'])
const { proxy } = getCurrentInstance()
@@ -178,21 +160,6 @@
    },
});
const { form } = toRefs(data);
const signatureDialogVisible = ref(false);
const signatureImg = ref('');
let submitStatus = null; // ä¸´æ—¶å­˜å‚¨é€šè¿‡/不通过状态
const isCrop = ref("");
const esign = ref(null);
const lineWidth = ref(0);
const lineColor = ref("#000000");
// ä¸Šä¼ é…ç½®
const upload = reactive({
  // ä¸Šä¼ çš„地址
  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
  // è®¾ç½®ä¸Šä¼ çš„请求头部
  headers: { Authorization: "Bearer " + getToken() },
});
// èŠ‚ç‚¹æ ‡é¢˜
const getNodeTitle = (index, len) => {
@@ -248,77 +215,10 @@
        productOptions.value = res.data;
    });
};
// æ‰“开签名弹窗
const openSignatureDialog = (status) => {
  submitStatus = status;
  signatureDialogVisible.value = true;
};
// æ¸…除签名
const clearSignature = () => {
    esign.value.reset();
};
// ç¡®è®¤ç­¾å
const confirmSignature = () => {
    esign.value.generate().then((res) => {
        console.log(res);
        // å°†base64转换为二进制
        const base64Data = res.split(',')[1]; // ç§»é™¤data:image/png;base64,前缀
        const binaryString = atob(base64Data);
        const bytes = new Uint8Array(binaryString.length);
        for (let i = 0; i < binaryString.length; i++) {
            bytes[i] = binaryString.charCodeAt(i);
        }
        signatureImg.value = bytes;
        // åˆ›å»ºæ–‡ä»¶å¯¹è±¡ç”¨äºŽä¸Šä¼ 
        const blob = new Blob([bytes], { type: 'image/png' });
        const file = new File([blob], 'signature.png', { type: 'image/png' });
        // åˆ›å»ºFormData
        const formData = new FormData();
        formData.append('file', file);
        // ä¸Šä¼ ç­¾åå›¾ç‰‡
        fetch(upload.url, {
            method: 'POST',
            headers: upload.headers,
            body: formData
        })
        .then(response => response.json())
        .then(data => {
            if (data.code === 200) {
                console.log('data---', data)
                let tempFileIds = [];
                tempFileIds.push(data.data.tempId);
                signatureDialogVisible.value = false;
                clearSignature();
                // åªæœ‰é€šè¿‡æ—¶æ‰ä¼ é€’签名文件ID
                if (submitStatus === 1) {
                    submitForm(submitStatus, tempFileIds);
                } else {
                    submitForm(submitStatus);
                }
            } else {
                proxy.$modal.msgError("签名图片上传失败:" + data.msg);
            }
        })
        .catch(error => {
            console.error('上传失败:', error);
            proxy.$modal.msgError("签名图片上传失败");
        });
    }).catch((err) => {
        console.log(err);
        proxy.$modal.msgWarning("请先签名!");
    })
};
// æäº¤å®¡æ‰¹
const submitForm = (status, tempFileIds) => {
const submitForm = (status) => {
  const filteredActivities = activities.value.filter(activity => activity.isShen);
  filteredActivities[0].approveNodeStatus = status;
  // åªæœ‰é€šè¿‡æ—¶æ‰éœ€è¦ç­¾å
  if (status === 1 && tempFileIds) {
    filteredActivities[0].tempFileIds = tempFileIds;
  }
  // åˆ¤æ–­æ˜¯å¦ä¸ºæœ€åŽä¸€æ­¥
  const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1;
  updateApproveNode({ ...filteredActivities[0], isLast }).then(() => {
src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -16,19 +16,20 @@
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="申请部门:" prop="approveDeptId">
                            <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 label="申请部门:" prop="approveDeptName">
              <el-input v-model="form.approveDeptName" placeholder="请输入" clearable/>
<!--                            <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>
@@ -36,6 +37,63 @@
          <el-col :span="24">
            <el-form-item :label="props.approveType == 5 ? '采购说明:' : '审批事由:'" prop="approveReason">
              <el-input v-model="form.approveReason" placeholder="请输入" clearable type="textarea" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- è¯·å‡æ—¶é—´ï¼ˆä»…当 approveType ä¸º 2 æ—¶æ˜¾ç¤ºï¼‰ -->
        <el-row :gutter="30" v-if="props.approveType == 2">
          <el-col :span="12">
            <el-form-item label="请假开始时间:" prop="startDate">
              <el-date-picker
                  v-model="form.startDate"
                  type="date"
                  placeholder="请选择开始日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="请假结束时间:" prop="endDate">
              <el-date-picker
                  v-model="form.endDate"
                  type="date"
                  placeholder="请选择结束日期"
                  value-format="YYYY-MM-DD"
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- æŠ¥é”€é‡‘额(仅当 approveType ä¸º 4 æ—¶æ˜¾ç¤ºï¼‰ -->
        <el-row v-if="props.approveType == 4">
          <el-col :span="24">
            <el-form-item label="报销金额:" prop="price">
              <el-input-number
                  v-model="form.price"
                  placeholder="请输入报销金额"
                  :min="0"
                  :precision="2"
                  :step="0.01"
                  style="width: 100%"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- å‡ºå·®åœ°ç‚¹ï¼ˆä»…当 approveType ä¸º 3 æ—¶æ˜¾ç¤ºï¼‰ -->
        <el-row v-if="props.approveType == 3">
          <el-col :span="24">
            <el-form-item label="出差地点:" prop="location">
              <el-input
                  v-model="form.location"
                  placeholder="请输入出差地点"
                  clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
@@ -88,6 +146,9 @@
                            <el-select
                                v-model="form.approveUser"
                                placeholder="选择人员"
                filterable
                default-first-option
                :reserve-keyword="false"
                            >
                                <el-option
                                    v-for="user in userList"
@@ -172,18 +233,27 @@
    approveId: "",
    approveUser: "",
        approveDeptId: "",
    approveDeptName: "",
    approveReason: "",
    checkResult: "",
    tempFileIds: [],
    approverList: [] // æ–°å¢žå­—段,存储所有节点的审批人id
    approverList: [], // æ–°å¢žå­—段,存储所有节点的审批人id
    startDate: "", // è¯·å‡å¼€å§‹æ—¶é—´
    endDate: "", // è¯·å‡ç»“束时间
    price: null, // æŠ¥é”€é‡‘额
    location: "" // å‡ºå·®åœ°ç‚¹
  },
  rules: {
    approveTime: [{ required: false, message: "请输入", trigger: "change" },],
    approveId: [{ required: false, message: "请输入", trigger: "blur" }],
    approveUser: [{ required: false, message: "请输入", trigger: "blur" }],
        approveDeptId: [{ required: true, message: "请输入", trigger: "blur" }],
    approveDeptName: [{ required: true, message: "请输入", trigger: "blur" }],
    approveReason: [{ required: true, message: "请输入", trigger: "blur" }],
    checkResult: [{ required: false, message: "请输入", trigger: "blur" }],
    startDate: [{ required: true, message: "请选择请假开始时间", trigger: "change" }],
    endDate: [{ required: true, message: "请选择请假结束时间", trigger: "change" }],
    price: [{ required: true, message: "请输入报销金额", trigger: "blur" }],
    location: [{ required: true, message: "请输入出差地点", trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
@@ -211,7 +281,6 @@
// æ‰“开弹框
const openDialog = (type, row) => {
  console.log('openDialog', type, row)
  operationType.value = type;
  dialogFormVisible.value = true;
    userListNoPageByTenantId().then((res) => {
@@ -278,6 +347,36 @@
    proxy.$modal.msgError("请为所有审批节点选择审批人!")
    return
  }
  // å½“ approveType ä¸º 2 æ—¶ï¼Œæ ¡éªŒè¯·å‡æ—¶é—´
  if (props.approveType == 2) {
    if (!form.value.startDate) {
      proxy.$modal.msgError("请选择请假开始时间!")
      return
    }
    if (!form.value.endDate) {
      proxy.$modal.msgError("请选择请假结束时间!")
      return
    }
    // æ ¡éªŒç»“束时间不能早于开始时间
    if (new Date(form.value.endDate) < new Date(form.value.startDate)) {
      proxy.$modal.msgError("请假结束时间不能早于开始时间!")
      return
    }
  }
  // å½“ approveType ä¸º 3 æ—¶ï¼Œæ ¡éªŒå‡ºå·®åœ°ç‚¹
  if (props.approveType == 3) {
    if (!form.value.location || form.value.location.trim() === '') {
      proxy.$modal.msgError("请输入出差地点!")
      return
    }
  }
  // å½“ approveType ä¸º 4 æ—¶ï¼Œæ ¡éªŒæŠ¥é”€é‡‘额
  if (props.approveType == 4) {
    if (!form.value.price || form.value.price <= 0) {
      proxy.$modal.msgError("请输入有效的报销金额!")
      return
    }
  }
  proxy.$refs.formRef.validate(valid => {
    if (valid) {
      if (operationType.value === "add" || currentApproveStatus.value == 3) {
src/views/collaborativeApproval/approvalProcess/fileList.vue
@@ -2,10 +2,11 @@
  <el-dialog v-model="dialogVisible" title="附件" width="40%" :before-close="handleClose">
    <el-table :data="tableData" border height="40vh">
      <el-table-column label="附件名称" prop="name" min-width="400" show-overflow-tooltip />
      <el-table-column fixed="right" label="操作" width="100" align="center">
      <el-table-column fixed="right" label="操作" width="150" align="center">
        <template #default="scope">
          <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">下载</el-button>
          <el-button link type="primary" size="small" @click="lookFile(scope.row)">预览</el-button>
          <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
@@ -16,6 +17,8 @@
<script setup>
import { ref } from 'vue'
import filePreview from '@/components/filePreview/index.vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import { delCommonFile } from '@/api/publicApi/commonFile.js'
const dialogVisible = ref(false)
const tableData = ref([])
@@ -35,6 +38,27 @@
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
}
// åˆ é™¤é™„ä»¶
const handleDelete = (row) => {
  ElMessageBox.confirm(`确认删除附件"${row.name}"吗?`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    delCommonFile([row.id]).then(() => {
      ElMessage.success('删除成功')
      // ä»Žåˆ—表中移除已删除的附件
      const index = tableData.value.findIndex(item => item.id === row.id)
      if (index !== -1) {
        tableData.value.splice(index, 1)
      }
    }).catch(() => {
      ElMessage.error('删除失败')
    })
  }).catch(() => {
    ElMessage.info('已取消删除')
  })
}
defineExpose({
  open
})
src/views/collaborativeApproval/approvalProcess/index.vue
@@ -130,13 +130,18 @@
    width: 120
  },
  {
    label: "申请日期",
    prop: "approveTime",
    label: "金额(元)",
    prop: "price",
    width: 120
  },
  {
    label: props.approveType === 2 ? "开始日期" : "申请日期",
    prop: props.approveType === 2 ? "startDate" : "approveTime",
        width: 200
  },
  {
    label: "结束日期",
    prop: "approveOverTime",
    prop: props.approveType === 2 ? "endDate" : "approveOverTime",
    width: 120
  },
  {
@@ -157,7 +162,6 @@
        clickFun: (row) => {
          openForm("edit", row);
        },
                disabled: (row) => row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4
      },
      {
        name: "审核",
src/views/collaborativeApproval/noticeManagement/index.vue
@@ -10,16 +10,17 @@
    <!-- é€šçŸ¥å…¬å‘Šæ¿ -->
    <div class="notice-board">
      <!-- æ”¾å‡é€šçŸ¥åŒºåŸŸ -->
      <div class="notice-section" v-if="holidayNoticeCount > 0">
      <!-- ç»Ÿä¸€é€šçŸ¥åŒºåŸŸ -->
      <div class="notice-section" v-if="totalNoticeCount > 0">
        <div class="section-header">
          <h3>📅 æ”¾å‡é€šçŸ¥</h3>
          <span class="section-count">{{ holidayNoticeCount }}条</span>
          <h3>� é€šçŸ¥å…¬å‘Š</h3>
          <span class="section-count">{{ totalNoticeCount }}条</span>
        </div>
        <div class="notice-cards">
          <!-- æ”¾å‡é€šçŸ¥ -->
          <div
              v-for="notice in holidayNotices"
              :key="notice.id"
              :key="'holiday-' + notice.id"
              class="notice-card holiday-card"
              :class="{ 'urgent': notice.priority === '3' }"
          >
@@ -40,6 +41,9 @@
            </div>
            <div class="card-footer">
              <div class="card-meta">
                <span class="type" :class="'type-' + notice.type">
                  {{ notice.type }}
                </span>
                <span class="priority" :class="'priority-' + notice.priority">
                  {{ getPriorityText(notice.priority) }}
                </span>
@@ -59,27 +63,11 @@
              <span>{{ notice.remark }}</span>
            </div>
          </div>
        </div>
      </div>
      <pagination
          v-if="holidayNoticePage.total > 0"
          :total="holidayNoticePage.total"
          :page="holidayNoticePage.current"
          :limit="holidayNoticePage.size"
          @pagination="handleHolidayNoticeCurrentChange"
      />
      <!-- è®¾å¤‡ç»´ä¿®é€šçŸ¥åŒºåŸŸ -->
      <div class="notice-section" v-if="maintenanceNoticeCount > 0">
        <div class="section-header">
          <h3>🔧 è®¾å¤‡ç»´ä¿®é€šçŸ¥</h3>
          <span class="section-count">{{ maintenanceNoticeCount }}条</span>
        </div>
        <div class="notice-cards">
          <!-- è®¾å¤‡ç»´ä¿®é€šçŸ¥ -->
          <div
              v-for="notice in maintenanceNotices"
              :key="notice.id"
              :key="'maintenance-' + notice.id"
              class="notice-card maintenance-card"
              :class="{ 'urgent': notice.priority === '3' }"
          >
@@ -122,12 +110,13 @@
        </div>
      </div>
      <!-- ç»Ÿä¸€åˆ†é¡µ -->
      <pagination
          v-if="maintenanceNoticePage.total > 0"
          :total="maintenanceNoticePage.total"
          :page="maintenanceNoticePage.current"
          :limit="maintenanceNoticePage.size"
          @pagination="handleMaintenanceNoticeCurrentChange"
          v-if="(holidayNoticePage.total + maintenanceNoticePage.total) > 0"
          :total="holidayNoticePage.total + maintenanceNoticePage.total"
          :page="Math.max(holidayNoticePage.current, maintenanceNoticePage.current)"
          :limit="Math.max(holidayNoticePage.size, maintenanceNoticePage.size)"
          @pagination="handleCurrentChange"
      />
      <!-- ç©ºçŠ¶æ€ -->
@@ -153,10 +142,7 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="公告类型" prop="type">
              <el-select v-model="form.type" placeholder="请选择公告类型" style="width: 100%">
                <el-option label="放假通知" :value="1"/>
                <el-option label="设备维修通知" :value="2"/>
              </el-select>
                            <el-input v-model="form.type" placeholder="请输入公告标题"/>
            </el-form-item>
          </el-col>
        </el-row>
@@ -419,16 +405,10 @@
  });
};
const holidayNoticeCount = ref()
const maintenanceNoticeCount = ref()
const totalNoticeCount = ref(0)
const fetchCount = () => {
  getCount().then(res => {
    holidayNoticeCount.value = res.data.filter(item => {
      return item.type === 1
    })[0].count;
    maintenanceNoticeCount.value = res.data.filter(item => {
      return item.type === 2
    })[0].count;
    totalNoticeCount.value = res.data.reduce((total, item) => total + item.count, 0);
  });
}
@@ -447,7 +427,7 @@
})
const fetchHolidayNotices = () => {
  listNotice({...holidayNoticePage.value, type: 1}).then(res => {
  listNotice({...holidayNoticePage.value}).then(res => {
    holidayNotices.value = res.data.records
    holidayNoticePage.value.total = res.data.total
  });
@@ -460,15 +440,12 @@
  });
};
const handleHolidayNoticeCurrentChange = (val) => {
const handleCurrentChange = (val) => {
  holidayNoticePage.value.size = val.limit
  holidayNoticePage.value.current = val.page
  fetchHolidayNotices()
};
const handleMaintenanceNoticeCurrentChange = (val) => {
  maintenanceNoticePage.value.size = val.limit
  maintenanceNoticePage.value.current = val.page
  fetchHolidayNotices()
  fetchMaintenanceNotices()
};
@@ -638,13 +615,23 @@
  gap: 8px;
}
.priority, .status {
.type, .priority, .status {
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}
.type-1 {
  background: #f0f9ff;
  color: #0369a1;
}
.type-2 {
  background: #fef3c7;
  color: #d97706;
}
.priority-1 {
  background: #f0f9ff;
  color: #0369a1;
src/views/customerService/expiryAfterSales/index.vue
@@ -59,7 +59,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('edit', row)">编辑</el-button>
                </template>
            </PIMTable>
        </div>
src/views/customerService/feedbackRegistration/index.vue
@@ -120,9 +120,6 @@
                clickFun: (row) => {
                    openForm("edit", row);
                },
                disabled: (row) => {
                    return row.checkUserId !== userStore.id || row.status !== 1
                }
            },
        ],
    },
@@ -172,12 +169,6 @@
const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
        // æ£€æŸ¥æ˜¯å¦æœ‰ä»–人维护的数据
        const unauthorizedData = selectedRows.value.filter(item => item.checkUserId !== userStore.id);
        if (unauthorizedData.length > 0) {
            proxy.$modal.msgWarning("不可删除他人维护的数据");
            return;
        }
        ids = selectedRows.value.map((item) => item.id);
    } else {
        proxy.$modal.msgWarning("请选择数据");
src/views/equipmentManagement/calibration/index.vue
@@ -57,10 +57,10 @@
<script setup>
import {onMounted, ref} from "vue";
import {ElMessageBox} from "element-plus";
import {ElMessageBox, ElMessage} from "element-plus";
import useUserStore from "@/store/modules/user.js";
import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue";
import {ledgerRecordListPage} from "@/api/equipmentManagement/calibration.js";
import {ledgerRecordListPage, ledgerRecordDelete} from "@/api/equipmentManagement/calibration.js";
const { proxy } = getCurrentInstance();
const userStore = useUserStore()
@@ -134,6 +134,7 @@
    {
        dataType: "action",
        label: "操作",
        width: 100,
        align: "center",
        fixed: 'right',
        operation: [
@@ -143,9 +144,16 @@
                clickFun: (row) => {
                    openCalibrationDia("edit", row);
                },
                disabled: (row) => {
                    return row.userId !== userStore.id
                }
            },
            {
                name: "删除",
                type: "text",
                style: {
                    color: "#F56C6C"
                },
                clickFun: (row) => {
                    handleDelete(row);
                },
            },
        ],
    },
@@ -194,6 +202,26 @@
    })
}
// åˆ é™¤è®°å½•
const handleDelete = (row) => {
    ElMessageBox.confirm(`确认删除计量器具编号为"${row.code}"的检定记录吗?`, "删除确认", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => {
            ledgerRecordDelete([row.id]).then(() => {
                ElMessage.success("删除成功");
                getList();
            }).catch(() => {
                ElMessage.error("删除失败");
            });
        })
        .catch(() => {
            proxy.$modal.msg("已取消删除");
        });
};
// å¯¼å‡º
const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
src/views/equipmentManagement/inspectionManagement/components/formDia.vue
@@ -1,102 +1,116 @@
<template>
  <div>
    <el-dialog :title="operationType === 'add' ? '新增巡检任务' : '编辑巡检任务'"
               v-model="dialogVisitable" width="800px" @close="cancel">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="设备名称" prop="taskId">
              <el-select v-model="form.taskId" @change="setDeviceModel">
                <el-option
                  v-for="(item, index) in deviceOptions"
                  :key="index"
                  :label="item.deviceName"
                  :value="item.id"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="巡检人" prop="inspector">
              <el-select v-model="form.inspector" placeholder="请选择" multiple clearable>
                <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/>
              </el-select>
            </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>
          </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"/>
                <el-option label="每周" value="WEEKLY"/>
                <el-option label="每月" value="MONTHLY"/>
                <!-- <el-option label="季度" value="QUARTERLY"/> -->
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType">
            <el-form-item label="日期" prop="frequencyDetail">
              <el-time-picker v-model="form.frequencyDetail" placeholder="选择时间" format="HH:mm"
                              value-format="HH:mm" />
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType">
            <el-form-item label="日期" prop="frequencyDetail">
              <el-select v-model="form.week" placeholder="请选择" clearable style="width: 50%">
                <el-option label="周一" value="MON"/>
                <el-option label="周二" value="TUE"/>
                <el-option label="周三" value="WED"/>
                <el-option label="周四" value="THU"/>
                <el-option label="周五" value="FRI"/>
                <el-option label="周六" value="SAT"/>
                <el-option label="周日" value="SUN"/>
              </el-select>
              <el-time-picker v-model="form.time" placeholder="选择时间" format="HH:mm"
                              value-format="HH:mm"  style="width: 50%"/>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType">
            <el-form-item label="日期" prop="frequencyDetail">
              <el-date-picker
                  v-model="form.frequencyDetail"
                  type="datetime"
                  clearable
                  placeholder="选择开始日期"
                  format="DD,HH:mm"
                  value-format="DD,HH:mm"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType">
            <el-form-item label="日期" prop="frequencyDetail">
              <el-date-picker
                  v-model="form.frequencyDetail"
                  type="datetime"
                  clearable
                  placeholder="选择开始日期"
                  format="MM,DD,HH:mm"
                  value-format="MM,DD,HH:mm"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="submitForm">保存</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
    <div>
        <el-dialog :title="operationType === 'add' ? '新增巡检任务' : '编辑巡检任务'"
                             v-model="dialogVisitable" width="800px" @close="cancel">
            <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="设备名称" prop="taskId">
                            <el-select v-model="form.taskId" @change="setDeviceModel" filterable>
                                <el-option
                                    v-for="(item, index) in deviceOptions"
                                    :key="index"
                                    :label="item.deviceName"
                                    :value="item.id"
                                ></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="巡检人" prop="inspector">
                            <el-select v-model="form.inspector"                 filterable
                                                 default-first-option
                                                 :reserve-keyword="false" placeholder="请选择" multiple clearable>
                                <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/>
                            </el-select>
                        </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>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="登记时间" prop="dateStr">
                            <el-date-picker
                                v-model="form.dateStr"
                                type="date"
                                placeholder="选择登记日期"
                                format="YYYY-MM-DD"
                                value-format="YYYY-MM-DD"
                                style="width: 100%"
                            />
                        </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"/>
                                <el-option label="每周" value="WEEKLY"/>
                                <el-option label="每月" value="MONTHLY"/>
                                <!-- <el-option label="季度" value="QUARTERLY"/> -->
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-time-picker v-model="form.frequencyDetail" placeholder="选择时间" format="HH:mm"
                                                            value-format="HH:mm" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-select v-model="form.week" placeholder="请选择" clearable style="width: 50%">
                                <el-option label="周一" value="MON"/>
                                <el-option label="周二" value="TUE"/>
                                <el-option label="周三" value="WED"/>
                                <el-option label="周四" value="THU"/>
                                <el-option label="周五" value="FRI"/>
                                <el-option label="周六" value="SAT"/>
                                <el-option label="周日" value="SUN"/>
                            </el-select>
                            <el-time-picker v-model="form.time" placeholder="选择时间" format="HH:mm"
                                                            value-format="HH:mm"  style="width: 50%"/>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-date-picker
                                v-model="form.frequencyDetail"
                                type="datetime"
                                clearable
                                placeholder="选择开始日期"
                                format="DD,HH:mm"
                                value-format="DD,HH:mm"
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType">
                        <el-form-item label="日期" prop="frequencyDetail">
                            <el-date-picker
                                v-model="form.frequencyDetail"
                                type="datetime"
                                clearable
                                placeholder="选择开始日期"
                                format="MM,DD,HH:mm"
                                value-format="MM,DD,HH:mm"
                            />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="cancel">取消</el-button>
                    <el-button type="primary" @click="submitForm">保存</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>
<script setup>
@@ -113,115 +127,117 @@
const operationType = ref('add');
const deviceOptions = ref([]);
const data = reactive({
  form: {
    taskId: undefined,
    taskName: undefined,
    inspector: '',
    inspectorIds: '',
    remarks: '',
    frequencyType: '',
    frequencyDetail: '',
    week: '',
    time: ''
  },
  rules: {
    taskId: [{ required: true, message: "请选择设备", trigger: "change" },],
    inspector: [{ required: true, message: "请输入巡检人", trigger: "blur" },],
  }
    form: {
        taskId: undefined,
        taskName: undefined,
        inspector: '',
        inspectorIds: '',
        remarks: '',
        frequencyType: '',
        frequencyDetail: '',
        week: '',
        time: '',
        dateStr: ''
    },
    rules: {
        taskId: [{ required: true, message: "请选择设备", trigger: "change" },],
        inspector: [{ required: true, message: "请输入巡检人", trigger: "blur" },],
        dateStr: [{ required: true, message: "请选择登记时间", trigger: "change" }]
    }
})
const { form, rules } = toRefs(data)
const userList = ref([])
const loadDeviceName = async () => {
  const { data } = await getDeviceLedger();
  deviceOptions.value = data;
    const { data } = await getDeviceLedger();
    deviceOptions.value = data;
};
const setDeviceModel = (id) => {
  const option = deviceOptions.value.find((item) => item.id === id);
  if (option) {
    form.value.taskName = option.deviceName;
  }
    const option = deviceOptions.value.find((item) => item.id === id);
    if (option) {
        form.value.taskName = option.deviceName;
    }
}
// æ‰“开弹框
const openDialog = async (type, row) => {
  dialogVisitable.value = true
  operationType.value = type
  // é‡ç½®è¡¨å•
  resetForm();
  // åŠ è½½ç”¨æˆ·åˆ—è¡¨
  userListNoPageByTenantId().then((res) => {
    userList.value = res.data;
  });
  // åŠ è½½è®¾å¤‡åˆ—è¡¨
  await loadDeviceName();
  if (type === 'edit' && row) {
    form.value = {...row}
    form.value.inspector = form.value.inspectorIds.split(',').map(Number)
    // å¦‚果有设备ID,自动设置设备信息
    if (form.value.taskId) {
      setDeviceModel(form.value.taskId);
    }
  }
    dialogVisitable.value = true
    operationType.value = type
    // é‡ç½®è¡¨å•
    resetForm();
    // åŠ è½½ç”¨æˆ·åˆ—è¡¨
    userListNoPageByTenantId().then((res) => {
        userList.value = res.data;
    });
    // åŠ è½½è®¾å¤‡åˆ—è¡¨
    await loadDeviceName();
    if (type === 'edit' && row) {
        form.value = {...row}
        form.value.inspector = form.value.inspectorIds.split(',').map(Number)
        // å¦‚果有设备ID,自动设置设备信息
        if (form.value.taskId) {
            setDeviceModel(form.value.taskId);
        }
    }
}
// å…³é—­å¯¹è¯æ¡†
const cancel = () => {
  resetForm()
  dialogVisitable.value = false
  emit('closeDia')
    resetForm()
    dialogVisitable.value = false
    emit('closeDia')
}
// é‡ç½®è¡¨å•函数
const resetForm = () => {
  if (proxy.$refs.formRef) {
    proxy.$refs.formRef.resetFields()
  }
  // é‡ç½®è¡¨å•数据确保设备信息正确重置
  form.value = {
    taskId: undefined,
    taskName: undefined,
    inspector: '',
    inspectorIds: '',
    remarks: '',
    frequencyType: '',
    frequencyDetail: '',
    week: '',
    time: ''
  }
    if (proxy.$refs.formRef) {
        proxy.$refs.formRef.resetFields()
    }
    // é‡ç½®è¡¨å•数据确保设备信息正确重置
    form.value = {
        taskId: undefined,
        taskName: undefined,
        inspector: '',
        inspectorIds: '',
        remarks: '',
        frequencyType: '',
        frequencyDetail: '',
        week: '',
        time: ''
    }
}
// æäº¤è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate(async valid => {
    if (valid) {
      try {
        form.value.inspectorIds = form.value.inspector.join(',')
        delete form.value.inspector
        if (form.value.frequencyType === 'WEEKLY') {
          let frequencyDetail = ''
          frequencyDetail = form.value.week + ',' + form.value.time
          form.value.frequencyDetail = frequencyDetail
        }
        let res = await userStore.getInfo()
        form.value.registrantId = res.user.userId
        await addOrEditTimingTask(form.value)
        cancel()
        proxy.$modal.msgSuccess('提交成功')
      } catch (error) {
        proxy.$modal.msgError('提交失败,请重试')
      }
    }
  })
    proxy.$refs["formRef"].validate(async valid => {
        if (valid) {
            try {
                form.value.inspectorIds = form.value.inspector.join(',')
                delete form.value.inspector
                if (form.value.frequencyType === 'WEEKLY') {
                    let frequencyDetail = ''
                    frequencyDetail = form.value.week + ',' + form.value.time
                    form.value.frequencyDetail = frequencyDetail
                }
                let res = await userStore.getInfo()
                form.value.registrantId = res.user.userId
                await addOrEditTimingTask(form.value)
                cancel()
                proxy.$modal.msgSuccess('提交成功')
            } catch (error) {
                proxy.$modal.msgError('提交失败,请重试')
            }
        }
    })
}
defineExpose({ openDialog })
</script>
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
@@ -32,7 +32,7 @@
        
        <!-- ç”Ÿäº§åŽ -->
        <div class="form-container">
          <div class="title">生产后</div>
          <div class="title">生产中</div>
          
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
@@ -59,7 +59,7 @@
        
        <!-- ç”Ÿäº§é—®é¢˜ -->
        <div class="form-container">
          <div class="title">生产问题</div>
          <div class="title">生产后</div>
          
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
src/views/equipmentManagement/inspectionManagement/index.vue
@@ -1,80 +1,78 @@
<template>
  <div class="app-container">
    <el-form :inline="true" :model="queryParams" class="search-form">
      <el-form-item label="搜索">
        <el-input
            v-model="queryParams.searchAll"
            placeholder="请输入关键字"
            clearable
            :style="{ width: '100%' }"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleQuery">查询</el-button>
        <el-button @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-card>
      <div style="display: flex;flex-direction: row;justify-content: space-between;margin-bottom: 10px;">
        <el-radio-group v-model="activeRadio" @change="radioChange">
          <el-radio-button v-for="tab in radios"
                           :key="tab.name"
                           :label="tab.label"
                           :value="tab.name"/>
        </el-radio-group>
        <!-- æ“ä½œæŒ‰é’®åŒº -->
        <el-space v-if="activeRadio !== 'task'">
          <el-button type="primary" :icon="Plus" @click="handleAdd(undefined)">新建</el-button>
          <el-button type="danger" :icon="Delete" @click="handleDelete">删除</el-button>
          <el-button @click="handleOut">导出</el-button>
        </el-space>
        <el-space v-else>
          <el-button @click="handleOut">导出</el-button>
        </el-space>
      </div>
      <div>
        <div>
          <PIMTable :table-loading="tableLoading"
                  :table-data="tableData"
                  :column="tableColumns"
                  @selection-change="handleSelectionChange"
                  :is-selection="true"
                  :border="true"
                  :table-style="{ width: '100%', height: 'calc(100vh - 23em)' }"
          >
          <template #inspector="{ row }">
            <div class="person-tags">
              <!-- è°ƒè¯•信息,上线时删除 -->
              <!-- {{ console.log('inspector data:', row.inspector) }} -->
              <template v-if="row.inspector && row.inspector.length > 0">
                <el-tag
                  v-for="(person, index) in row.inspector"
                  :key="index"
                  size="small"
                  type="primary"
                  class="person-tag"
                >
                  {{ person }}
                </el-tag>
              </template>
              <span v-else class="no-data">--</span>
            </div>
          </template>
            </PIMTable>
        </div>
        <pagination
            v-if="total>0"
            :page="pageNum"
            :limit="pageSize"
            :total="total"
            @pagination="handlePagination"
            :layout="'total, prev, pager, next, jumper'"
        />
      </div>
    </el-card>
    <form-dia ref="formDia" @closeDia="handleQuery"></form-dia>
    <view-files ref="viewFiles"></view-files>
  </div>
    <div class="app-container">
        <el-form :inline="true" :model="queryParams" class="search-form">
            <el-form-item label="搜索">
                <el-input
                    v-model="queryParams.searchAll"
                    placeholder="请输入关键字"
                    clearable
                    :style="{ width: '100%' }"
                />
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="handleQuery">查询</el-button>
                <el-button @click="resetQuery">重置</el-button>
            </el-form-item>
        </el-form>
        <el-card>
            <div style="display: flex;flex-direction: row;justify-content: space-between;margin-bottom: 10px;">
                <el-radio-group v-model="activeRadio" @change="radioChange">
                    <el-radio-button v-for="tab in radios"
                                                     :key="tab.name"
                                                     :label="tab.label"
                                                     :value="tab.name"/>
                </el-radio-group>
                <!-- æ“ä½œæŒ‰é’®åŒº -->
                <el-space v-if="activeRadio !== 'task'">
                    <el-button type="primary" :icon="Plus" @click="handleAdd(undefined)">新建</el-button>
                    <el-button type="danger" :icon="Delete" @click="handleDelete">删除</el-button>
                    <el-button @click="handleOut">导出</el-button>
                </el-space>
                <el-space v-else>
                    <el-button @click="handleOut">导出</el-button>
                </el-space>
            </div>
            <div>
                <div>
                    <PIMTable :table-loading="tableLoading"
                                        :table-data="tableData"
                                        :column="tableColumns"
                                        @selection-change="handleSelectionChange"
                                        :is-selection="true"
                                        :border="true"
                                        :table-style="{ width: '100%', height: 'calc(100vh - 23em)' }"
                                        :page="{
          current: pageNum,
          size: pageSize,
          total: total,
        }"
                                        @pagination="pagination"
                    >
                        <template #inspector="{ row }">
                            <div class="person-tags">
                                <!-- è°ƒè¯•信息,上线时删除 -->
                                <!-- {{ console.log('inspector data:', row.inspector) }} -->
                                <template v-if="row.inspector && row.inspector.length > 0">
                                    <el-tag
                                        v-for="(person, index) in row.inspector"
                                        :key="index"
                                        size="small"
                                        type="primary"
                                        class="person-tag"
                                    >
                                        {{ person }}
                                    </el-tag>
                                </template>
                                <span v-else class="no-data">--</span>
                            </div>
                        </template>
                    </PIMTable>
                </div>
            </div>
        </el-card>
        <form-dia ref="formDia" @closeDia="handleQuery"></form-dia>
        <view-files ref="viewFiles"></view-files>
    </div>
</template>
<script setup>
@@ -90,9 +88,9 @@
// æŽ¥å£å¼•å…¥
import {
  delTimingTask,
  inspectionTaskList,
  timingTaskList
    delTimingTask,
    inspectionTaskList,
    timingTaskList
} from "@/api/inspectionManagement/index.js";
// å…¨å±€å˜é‡
@@ -102,14 +100,14 @@
// æŸ¥è¯¢å‚æ•°
const queryParams = reactive({
  searchAll: "",
    searchAll: "",
});
// å•选框配置
const activeRadio = ref("taskManage");
const radios = reactive([
  { name: "taskManage", label: "定时任务管理" },
  { name: "task", label: "定时任务记录" },
    { name: "taskManage", label: "定时任务管理" },
    { name: "task", label: "定时任务记录" },
]);
// è¡¨æ ¼æ•°æ®
@@ -124,234 +122,233 @@
// åˆ—配置
const columns = ref([
  { prop: "taskName", label: "巡检任务名称", minWidth: 160 },
  { prop: "remarks", label: "备注", minWidth: 150 },
  { prop: "inspector", label: "执行巡检人", minWidth: 150, slot: "inspector" },
  {
    prop: "frequencyType",
    label: "频次",
    minWidth: 150,
    formatter: (_, __, val) => ({
      DAILY: "每日",
      WEEKLY: "每周",
      MONTHLY: "每月",
      QUARTERLY: "季度"
    }[val] || "")
  },
  {
    prop: "frequencyDetail",
    label: "开始日期与时间",
    minWidth: 150,
    formatter: (row, column, cellValue) => {
      // å…ˆåˆ¤æ–­æ˜¯å¦æ˜¯å­—符串
      if (typeof cellValue !== 'string') return '';
      let val = cellValue;
      const replacements = {
        MON: '周一',
        TUE: '周二',
        WED: '周三',
        THU: '周四',
        FRI: '周五',
        SAT: '周六',
        SUN: '周日'
      };
      // ä½¿ç”¨æ­£åˆ™ä¸€æ¬¡æ€§æ›¿æ¢æ‰€æœ‰åŒ¹é…é¡¹
      return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]);
    }
  },
  { prop: "registrant", label: "登记人", minWidth: 100 },
  { prop: "createTime", label: "登记日期", minWidth: 100 },
    { prop: "taskName", label: "巡检任务名称", minWidth: 160 },
    { prop: "remarks", label: "备注", minWidth: 150 },
    { prop: "inspector", label: "执行巡检人", minWidth: 150, slot: "inspector" },
    {
        prop: "frequencyType",
        label: "频次",
        minWidth: 150,
        formatter: (_, __, val) => ({
            DAILY: "每日",
            WEEKLY: "每周",
            MONTHLY: "每月",
            QUARTERLY: "季度"
        }[val] || "")
    },
    {
        prop: "frequencyDetail",
        label: "开始日期与时间",
        minWidth: 150,
        formatter: (row, column, cellValue) => {
            // å…ˆåˆ¤æ–­æ˜¯å¦æ˜¯å­—符串
            if (typeof cellValue !== 'string') return '';
            let val = cellValue;
            const replacements = {
                MON: '周一',
                TUE: '周二',
                WED: '周三',
                THU: '周四',
                FRI: '周五',
                SAT: '周六',
                SUN: '周日'
            };
            // ä½¿ç”¨æ­£åˆ™ä¸€æ¬¡æ€§æ›¿æ¢æ‰€æœ‰åŒ¹é…é¡¹
            return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]);
        }
    },
    { prop: "registrant", label: "登记人", minWidth: 100 },
    { prop: "dateStr", label: "登记日期", minWidth: 100 },
]);
// æ“ä½œåˆ—配置
const getOperationColumn = (operations) => {
  if (!operations || operations.length === 0) return null;
  const operationConfig = {
    label: "操作",
    width: 130,
    fixed: "right",
    dataType: "action",
    operation: operations.map(op => {
      switch (op) {
        case 'edit':
          return {
            name: "编辑",
            clickFun: handleAdd,
            color: "#409EFF"
          };
        case 'viewFile':
          return {
            name: "查看附件",
            clickFun: viewFile,
            color: "#67C23A"
          };
        default:
          return null;
      }
    }).filter(Boolean)
  };
  return operationConfig;
    if (!operations || operations.length === 0) return null;
    const operationConfig = {
        label: "操作",
        width: 130,
        fixed: "right",
        dataType: "action",
        operation: operations.map(op => {
            switch (op) {
                case 'edit':
                    return {
                        name: "编辑",
                        clickFun: handleAdd,
                        color: "#409EFF"
                    };
                case 'viewFile':
                    return {
                        name: "查看附件",
                        clickFun: viewFile,
                        color: "#67C23A"
                    };
                default:
                    return null;
            }
        }).filter(Boolean)
    };
    return operationConfig;
};
onMounted(() => {
  radioChange('taskManage');
    radioChange('taskManage');
});
// å•选变化
const radioChange = (value) => {
  if (value === "taskManage") {
    const operationColumn = getOperationColumn(['edit']);
    tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])];
    operationsArr.value = ['edit'];
  } else if (value === "task") {
    const operationColumn = getOperationColumn(['viewFile']);
    tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])];
    operationsArr.value = ['viewFile'];
  }
  pageNum.value = 1;
  pageSize.value = 10;
  getList();
    if (value === "taskManage") {
        const operationColumn = getOperationColumn(['edit']);
        tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])];
        operationsArr.value = ['edit'];
    } else if (value === "task") {
        const operationColumn = getOperationColumn(['viewFile']);
        tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])];
        operationsArr.value = ['viewFile'];
    }
    pageNum.value = 1;
    pageSize.value = 10;
    getList();
};
// æŸ¥è¯¢æ“ä½œ
const handleQuery = () => {
  pageNum.value = 1;
  pageSize.value = 10;
  getList();
    pageNum.value = 1;
    pageSize.value = 10;
    getList();
};
// åˆ†é¡µå¤„理
const handlePagination = (val) => {
    pageNum.value = val.page;
    pageSize.value = val.size;
const pagination = (obj) => {
    pageNum.value = obj.page;
    pageSize.value = obj.limit;
    getList();
};
// èŽ·å–åˆ—è¡¨æ•°æ®
const getList = () => {
  tableLoading.value = true;
  const params = { ...queryParams, size: pageSize.value, current: pageNum.value };
  let apiCall;
  if (activeRadio.value === "task") {
    apiCall = inspectionTaskList(params);
  } else {
    apiCall = timingTaskList(params);
  }
  apiCall.then(res => {
    const rawData = res.data.records || [];
    // å¤„理 inspector å­—段,将字符串转换为数组(适用于所有情况)
    tableData.value = rawData.map(item => {
      const processedItem = { ...item };
      // å¤„理 inspector å­—段
      if (processedItem.inspector) {
        if (typeof processedItem.inspector === 'string') {
          // å­—符串按逗号分割
          processedItem.inspector = processedItem.inspector.split(',').map(s => s.trim()).filter(s => s);
        } else if (!Array.isArray(processedItem.inspector)) {
          // éžæ•°ç»„转为数组
          processedItem.inspector = [processedItem.inspector];
        }
      } else {
        // ç©ºå€¼è®¾ä¸ºç©ºæ•°ç»„
        processedItem.inspector = [];
      }
      return processedItem;
    });
    total.value = res.data.total || 0;
  }).finally(() => {
    tableLoading.value = false;
  });
    tableLoading.value = true;
    const params = { ...queryParams, size: pageSize.value, current: pageNum.value };
    let apiCall;
    if (activeRadio.value === "task") {
        apiCall = inspectionTaskList(params);
    } else {
        apiCall = timingTaskList(params);
    }
    apiCall.then(res => {
        const rawData = res.data.records || [];
        // å¤„理 inspector å­—段,将字符串转换为数组(适用于所有情况)
        tableData.value = rawData.map(item => {
            const processedItem = { ...item };
            // å¤„理 inspector å­—段
            if (processedItem.inspector) {
                if (typeof processedItem.inspector === 'string') {
                    // å­—符串按逗号分割
                    processedItem.inspector = processedItem.inspector.split(',').map(s => s.trim()).filter(s => s);
                } else if (!Array.isArray(processedItem.inspector)) {
                    // éžæ•°ç»„转为数组
                    processedItem.inspector = [processedItem.inspector];
                }
            } else {
                // ç©ºå€¼è®¾ä¸ºç©ºæ•°ç»„
                processedItem.inspector = [];
            }
            return processedItem;
        });
        total.value = res.data.total || 0;
    }).finally(() => {
        tableLoading.value = false;
    });
};
// é‡ç½®æŸ¥è¯¢
const resetQuery = () => {
  for (const key in queryParams) {
    if (!["pageNum", "pageSize"].includes(key)) {
      queryParams[key] = "";
    }
  }
  handleQuery();
    for (const key in queryParams) {
        if (!["pageNum", "pageSize"].includes(key)) {
            queryParams[key] = "";
        }
    }
    handleQuery();
};
// æ–°å¢ž / ç¼–辑
const handleAdd = (row) => {
  const type = row ? 'edit' : 'add';
  nextTick(() => {
    formDia.value?.openDialog(type, row);
  });
    const type = row ? 'edit' : 'add';
    nextTick(() => {
        formDia.value?.openDialog(type, row);
    });
};
// æŸ¥çœ‹é™„ä»¶
const viewFile = (row) => {
  nextTick(() => {
    viewFiles.value?.openDialog(row);
  });
    nextTick(() => {
        viewFiles.value?.openDialog(row);
    });
};
// åˆ é™¤æ“ä½œ
const handleDelete = () => {
  if (!selectedRows.value.length) {
    proxy.$modal.msgWarning("请选择要删除的数据");
    return;
  }
  const deleteIds = selectedRows.value.map(item => item.id);
  proxy.$modal.confirm('是否确认删除所选数据项?').then(() => {
    return delTimingTask(deleteIds);
  }).then(() => {
    proxy.$modal.msgSuccess("删除成功");
    handleQuery();
  }).catch(() => {});
    if (!selectedRows.value.length) {
        proxy.$modal.msgWarning("请选择要删除的数据");
        return;
    }
    const deleteIds = selectedRows.value.map(item => item.id);
    proxy.$modal.confirm('是否确认删除所选数据项?').then(() => {
        return delTimingTask(deleteIds);
    }).then(() => {
        proxy.$modal.msgSuccess("删除成功");
        handleQuery();
    }).catch(() => {});
};
// å¤šé€‰å˜æ›´
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
    selectedRows.value = selection;
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      // æ ¹æ®å½“前选中的标签页调用不同的导出接口
      if (activeRadio.value === "taskManage") {
        // å®šæ—¶ä»»åŠ¡ç®¡ç†
        proxy.download("/timingTask/export", {}, "定时任务管理.xlsx");
      } else if (activeRadio.value === "task") {
        // å®šæ—¶ä»»åŠ¡è®°å½•
        proxy.download("/inspectionTask/export", {}, "定时任务记录.xlsx");
      }
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => {
            // æ ¹æ®å½“前选中的标签页调用不同的导出接口
            if (activeRadio.value === "taskManage") {
                // å®šæ—¶ä»»åŠ¡ç®¡ç†
                proxy.download("/timingTask/export", {}, "定时任务管理.xlsx");
            } else if (activeRadio.value === "task") {
                // å®šæ—¶ä»»åŠ¡è®°å½•
                proxy.download("/inspectionTask/export", {}, "定时任务记录.xlsx");
            }
        })
        .catch(() => {
            proxy.$modal.msg("已取消");
        });
};
</script>
<style scoped>
.person-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.person-tag {
  margin-right: 4px;
  margin-bottom: 2px;
    margin-right: 4px;
    margin-bottom: 2px;
}
.no-data {
  color: #909399;
  font-size: 14px;
    color: #909399;
    font-size: 14px;
}
</style>
src/views/equipmentManagement/ledger/index.vue
@@ -82,15 +82,14 @@
      </PIMTable>
    </div>
    <Modal ref="modalRef" @success="getTableData"></Modal>
        <el-dialog v-model="qrDialogVisible" title="二维码" width="300px">
            <div style="text-align:center;">
                <img :src="qrCodeUrl" alt="二维码" style="width:200px;height:200px;" />
                <div style="margin-top:6px;font-size:14px;color:#333;">{{ qrRowData?.deviceName }}</div>
                <div style="margin:10px 0;">
                    <el-button type="primary" @click="downloadQRCode">下载二维码图片</el-button>
                </div>
            </div>
        </el-dialog>
    <el-dialog v-model="qrDialogVisible" title="二维码" width="300px">
      <div style="text-align:center;">
        <img :src="qrCodeUrl" alt="二维码" style="width:200px;height:200px;" />
        <div style="margin:10px 0;">
          <el-button type="primary" @click="downloadQRCode">下载二维码图片</el-button>
        </div>
      </div>
    </el-dialog>
  </div>
</template>
@@ -300,44 +299,10 @@
};
const downloadQRCode = () => {
    const name = qrRowData.value?.deviceName || "二维码";
    const img = new Image();
    img.src = qrCodeUrl.value;
    img.onload = () => {
        const padding = 10;
        const qrSize = 200;
        const textHeight = 24; // space for text
        const width = qrSize + padding * 2;
        const height = qrSize + padding * 2 + textHeight;
        const canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;
        const ctx = canvas.getContext("2d");
        // background
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(0, 0, width, height);
        // draw QR centered
        ctx.drawImage(img, padding, padding, qrSize, qrSize);
        // draw name centered below
        ctx.fillStyle = "#333";
        ctx.font = "14px Arial";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        const maxTextWidth = width - padding * 2;
        let displayName = name;
        // ellipsis if too long
        while (ctx.measureText(displayName).width > maxTextWidth && displayName.length > 0) {
            displayName = displayName.slice(0, -1);
        }
        if (displayName !== name) displayName = displayName + "…";
        ctx.fillText(displayName, width / 2, qrSize + padding + textHeight / 2);
        const dataUrl = canvas.toDataURL("image/png");
        const a = document.createElement("a");
        a.href = dataUrl;
        a.download = `${name}.png`;
        a.click();
    };
  const a = document.createElement("a");
  a.href = qrCodeUrl.value;
  a.download = `${qrRowData.value.deviceName || "二维码"}.png`;
  a.click();
};
onMounted(() => {
src/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue
@@ -67,7 +67,9 @@
                            <el-select
                                v-model="form.userId"
                                placeholder="请选择"
                                disabled
                filterable
                default-first-option
                :reserve-keyword="false"
                                clearable
                            >
                                <el-option
src/views/equipmentManagement/measurementEquipment/components/formDia.vue
@@ -64,7 +64,9 @@
                                v-model="form.userId"
                                placeholder="请选择"
                                clearable
                                disabled
                filterable
                default-first-option
                :reserve-keyword="false"
                            >
                                <el-option
                                    v-for="item in userList"
src/views/equipmentManagement/measurementEquipment/index.vue
@@ -148,13 +148,13 @@
                    openCalibrationDia("verifying", row);
                },
            },
            {
                name: "附件",
                type: "text",
                clickFun: (row) => {
          openFilesFormDia(row);
                },
            },
            // {
            //     name: "附件",
            //     type: "text",
            //     clickFun: (row) => {
      //     openFilesFormDia(row);
            //     },
            // },
        ],
    },
]);
@@ -221,12 +221,6 @@
const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
        // æ£€æŸ¥æ˜¯å¦æœ‰ä»–人维护的数据
        const unauthorizedData = selectedRows.value.filter(item => item.userId !== userStore.id);
        if (unauthorizedData.length > 0) {
            proxy.$modal.msgWarning("不可删除他人维护的数据");
            return;
        }
        ids = selectedRows.value.map((item) => item.id);
    } else {
        proxy.$modal.msgWarning("请选择数据");
src/views/equipmentManagement/repair/Form/MaintainForm.vue
@@ -6,6 +6,13 @@
    <el-form-item label="维修结果">
      <el-input v-model="form.maintenanceResult" placeholder="请输入维修结果" />
    </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-select>
    </el-form-item>
    <el-form-item label="维修日期">
      <el-date-picker
        v-model="form.maintenanceTime"
@@ -34,6 +41,7 @@
  maintenanceName: undefined, // ç»´ä¿®åç§°
  maintenanceResult: undefined, // ç»´ä¿®ç»“æžœ
  maintenanceTime: undefined, // ç»´ä¿®æ—¥æœŸ
  status: 0,
});
const setForm = (data) => {
src/views/equipmentManagement/repair/Form/RepairForm.vue
@@ -40,6 +40,19 @@
          <el-input v-model="form.repairName" 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-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-col>
    </el-row>
    <el-row>
      <el-col :span="24">
        <el-form-item label="故障现象">
          <el-input
@@ -58,6 +71,8 @@
import useFormData from "@/hooks/useFormData";
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
import useUserStore from "@/store/modules/user";
const { id } = defineProps(["id"])
defineOptions({
  name: "设备报修表单",
@@ -78,6 +93,7 @@
  repairTime: undefined, // æŠ¥ä¿®æ—¥æœŸ
  repairName: userStore.nickName, // æŠ¥ä¿®äºº
  remark: undefined, // æ•…障现象
  status: 0, // æŠ¥ä¿®çŠ¶æ€
});
const setDeviceModel = (id) => {
@@ -96,6 +112,7 @@
  form.repairTime = data.repairTime;
  form.repairName = data.repairName;
  form.remark = data.remark;
  form.status = data.status;
};
// onMounted(() => {
src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -1,6 +1,6 @@
<template>
  <el-dialog v-model="visible" :title="modalOptions.title" @close="close">
    <RepairForm ref="repairFormRef" />
    <RepairForm ref="repairFormRef" :id="id" />
    <template #footer>
            <el-button type="primary" @click="sendForm" :loading="loading">
                {{ modalOptions.confirmText }}
src/views/equipmentManagement/repair/index.vue
@@ -106,8 +106,9 @@
        @pagination="changePage"
      >
        <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 === 0" type="danger">待维修</el-tag>
          <el-tag v-if="row.status === 0" type="warning">待维修</el-tag>
        </template>
        <template #operation="{ row }">
          <el-button
src/views/equipmentManagement/upkeep/Form/MaintenanceForm.vue
@@ -17,11 +17,22 @@
        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-select>
    </el-form-item>
    <el-form-item label="保养结果">
      <el-select v-model="form.maintenanceResult" placeholder="请选择保养结果">
      <!-- <el-select v-model="form.maintenanceResult" placeholder="请选择保养结果">
        <el-option label="完好" :value="1"></el-option>
        <el-option label="ç»´ä¿®" :value="0"></el-option>
      </el-select>
      </el-select> -->
      <el-input
        v-model="form.maintenanceResult"
        placeholder="请输入保养结果"
        type="text" />
    </el-form-item>
  </el-form>
</template>
@@ -40,6 +51,7 @@
  maintenanceActuallyName: undefined, // å®žé™…保养人
  maintenanceActuallyTime: undefined, // å®žé™…保养日期
  maintenanceResult: undefined, // ä¿å…»ç»“æžœ
  status: 0, // ä¿å…»çŠ¶æ€
});
const setForm = (data) => {
src/views/equipmentManagement/upkeep/Form/PlanForm.vue
@@ -5,6 +5,9 @@
        v-model="form.deviceLedgerId"
        @change="setDeviceModel"
        placeholder="请选择设备"
        filterable
        default-first-option
        :reserve-keyword="false"
      >
        <el-option
          v-for="(item, index) in deviceOptions"
@@ -20,6 +23,30 @@
        placeholder="请输入规格型号"
        disabled
      />
    </el-form-item>
    <el-form-item label="录入人">
      <el-select
        v-model="form.createUser"
        placeholder="请选择"
        filterable
        default-first-option
        :reserve-keyword="false"
        clearable
      >
        <el-option
          v-for="item in userList"
          :key="item.userId"
          :label="item.userName"
          :value="item.userId"
        />
      </el-select>
    </el-form-item>
    <el-form-item v-if="id" 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-select>
    </el-form-item>
    <el-form-item label="计划保养日期">
      <el-date-picker
@@ -40,6 +67,7 @@
import { getDeviceLedger } from "@/api/equipmentManagement/ledger";
import { onMounted } from "vue";
import dayjs from "dayjs";
import { userListNoPage } from "@/api/system/user.js";
defineOptions({
  name: "计划表单",
@@ -51,11 +79,15 @@
  deviceOptions.value = data;
};
const { id } = defineProps(['id']);
const { form, resetForm } = useFormData({
  deviceLedgerId: undefined, // è®¾å¤‡Id
  deviceName: undefined, // è®¾å¤‡åç§°
  deviceModel: undefined, // è§„格型号
  maintenancePlanTime: undefined, // è®¡åˆ’保养日期
  createUser: undefined, // å½•入人
  status: 0, //保修状态
});
const setDeviceModel = (id) => {
@@ -75,15 +107,23 @@
  form.deviceLedgerId = data.deviceLedgerId;
  form.deviceName = data.deviceName;
  form.deviceModel = data.deviceModel;
  form.createUser = Number(data.createUser);
  form.status = data.status;
  form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
    "YYYY-MM-DD HH:mm:ss"
  );
};
// ç”¨æˆ·åˆ—表
const userList = ref([]);
const loadForm = () => {};
onMounted(() => {
  loadDeviceName();
  userListNoPage().then((res) => {
    userList.value = res.data;
  });
});
defineExpose({
src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
@@ -5,7 +5,7 @@
    width="30%"
    @close="close"
  >
    <PlanForm ref="planFormRef"></PlanForm>
    <PlanForm ref="planFormRef" :id="id"></PlanForm>
    <template #footer>
            <el-button type="primary" @click="sendForm" :loading="loading">
                {{ modalOptions.confirmText }}
src/views/equipmentManagement/upkeep/index.vue
@@ -86,16 +86,18 @@
        @pagination="changePage"
      >
        <template #maintenanceResultRef="{ row }">
          <el-tag v-if="row.maintenanceResult === 1" type="success">
          <div>{{ row.maintenanceResult || '-' }}</div>
          <!-- <el-tag v-if="row.maintenanceResult === 1" type="success">
            å®Œå¥½
          </el-tag>
          <el-tag v-if="row.maintenanceResult === 0" type="danger">
            ç»´ä¿®
          </el-tag>
          </el-tag> -->
        </template>
        <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 === 0" type="danger">待保养</el-tag>
          <el-tag v-if="row.status === 0" type="warning">待保养</el-tag>
        </template>
        <template #operation="{ row }">
          <el-button
@@ -186,13 +188,13 @@
    align: "center",
    prop: "createUserName",
  },
  {
    label: "录入日期",
    align: "center",
    prop: "createTime",
    formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"),
    width: 200,
  },
  // {
  //   label: "录入日期",
  //   align: "center",
  //   prop: "createTime",
  //   formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"),
  //   width: 200,
  // },
  {
    label: "实际保养人",
    align: "center",
src/views/financialManagement/expenseManagement/index.vue
@@ -106,7 +106,6 @@
  listPage,
  {
    expenseMethod: undefined,
    entryDate: undefined,
  },
  [
    {
@@ -227,11 +226,9 @@
const changeDaterange = (value) => {
  if (value) {
    filters.entryDate = value;
    filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
    filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
  } else {
    filters.entryDate = null;
    filters.entryDateStart = undefined;
    filters.entryDateEnd = undefined;
  }
@@ -259,6 +256,12 @@
};
onMounted(() => {
  filters.entryDate = [
    dayjs().format("YYYY-MM-DD"),
    dayjs().add(1, "day").format("YYYY-MM-DD"),
  ]
  filters.entryDateStart = dayjs().format("YYYY-MM-DD")
  filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD")
  getTableData();
});
</script>
src/views/financialManagement/financialStatements/index.vue
@@ -1,4 +1,4 @@
 <template>
<template>
  <div style="padding: 20px;">
    <!-- é¡µé¢æ ‡é¢˜å’Œæ—¥æœŸç­›é€‰ -->
    <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;">
@@ -10,7 +10,7 @@
        range-separator="至"
        start-placeholder="开始日期"
        end-placeholder="结束日期"
        clearable
        :default-value="[new Date(firstDayOfMonth), new Date()]"
        @change="handleDateChange"
        class="w-full md:w-auto"
        style="margin-right: 30px;"
@@ -137,7 +137,8 @@
import dayjs from "dayjs";
// æ—¥æœŸèŒƒå›´
const dateRange = ref(null);
const dateRange = ref([]);
const firstDayOfMonth = ref(null);
const chartStyle = {
    width: '100%',
    height: '100%', // è®¾ç½®å›¾è¡¨å®¹å™¨çš„高度
@@ -319,9 +320,6 @@
})
const getData = async () => {
  if (!dateRange.value || !dateRange.value.length) {
    return;
  }
  try {
    const {code,data} = await reportForms({entryDateStart:dateRange.value[0], entryDateEnd:dateRange.value[1]});
    if(code === 200) {
@@ -372,22 +370,30 @@
};
// åˆå§‹åŒ–
// åˆå§‹åŒ–日期范围(默认当月)
onMounted(() => {
  // ä¸è®¾ç½®é»˜è®¤æ—¥æœŸï¼Œç”±ç”¨æˆ·æ‰‹åŠ¨é€‰æ‹©
  const today = new Date();
  const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
  firstDayOfMonth.value = firstDay;
  dateRange.value = [dayjs(firstDay).format("YYYY-MM-DD"), dayjs(today).format("YYYY-MM-DD")];
  getData()
});
// å¤„理日期范围变化
const handleDateChange = (newRange) => {
  dateRange.value = newRange;
  if (newRange && newRange.length === 2) {
    dateRange.value = newRange;
    getData()
  }
};
// é‡ç½®æ—¥æœŸèŒƒå›´
const resetDateRange = () => {
  dateRange.value = null;
  const today = new Date();
  const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
  dateRange.value = [dayjs(firstDay).format("YYYY-MM-DD"), dayjs(today).format("YYYY-MM-DD")];
  getData()
};
</script>
src/views/financialManagement/revenueManagement/index.vue
@@ -106,7 +106,6 @@
  listPage,
  {
    incomeMethod: undefined,
    entryDate: undefined,
  },
  [
    {
@@ -227,11 +226,9 @@
const changeDaterange = (value) => {
  if (value) {
    filters.entryDate = value;
    filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
    filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
  } else {
    filters.entryDate = null;
    filters.entryDateStart = undefined;
    filters.entryDateEnd = undefined;
  }
@@ -259,6 +256,12 @@
};
onMounted(() => {
  filters.entryDate = [
    dayjs().format("YYYY-MM-DD"),
    dayjs().add(1, "day").format("YYYY-MM-DD"),
  ]
  filters.entryDateStart = dayjs().format("YYYY-MM-DD")
  filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD")
  getTableData();
});
</script>
src/views/index.vue
@@ -13,9 +13,13 @@
                            <div class="company-meta">{{userStore.roleName}}</div>
                        </div>
                        <div style="display: flex;align-items: center;gap: 8px">
                            <el-icon color="#5053B5" size="22"><Clock /></el-icon>
                            <span>登陆日期:{{userStore.currentLoginTime}}</span>
                        </div>
                        <el-icon color="#5053B5" size="22"><Clock /></el-icon>
                        <span>登陆日期:{{userStore.currentLoginTime}}</span>
                    </div>
                    <div style="display: flex;align-items: center;gap: 8px">
                        <el-icon color="#5053B5" size="22"><Calendar /></el-icon>
                        <span>排班时间:{{scheduleTime}}</span>
                    </div>
                    </div>
                </div>
                <div class="data-cards">
@@ -118,11 +122,11 @@
            <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>
<!--                    <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"
@@ -165,17 +169,23 @@
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ref, reactive, onMounted } from 'vue'
import { ElNotification } from 'element-plus'
import Echarts from "@/components/Echarts/echarts.vue";
import * as echarts from 'echarts';
import useUserStore from "@/store/modules/user.js";
import { Clock, Calendar } from '@element-plus/icons-vue'
import {
    analysisCustomerContractAmounts, getAmountHalfYear,
    getBusiness,
    homeTodos,
    qualityStatistics,
    statisticsReceivablePayable
    statisticsReceivablePayable,
    approveAndDeviceTodos,
    noticesCount
} from "@/api/viewIndex.js";
import { getCurrentUserLatestScheduling } from "@/api/personnelManagement/scheduling.js";
import dayjs from "dayjs";
const userStore = useUserStore()
@@ -341,6 +351,10 @@
const todoList = ref([])
const radio1 = ref(1)
// æŽ’班时间
const scheduleTime = ref('')
const scheduleInfo = ref({})
// å›¾è¡¨å¼•用
const barChart = ref(null)
const lineChart = ref(null)
@@ -358,6 +372,9 @@
    statisticsReceivable()
    qualityStatisticsInfo()
    getAmountHalfYearNum()
    getCurrentUserSchedule()
    getApproveAndDeviceTodos()
    getOngoingAnnouncementNoticeNumber()
})
// æ•°æ®ç»Ÿè®¡
const getBusinessData = () => {
@@ -409,6 +426,35 @@
        qualityStatisticsObject.value.factoryNum = res.data.factoryNum
    })
}
// èŽ·å–å½“å‰ç”¨æˆ·æŽ’ç­ä¿¡æ¯
const getCurrentUserSchedule = async () => {
  try {
    const res = await getCurrentUserLatestScheduling()
    if (res.data) {
      const currentSchedule = res.data
      scheduleInfo.value = currentSchedule
      // æ ¼å¼åŒ–排班时间显示
      if (currentSchedule.startTime && currentSchedule.endTime) {
        scheduleTime.value = `${currentSchedule.startTime} - ${currentSchedule.endTime}`
      } else if (currentSchedule.workStartTime && currentSchedule.workEndTime) {
        const startTime = dayjs(currentSchedule.workStartTime).format('HH:mm')
        const endTime = dayjs(currentSchedule.workEndTime).format('HH:mm')
        scheduleTime.value = `${startTime} - ${endTime}`
      } else {
        scheduleTime.value = '今日无排班'
      }
    } else {
      scheduleTime.value = '今日无排班'
      scheduleInfo.value = {}
    }
  } catch (error) {
    console.error('获取排班信息失败:', error)
    scheduleTime.value = '获取排班信息失败'
  }
}
const getAmountHalfYearNum = async () => {
    const res = await getAmountHalfYear()
    console.log(res)
@@ -484,6 +530,44 @@
        }
    ]
}
// ååŒå¾…审批和报修待办事项
const getApproveAndDeviceTodos = async () => {
    try {
        const res = await approveAndDeviceTodos()
        const { approveTodo, deviceRepairTodo } = res.data
        // æ˜¾ç¤ºé€šçŸ¥
        ElNotification({
                title: '待办事项提醒',
                message: `当前有${approveTodo}条待审批事项,${deviceRepairTodo}条待维修事项`,
                type: 'warning',
                duration: 5000
            })
    } catch (error) {
        console.error('获取协同待办事项失败:', error)
    }
}
// è¿›è¡Œä¸­å…¬å‘Šé€šçŸ¥
const getOngoingAnnouncementNoticeNumber = async () => {
    try {
        const res = await noticesCount()
        // const { approveTodo, deviceRepairTodo } = res.data
        const _noticesCount = res.data
        if(!_noticesCount){
            return
        }
        // æ˜¾ç¤ºé€šçŸ¥
        ElNotification({
                title: '通知公告通知',
                message: `当前有${_noticesCount}条公告通知,注意查看`,
                type: 'warning',
                duration: 5000
            })
    } catch (error) {
        console.error('获取协同待办事项失败:', error)
    }
}
</script>
<style scoped>
src/views/inventoryManagement/dispatchLog/index.vue
@@ -1,144 +1,199 @@
<template>
    <div class="app-container">
        <div class="search_form">
            <div>
                <span class="search_title">供应商名称:</span>
                <el-input
                    v-model="searchForm.supplierName"
                    style="width: 240px"
                    placeholder="请输入"
                    @change="handleQuery"
                    clearable
                    prefix-icon="Search"
                />
                <span class="search_title ml10">出库日期:</span>
                <el-date-picker
                    v-model="searchForm.timeStr"
                    type="date"
                    placeholder="请选择日期"
                    value-format="YYYY-MM-DD"
                    format="YYYY-MM-DD"
                    clearable
                    @change="handleQuery"
                />
                <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
                >搜索</el-button
                >
            </div>
            <div>
                <!-- <el-button type="primary" @click="openForm('add')">新增</el-button> -->
                <el-button @click="handleOut">导出</el-button>
                <el-button type="danger" plain @click="handleDelete">删除</el-button>
                <el-button type="primary" plain @click="handlePrint">打印</el-button>
            </div>
        </div>
        <div class="table_list">
            <el-table
                :data="tableData"
                border
                v-loading="tableLoading"
                @selection-change="handleSelectionChange"
                :expand-row-keys="expandedRowKeys"
                :row-key="(row) => row.id"
                show-summary
                style="width: 100%"
                :summary-method="summarizeMainTable"
                height="calc(100vh - 18.5em)"
            >
                <el-table-column align="center" type="selection" width="55" />
                <el-table-column align="center" label="序号" type="index" width="60" />
                <el-table-column
                    label="出库日期"
                    prop="createTime"
                    min-width="250"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="供应商名称"
                    prop="supplierName"
                    width="250"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="产品大类"
                    prop="productCategory"
                    width="100"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="规格型号"
                    prop="specificationModel"
                    width="100"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="单位"
                    prop="unit"
                    width="80"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="出库数量"
                    prop="inboundNum"
                    width="100"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="含税单价(元)"
                    prop="taxInclusiveUnitPrice"
                    width="100"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="含税总价(元)"
                    prop="taxInclusiveTotalPrice"
                    width="100"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="税率(%)"
                    prop="taxRate"
                    width="100"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="不含税总价(元)"
                    prop="taxExclusiveTotalPrice"
                    width="180"
                    show-overflow-tooltip
                />
                <el-table-column
                    label="出库人"
                    prop="createBy"
                    width="80"
                    show-overflow-tooltip
                />
                <!-- <el-table-column
                    fixed="right"
                    label="操作"
                    min-width="60"
                    align="center"
                >
                    <template #default="scope">
                        <el-button
                            link
                            type="primary"
                            size="small"
                            @click="openForm('edit', scope.row)"
                            >编辑</el-button
                        >
                    </template>
                </el-table-column> -->
            </el-table>
            <pagination
                v-show="total > 0"
                :total="total"
                layout="total, sizes, prev, pager, next, jumper"
                :page="page.current"
                :limit="page.size"
                @pagination="paginationChange"
            />
        </div>
        <el-tabs v-model="activeTab" @tab-change="handleTabChange">
            <el-tab-pane label="成品出库" name="production">
                <div class="search_form">
                    <div>
                        <span class="search_title ml10">出库日期:</span>
                        <el-date-picker
                            v-model="searchForm.timeStr"
                            type="date"
                            placeholder="请选择日期"
                            value-format="YYYY-MM-DD"
                            format="YYYY-MM-DD"
                            clearable
                            @change="handleQuery"
                        />
                        <span class="search_title ml10">产品大类:</span>
                        <el-input
                            v-model="searchForm.productCategory"
                            style="width: 240px"
                            placeholder="请输入"
                            clearable
                        />
                        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
                    </div>
                    <div>
                        <el-button @click="handleOut">导出</el-button>
                        <el-button type="danger" plain @click="handleDelete">删除</el-button>
                        <el-button type="primary" plain @click="handlePrint">打印</el-button>
                    </div>
                </div>
                <div class="table_list">
                    <el-table
                        :data="tableData"
                        border
                        v-loading="tableLoading"
                        @selection-change="handleSelectionChange"
                        :expand-row-keys="expandedRowKeys"
                        :row-key="(row) => row.id"
                        show-summary
                        style="width: 100%"
                        :summary-method="summarizeMainTable"
                        height="calc(100vh - 18.5em)"
                    >
                        <el-table-column align="center" type="selection" width="55" />
                        <el-table-column align="center" label="序号" type="index" width="60" />
                        <el-table-column label="出库日期" prop="createTime" width="120" show-overflow-tooltip />
                        <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
                        <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
                        <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
                        <el-table-column label="单位" prop="unit" width="80" show-overflow-tooltip />
                        <el-table-column label="出库数量" prop="inboundNum" width="100" show-overflow-tooltip />
                        <el-table-column label="单价(元)" prop="unitPrice" width="150"></el-table-column>
                        <el-table-column label="总价(元)" prop="totalPrice" width="150"></el-table-column>
                        <el-table-column label="出库人" prop="createBy" width="80" show-overflow-tooltip />
                    </el-table>
                    <pagination
                        v-show="total > 0"
                        :total="total"
                        layout="total, sizes, prev, pager, next, jumper"
                        :page="page.current"
                        :limit="page.size"
                        @pagination="paginationChange"
                    />
                </div>
            </el-tab-pane>
            <el-tab-pane label="原料出库" name="purchase">
                <div class="search_form">
                    <div>
                        <span class="search_title ml10">出库日期:</span>
                        <el-date-picker
                            v-model="searchForm.timeStr"
                            type="date"
                            placeholder="请选择日期"
                            value-format="YYYY-MM-DD"
                            format="YYYY-MM-DD"
                            clearable
                            @change="handleQuery"
                        />
                        <span class="search_title ml10">产品大类:</span>
                        <el-input
                            v-model="searchForm.productCategory"
                            style="width: 240px"
                            placeholder="请输入"
                            clearable
                        />
                        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
                    </div>
                    <div>
                        <el-button @click="handleOut">导出</el-button>
                        <el-button type="danger" plain @click="handleDelete">删除</el-button>
                        <el-button type="primary" plain @click="handlePrint">打印</el-button>
                    </div>
                </div>
                <div class="table_list">
                    <el-table
                        :data="tableData"
                        border
                        v-loading="tableLoading"
                        @selection-change="handleSelectionChange"
                        :expand-row-keys="expandedRowKeys"
                        :row-key="(row) => row.id"
                        show-summary
                        style="width: 100%"
                        :summary-method="summarizeMainTable"
                        height="calc(100vh - 18.5em)"
                    >
                        <el-table-column align="center" type="selection" width="55" />
                        <el-table-column align="center" label="序号" type="index" width="60" />
                        <el-table-column label="出库日期" prop="createTime" width="120" show-overflow-tooltip />
                        <el-table-column label="采购合同号" prop="purchaseContractNumber" width="180" show-overflow-tooltip />
                        <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
                        <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
                        <el-table-column label="单位" prop="unit" width="80" show-overflow-tooltip />
                        <el-table-column label="出库数量" prop="inboundNum" width="100" show-overflow-tooltip />
                        <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" width="150"></el-table-column>
                        <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" width="150"></el-table-column>
                        <el-table-column label="出库人" prop="createBy" width="80" show-overflow-tooltip />
                    </el-table>
                    <pagination
                        v-show="total > 0"
                        :total="total"
                        layout="total, sizes, prev, pager, next, jumper"
                        :page="page.current"
                        :limit="page.size"
                        @pagination="paginationChange"
                    />
                </div>
            </el-tab-pane>
            <el-tab-pane label="材料出库" name="manual">
                <div class="search_form">
                    <div>
                        <span class="search_title ml10">出库日期:</span>
                        <el-date-picker
                            v-model="searchForm.timeStr"
                            type="date"
                            placeholder="请选择日期"
                            value-format="YYYY-MM-DD"
                            format="YYYY-MM-DD"
                            clearable
                            @change="handleQuery"
                        />
                        <span class="search_title ml10">产品大类:</span>
                        <el-input
                            v-model="searchForm.productCategory"
                            style="width: 240px"
                            placeholder="请输入"
                            clearable
                        />
                        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
                    </div>
                    <div>
                        <el-button @click="handleOut">导出</el-button>
                        <el-button type="danger" plain @click="handleDelete">删除</el-button>
                        <el-button type="primary" plain @click="handlePrint">打印</el-button>
                    </div>
                </div>
                <div class="table_list">
                    <el-table
                        :data="tableData"
                        border
                        v-loading="tableLoading"
                        @selection-change="handleSelectionChange"
                        :expand-row-keys="expandedRowKeys"
                        :row-key="(row) => row.id"
                        show-summary
                        style="width: 100%"
                        :summary-method="summarizeMainTable"
                        height="calc(100vh - 18.5em)"
                    >
                        <el-table-column align="center" type="selection" width="55" />
                        <el-table-column align="center" label="序号" type="index" width="60" />
                        <el-table-column label="出库日期" prop="createTime" show-overflow-tooltip width="130"/>
                        <el-table-column label="批次号" prop="code" width="130" show-overflow-tooltip />
                        <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
                        <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
                        <el-table-column label="单位" prop="unit" show-overflow-tooltip />
                        <el-table-column label="物品类型" prop="itemType" show-overflow-tooltip />
                        <el-table-column label="出库数量" prop="inboundNum" show-overflow-tooltip />
                        <el-table-column label="单价(元)" prop="taxInclusiveUnitPrice" width="150"></el-table-column>
                        <el-table-column label="总价(元)" prop="taxInclusiveTotalPrice" width="150"></el-table-column>
                        <el-table-column label="出库人" prop="createBy" show-overflow-tooltip />
                    </el-table>
                    <pagination
                        v-show="total > 0"
                        :total="total"
                        layout="total, sizes, prev, pager, next, jumper"
                        :page="page.current"
                        :limit="page.size"
                        @pagination="paginationChange"
                    />
                </div>
            </el-tab-pane>
        </el-tabs>
        
        <!-- æ‰“印预览弹窗 -->
        <el-dialog
@@ -163,7 +218,7 @@
                    <div v-for="(item, index) in printData" :key="index" class="print-page">
                        <div class="delivery-note">
                            <div class="header">
                                <div class="company-name">鼎诚瑞实业有限责任公司</div>
                                <div class="company-name">海川开心食品有限公司</div>
                                <div class="document-title">零售发货单</div>
                            </div>
                            
@@ -258,17 +313,22 @@
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
import { ref } from "vue";
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
import { ElMessageBox } from "element-plus";
import useUserStore from "@/store/modules/user";
import {
    getStockOutPage,
    delStockOut,
} from "@/api/inventoryManagement/stockOut.js";
import {
    getStockInPageByProduct,
    getStockInPageByCustom,
} from "@/api/inventoryManagement/stockIn.js";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const activeTab = ref('production');
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
@@ -285,7 +345,9 @@
const data = reactive({
    searchForm: {
        supplierName: "",
        timeStr: "",
        customerName: "",
        productCategory:'',
        timeStr: getCurrentDate(),
    },
    form: {
        supplierId: null,
@@ -322,18 +384,56 @@
};
const getList = () => {
    tableLoading.value = true;
    getStockOutPage({ ...searchForm.value, ...page })
    const params = { ...page }
    if (activeTab.value === 'production') {
        params.customerName = searchForm.value.customerName
        params.timeStr = searchForm.value.timeStr
    } else {
        params.supplierName = searchForm.value.supplierName
        params.timeStr = searchForm.value.timeStr
    }
    params.productCategory = searchForm.value.productCategory
    // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹è°ƒç”¨ä¸åŒçš„æŽ¥å£
    const apiCall = activeTab.value === 'production'
        ? getStockInPageByProduct(params)
        : activeTab.value === 'manual'
        ? getStockInPageByCustom(params)
        : getStockOutPage(params)
    apiCall
        .then((res) => {
            tableLoading.value = false;
            tableData.value = res.data.records;
            tableData.value.map((item) => {
                item.children = [];
                // å‰ç«¯è®¡ç®—总价
                const inboundNum = Number(item.inboundNum) || 0;
                if (activeTab.value === 'production') {
                    // æˆå“å‡ºåº“:总价 = unitPrice Ã— inboundNum
                    const unitPrice = Number(item.unitPrice) || 0;
                    item.totalPrice = (unitPrice * inboundNum).toFixed(2);
                } else {
                    // åŽŸæ–™å’Œææ–™å‡ºåº“ï¼šæ€»ä»· = taxInclusiveUnitPrice Ã— inboundNum
                    const taxInclusiveUnitPrice = Number(item.taxInclusiveUnitPrice) || 0;
                    item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * inboundNum).toFixed(2);
                }
            });
            total.value = res.data.total;
        })
        .catch(() => {
            tableLoading.value = false;
        });
};
const handleTabChange = () => {
    page.current = 1
    searchForm.value.supplierName = ''
    searchForm.value.customerName = ''
    searchForm.value.timeStr = ''
    selectedRows.value = []
      searchForm.value.productCategory = ''
    getList()
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
@@ -361,7 +461,14 @@
        type: "warning",
    })
        .then(() => {
            proxy.download("/stockmanagement/export", {}, "出库台账.xlsx");
            // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹è°ƒç”¨ä¸åŒçš„导出接口
            let exportUrl = "/stockmanagement/export"
            if (activeTab.value === 'production') {
                exportUrl = "/stockmanagement/exportone"
            } else if (activeTab.value === 'manual') {
                exportUrl = "/stockmanagement/exportTwo"
            }
            proxy.download(exportUrl, {}, "出库台账.xlsx");
        })
        .catch(() => {
            proxy.$modal.msg("已取消");
@@ -554,7 +661,7 @@
      <div class="print-page">
        <div class="delivery-note">
          <div class="header">
            <div class="company-name">鼎诚瑞实业有限责任公司</div>
            <div class="company-name">海川开心食品有限公司</div>
            <div class="document-title">零售发货单</div>
          </div>
          
@@ -863,3 +970,5 @@
    }
}
</style>
src/views/inventoryManagement/issueManagement/index.vue
@@ -1,67 +1,136 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">供应商名称:</span>
        <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请输入" @change="handleQuery"
          clearable prefix-icon="Search" />
                <span class="search_title ml10">入库日期:</span>
                <el-date-picker
                    v-model="searchForm.timeStr"
                    type="date"
                    placeholder="请选择日期"
                    value-format="YYYY-MM-DD"
                    format="YYYY-MM-DD"
                    clearable
                    @change="handleQuery"
                />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
      </div>
      <div>
        <!-- <el-button type="primary" @click="openForm('add')">新增出库</el-button> -->
        <el-button @click="handleOut">导出</el-button>
        <!-- <el-button type="danger" plain @click="handleDelete">删除</el-button> -->
      </div>
    </div>
    <div class="table_list">
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
        :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="入库时间" prop="createTime" width="100" show-overflow-tooltip />
        <el-table-column label="入库批次" prop="inboundBatches" width="160" show-overflow-tooltip />
        <el-table-column label="供应商名称" prop="supplierName" width="240" show-overflow-tooltip />
        <el-table-column label="产品大类" prop="productCategory" width="100" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="specificationModel" width="200" show-overflow-tooltip />
        <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
        <el-table-column label="入库数量" prop="inboundNum" width="90" show-overflow-tooltip />
        <el-table-column label="库存数量" prop="inboundNum0" width="90" show-overflow-tooltip />
        <el-table-column label="含税单价" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip />
        <el-table-column label="含税总价" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip />
        <el-table-column label="税率(%)" prop="taxRate" width="80" show-overflow-tooltip />
        <el-table-column label="不含税总价" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip />
        <el-table-column label="入库人" prop="createBy" width="80" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="60" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="openForm(scope.row);">领用</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
        :page="page.current" :limit="page.size" @pagination="paginationChange" />
    </div>
    <el-dialog v-model="dialogFormVisible" :title="'新增出库'" width="40%" @close="closeDia">
    <el-tabs v-model="activeTab" @tab-change="handleTabChange">
      <el-tab-pane label="成品出库" name="production">
        <div class="search_form">
          <div>
            <span class="search_title ml10">产品大类:</span>
            <el-input
              v-model="searchForm.productCategory"
              style="width: 240px"
              placeholder="请输入"
              clearable
            />
            <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
          </div>
          <div>
            <el-button @click="handleOut">导出</el-button>
          </div>
        </div>
        <div class="table_list">
          <el-table :data="tableData" border v-loading="tableLoading"
            :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
            :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
            <el-table-column align="center" label="序号" type="index" width="60" />
            <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
            <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
            <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
            <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
            <el-table-column label="剩余库存" prop="inboundNum0" width="90" show-overflow-tooltip />
            <el-table-column fixed="right" label="操作" min-width="60" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="openForm(scope.row);">发货</el-button>
              </template>
            </el-table-column>
          </el-table>
          <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
            :page="page.current" :limit="page.size" @pagination="paginationChange" />
        </div>
      </el-tab-pane>
     <el-tab-pane label="原料出库" name="purchase">
       <div class="search_form">
         <div>
            <span class="search_title ml10">产品大类:</span>
            <el-input
              v-model="searchForm.productCategory"
              style="width: 240px"
              placeholder="请输入"
              clearable
            />
           <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
         </div>
         <div>
           <el-button @click="handleOut">导出</el-button>
         </div>
       </div>
       <div class="table_list">
         <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
           :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
           :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
           <el-table-column align="center" type="selection" width="55" />
           <el-table-column align="center" label="序号" type="index" width="60" />
                     <el-table-column label="采购合同号" prop="purchaseContractNumber" width="180" show-overflow-tooltip />
                     <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
           <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
           <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
           <el-table-column label="剩余库存" prop="inboundNum0" width="90" show-overflow-tooltip />
                     <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" width="150"></el-table-column>
                     <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" width="150"></el-table-column>
           <el-table-column fixed="right" label="操作" min-width="60" align="center">
             <template #default="scope">
               <el-button link type="primary" size="small" @click="openForm(scope.row);">领用</el-button>
             </template>
           </el-table-column>
         </el-table>
         <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
           :page="page.current" :limit="page.size" @pagination="paginationChange" />
       </div>
     </el-tab-pane>
      <el-tab-pane label="材料出库" name="manual">
        <div class="search_form">
          <div>
            <span class="search_title ml10">产品大类:</span>
            <el-input
              v-model="searchForm.productCategory"
              style="width: 240px"
              placeholder="请输入"
              clearable
            />
            <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
          </div>
          <div>
            <el-button @click="handleOut">导出</el-button>
          </div>
        </div>
        <div class="table_list">
          <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
            :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
            :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
            <el-table-column align="center" type="selection" width="55" />
            <el-table-column align="center" label="序号" type="index" width="60" />
            <el-table-column label="批次号" prop="code" width="130" show-overflow-tooltip />
            <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
            <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
            <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
            <el-table-column label="物品类型" prop="itemType" show-overflow-tooltip />
                        <el-table-column label="剩余库存" prop="inboundNum0" width="90" show-overflow-tooltip />
            <el-table-column fixed="right" label="操作" width="100" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="openForm(scope.row);">领用</el-button>
              </template>
            </el-table-column>
          </el-table>
          <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
            :page="page.current" :limit="page.size" @pagination="paginationChange" />
        </div>
      </el-tab-pane>
    </el-tabs>
    <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="40%" @close="closeDia">
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-form-item label="出库数量:" prop="salesContractNo">
            <div>{{getAvailableQuantityText()}}:{{currentRowNum}}</div>
        <el-form-item :label="getQuantityLabel()" prop="salesContractNo">
          <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.inboundQuantity" placeholder="请输入" clearable />
        </el-form-item>
        <el-form-item label="出库日期:" prop="projectName">
        <el-form-item :label="getDateLabel()" prop="projectName">
          <el-date-picker style="width: 100%" v-model="form.inboundTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
            type="date" placeholder="请选择" clearable />
        </el-form-item>
        <el-form-item label="出库人:" prop="entryPerson">
          <el-select v-model="form.nickName" placeholder="请选择" clearable>
        <el-form-item :label="getPersonLabel()" prop="entryPerson">
          <el-select v-model="form.nickName"                 filterable
                     default-first-option
                     :reserve-keyword="false" placeholder="请选择" clearable>
            <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
          </el-select>
        </el-form-item>
@@ -78,12 +147,14 @@
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
import { ref } from 'vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import { ElMessageBox } from "element-plus";
import useUserStore from '@/store/modules/user'
import { userListNoPageByTenantId } from "@/api/system/user.js";
import {
  getStockInPage
    getStockInPage,
    getStockInPageByProduction,
    getStockInPageByCustom, getInPageByCustom
} from "@/api/inventoryManagement/stockIn.js";
import {
  getStockManagePage,
@@ -106,14 +177,17 @@
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const dialogFormVisible = ref(false)
const activeTab = ref('production')
const data = reactive({
  searchForm: {
    supplierName: '',
    customerName: '',
    inboundQuantity:'',
    inboundTime:'',
    nickName: '',
    userId: '',
        timeStr: '',
    productCategory:'',
    timeStr: getCurrentDate(),
  },
  form: {
    productrecordId: '',
@@ -139,14 +213,40 @@
}
const getList = () => {
  tableLoading.value = true
  getStockInPage({ ...searchForm.value, ...page }).then(res => {
  const params = { ...page }
  if (activeTab.value === 'production') {
    params.customerName = searchForm.value.customerName
    params.timeStr = searchForm.value.timeStr
  } else {
    params.supplierName = searchForm.value.supplierName
    params.timeStr = searchForm.value.timeStr
  }
  params.productCategory = searchForm.value.productCategory
  let apiCall
  if (activeTab.value === 'production') {
    apiCall = getStockInPageByProduction(params)
  } else if (activeTab.value === 'manual') {
    apiCall = getInPageByCustom(params)
  } else {
    apiCall = getStockInPage(params)
  }
  apiCall.then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    total.value = res.data.total
    console.log('res', res.data.records)
  }).catch(() => {
    tableLoading.value = false
  })
}
const handleTabChange = () => {
  page.current = 1
  searchForm.value.supplierName = ''
  searchForm.value.customerName = ''
  searchForm.value.timeStr = ''
  selectedRows.value = []
  searchForm.value.productCategory = ''
  getList()
}
const findNodeById = (nodes, productId) => {
@@ -212,12 +312,14 @@
  }
  proxy.$refs["formRef"].validate(valid => {
    if (valid && currentRowId.value) {
      const typeMap = { production: 2, purchase: 1, manual: 3 }
      const outData = {
        id: currentRowId.value, // åŽŸå§‹è®°å½•ID
        salesLedgerProductId: salesLedgerProductId.value,
        salesLedgerProductId: activeTab.value === 'manual' ? 0 : salesLedgerProductId.value,
        quantity: form.value.inboundQuantity, // å‡ºåº“数量
        time: form.value.inboundTime, // å‡ºåº“æ—¶é—´
        userId: form.value.nickName // æ“ä½œäºº
        userId: form.value.nickName, // æ“ä½œäºº
        type: typeMap[activeTab.value] // å‡ºåº“类型:采购1,生产2,自定义3
      }
      console.log(outData)
@@ -247,7 +349,14 @@
    type: 'warning',
  }
  ).then(() => {
    proxy.download("/stockin/export", {}, '入库台账.xlsx')
    // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹è°ƒç”¨ä¸åŒçš„导出接口
    let exportUrl = "/stockin/export"
    if (activeTab.value === 'production') {
      exportUrl = "/stockin/exportOne"
    } else if (activeTab.value === 'manual') {
      exportUrl = "/stockin/exportTwo"
    }
    proxy.download(exportUrl, {}, '入库台账.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
@@ -285,9 +394,62 @@
  const day = String(today.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}
// æ ¹æ®tab类型获取弹框标题
const getDialogTitle = () => {
  const titleMap = {
    production: '新增发货',
    purchase: '新增领用',
    manual: '新增领用'
  };
  return titleMap[activeTab.value] || '新增出库';
};
// æ ¹æ®tab类型获取可出库数量文本
const getAvailableQuantityText = () => {
  const textMap = {
    production: '可发货数量',
    purchase: '可领用数量',
    manual: '可领用数量'
  };
  return textMap[activeTab.value] || '可出库数量';
};
// æ ¹æ®tab类型获取数量字段标签
const getQuantityLabel = () => {
  const labelMap = {
    production: '发货数量:',
    purchase: '领用数量:',
    manual: '领用数量:'
  };
  return labelMap[activeTab.value] || '出库数量:';
};
// æ ¹æ®tab类型获取日期字段标签
const getDateLabel = () => {
  const labelMap = {
    production: '发货日期:',
    purchase: '领用日期:',
    manual: '领用日期:'
  };
  return labelMap[activeTab.value] || '出库日期:';
};
// æ ¹æ®tab类型获取人员字段标签
const getPersonLabel = () => {
  const labelMap = {
    production: '发货人:',
    purchase: '领用人:',
    manual: '领用人:'
  };
  return labelMap[activeTab.value] || '出库人:';
};
onMounted(() => {
  getList()
})
</script>
<style scoped lang="scss"></style>
src/views/inventoryManagement/receiptManagement/components/formDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,399 @@
<template>
  <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="70%"
    @close="closeDia">
    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
      <el-form-item label="采购订单号" prop="purchaseContractNumber">
        <el-select
          v-model="form.purchaseContractNumber"
          placeholder="请选择采购订单号"
          clearable
          filterable
          :loading="loadingPurchaseOptions"
          @change="handlePurchaseChange"
          :disabled="operationType === 'edit'"
          style="width: 100%"
        >
          <el-option
            v-for="item in purchaseOptions"
            :key="item.purchaseContractNumber"
            :label="formatPurchaseOption(item)"
            :value="item.purchaseContractNumber"
          />
        </el-select>
      </el-form-item>
      <el-table
        :data="productList"
        border
        v-loading="loadingProducts"
        @selection-change="handleSelectionChange"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column
          align="center"
          label="序号"
          type="index"
          width="60"
        />
        <el-table-column label="产品大类" prop="productCategory" />
        <el-table-column label="规格型号" prop="specificationModel" />
        <el-table-column label="单位" prop="unit" width="70" />
        <!-- <el-table-column label="供应商" prop="supplierName" width="100" /> -->
        <el-table-column label="采购数量" prop="quantity" width="100" />
        <el-table-column label="待入库数量" prop="quantity0" width="100" />
        <el-table-column label="本次入库数量" prop="quantityStock" width="150">
          <template #default="scope">
            <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column label="税率(%)" prop="taxRate" width="120" />
        <el-table-column label="单价(元)" prop="taxInclusiveUnitPrice" width="150">
                    <template #default="scope">
                        <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" :disabled="operationType === 'edit'"/>
                    </template>
                </el-table-column>
        <el-table-column
          label="总价(元)"
                    :formatter="formattedNumber"
          prop="taxInclusiveTotalPrice"
          width="150"
        >
        </el-table-column>
      </el-table>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确认</el-button>
        <el-button @click="closeDia">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
import useUserStore from '@/store/modules/user'
import {
  updateStockIn,
  addSutockIn,
  selectProductRecordListByPuechaserId
} from "@/api/inventoryManagement/stockIn.js";
import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js";
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close', 'success'])
const operationType = ref('')// æ“ä½œç±»åž‹: 'add' æˆ– 'edit'
const dialogFormVisible = ref(false)// å¼¹æ¡†æ˜¾ç¤ºçŠ¶æ€
const productList = ref([]);// äº§å“åˆ—表数据
const loadingProducts = ref(false);// äº§å“åŠ è½½çŠ¶æ€
const selectedRows = ref([]) // äº§å“è¡¨æ ¼é€‰ä¸­è¡Œ
const purchaseOptions = ref([])
const loadingPurchaseOptions = ref(false)
const loading = ref(false);
const data = reactive({
  form: {
    id: null,
    purchaseContractNumber: '', // é‡‡è´­è®¢å•号
    supplierId: null,       // ä¾›åº”商ID
    supplierName: '',       // ä¾›åº”商名称
    inboundTime: '',        // å…¥åº“æ—¶é—´
    inboundBatch: '',       // å…¥åº“批次
    recorderId: userStore.userId, // å½•入人ID
    recorderName: userStore.name, // å½•入人姓名
    entryDate: getCurrentDate(),  // å½•入日期
    remark: '',             // å¤‡æ³¨
  },
  rules: {
    purchaseContractNumber: [{ required: true, message: "请输入采购合同号", trigger: "blur" }],
    supplierId: [{ required: true, message: "请选择供应商", trigger: "change" }],
    inboundTime: [{ required: true, message: "请选择入库时间", trigger: "change" }],
    inboundBatch: [{ required: true, message: "请输入入库批次", trigger: "blur" }]
  }
})
const { form, rules } = toRefs(data)
// åŠ¨æ€è®¡ç®—å¯¹è¯æ¡†æ ‡é¢˜
const getDialogTitle = () => {
  return operationType.value === 'add' ? '新增入库' : '编辑入库'
}
const formatPurchaseOption = (item = {}) => {
  const contract = item.purchaseContractNumber || '--';
  const supplier = item.supplierName ? ` Â· ${item.supplierName}` : '';
  return `${contract}${supplier}`;
};
const loadPurchaseOptions = async (keyword = '') => {
  try {
    loadingPurchaseOptions.value = true;
    const res = await purchaseListPage({
      current: -1,
      size: -1,
      purchaseContractNumber: keyword,
    });
    const records = res.data?.records || [];
    purchaseOptions.value = records;
    if (
      form.value.purchaseContractNumber &&
      !purchaseOptions.value.find(
        (item) => item.purchaseContractNumber === form.value.purchaseContractNumber
      )
    ) {
      purchaseOptions.value.push({
        purchaseContractNumber: form.value.purchaseContractNumber,
        supplierName: form.value.supplierName,
        supplierId: form.value.supplierId,
      });
    }
  } finally {
    loadingPurchaseOptions.value = false;
  }
};
const handlePurchaseChange = (value) => {
  form.value.purchaseContractNumber = value || '';
  const matched = purchaseOptions.value.find(
    (item) => item.purchaseContractNumber === value
  );
  if (matched) {
    form.value.supplierName = matched.supplierName || form.value.supplierName;
    form.value.supplierId = matched.supplierId || form.value.supplierId;
  }
  if (!value) {
    productList.value = [];
    return;
  }
  fetchProductsByContract();
};
const exceedsAddLimit = (product) => {
  const stock = Number(product?.quantityStock ?? 0);
  const waiting = Number(product?.quantity0 ?? 0);
  if (!Number.isFinite(stock) || !Number.isFinite(waiting)) {
    return false;
  }
  return stock > waiting;
};
const exceedsEditLimit = (product) => {
  const stock = Number(product?.quantityStock ?? 0);
  const waiting = Number(product?.quantity0 ?? 0);
  const original = Number(product?.originalQuantityStock ?? 0);
  if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) {
    return false;
  }
  return stock > waiting + original;
};
const formattedNumber = (row, column, cellValue) => {
  return parseFloat(cellValue).toFixed(2);
};
// è®¡ç®—总价
const calculateTotalPrice = (row) => {
  const quantityStock = Number(row?.quantityStock ?? 0);
  const taxInclusiveUnitPrice = Number(row?.taxInclusiveUnitPrice ?? 0);
  if (Number.isFinite(quantityStock) && Number.isFinite(taxInclusiveUnitPrice)) {
    row.taxInclusiveTotalPrice = quantityStock * taxInclusiveUnitPrice;
  } else {
    row.taxInclusiveTotalPrice = 0;
  }
};
const fetchProductsByContract = async () => {
  if (!form.value.purchaseContractNumber) {
    proxy.$modal.msgWarning('请选择合同号')
    return
  }
  try {
    loadingProducts.value = true
    const productRes = await selectProductRecordListByPuechaserId({
      purchaseContractNumber: form.value.purchaseContractNumber
    });
    if (!productRes.data || productRes.data.length === 0) {
      proxy.$modal.msgWarning('该合同下没有产品记录')
      productList.value = [];
      return
    }
    productList.value = productRes.data.map(item => ({
      ...item,
      quantityStock: 0,
      taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0),
      taxInclusiveTotalPrice: 0,
      originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0),
    }))
  } catch (error) {
    console.error('查询产品记录失败:', error)
    proxy.$modal.msgError('查询产品记录失败')
    productList.value = [];
  } finally {
    loadingProducts.value = false
  }
}
const updatePro = async () => {
  if (selectedRows.value.length === 0) {
    proxy.$modal.msgWarning('请先选择产品');
    return;
  }
  const target = selectedRows.value[0];
  const stock = Number(target?.quantityStock ?? 0);
  if (!Number.isFinite(stock) || stock <= 0) {
    proxy.$modal.msgWarning('请填写有效的入库数量');
    return;
  }
  if (exceedsEditLimit(target)) {
    proxy.$modal.msgError('本次入库数量不能超过原入库数量与待入库数量之和');
    return;
  }
  const stockInData = {
    id: selectedRows.value[0].recordId,
    quantityStock: Number(selectedRows.value[0].quantityStock),
  };
  await updateStockIn(stockInData)
  proxy.$modal.msgSuccess('修改入库成功')
  closeDia()
  emit('success')
}
const submitForm = async () => {
  if (selectedRows.value.length === 0) {
    proxy.$modal.msgWarning('请先选择采购合同并选择产品')
    return
  }
  if(operationType.value !== 'add'){
    await updatePro()
    return
  }
  try {
    await proxy.$refs.formRef.validate()
    const invalidProducts = selectedRows.value.filter((product) => {
        const stock = Number(product?.quantityStock ?? 0);
        if (!Number.isFinite(stock) || stock <= 0) {
          return true;
        }
        return exceedsAddLimit(product);
    })
    if (invalidProducts.length > 0) {
      proxy.$modal.msgError('本次入库数量需大于0,且不能超过待入库数量')
      return
    }
    const stockInData = {
      ...form.value,
      inboundTime: formatDateTime(form.value.inboundTime),
      nickName: userStore.nickName,
      details: selectedRows.value.map(product => ({
        id: product.id,
        inboundQuantity: Number(product.quantityStock),
                taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice),
                taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice)
      })),
    };
    loading.value = true
    await addSutockIn(stockInData)
    proxy.$modal.msgSuccess('新增入库成功')
    closeDia()
    emit('success')
  } catch (error) {
    console.error('提交失败:', error)
    if (!error.errors) {
      proxy.$modal.msgError('操作失败,请重试')
    }
  } finally {
    loading.value = false
  }
}
const closeDia = () => {
  proxy.$refs.formRef.resetFields()
  dialogFormVisible.value = false
  emit('close')
}
const handleSelectionChange = (selection) => {
  selectedRows.value = selection.filter(item => item.id);
}
function formatDateTime(date = new Date(), includeTime = true) {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  if (!includeTime) {
    return `${year}-${month}-${day}`;
  }
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  const seconds = String(d.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
function getCurrentDate() {
  return formatDateTime(new Date(), false);
}
const openDialog = async (type, row) => {
  operationType.value = type
  dialogFormVisible.value = true
  selectedRows.value = []
  await loadPurchaseOptions();
  if (type === 'add') {
    form.value = {
      id: null,
      purchaseContractNumber: '',
      supplierId: null,
      supplierName: '',
      inboundTime: '',
      inboundBatch: '',
      recorderId: userStore.userId,
      recorderName: userStore.name,
      entryDate: getCurrentDate(),
      remark: ''
    }
    productList.value = []
  } else {
    form.value = JSON.parse(JSON.stringify(row))
    try {
      loadingProducts.value = true
      const res = await selectProductRecordListByPuechaserId({
        purchaseContractNumber: form.value.purchaseContractNumber,
        id: row.id
      });
      productList.value = res.data.map(item => ({
        ...item,
        quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
        taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0),
        taxInclusiveTotalPrice: Number(item?.quantityStock ?? 0) * Number(item?.taxInclusiveUnitPrice ?? 0),
        originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
      }))
      selectedRows.value = productList.value
    } catch (error) {
      console.error('加载产品失败:', error)
      proxy.$modal.msgError('加载产品失败')
      productList.value = []
    } finally {
      loadingProducts.value = false
    }
  }
}
defineExpose({
  openDialog,
})
</script>
<style scoped lang="scss"></style>
src/views/inventoryManagement/receiptManagement/components/formDiaManual.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,332 @@
<template>
  <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增自定义入库' : '编辑自定义入库'" width="70%"
    @close="closeDia">
    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
      <div style="margin-bottom: 10px;" v-if="operationType === 'add'">
        <el-button type="primary" @click="addProductRow">新增</el-button>
      </div>
      <el-table
        :data="productList"
        border
        v-loading="loadingProducts"
      >
        <el-table-column
          align="center"
          label="序号"
          type="index"
          width="60"
        />
        <el-table-column label="产品大类" prop="productCategory" width="200">
          <template #default="scope">
            <el-input v-model="scope.row.productCategory" placeholder="请输入产品大类" />
          </template>
        </el-table-column>
        <el-table-column label="规格型号" prop="specificationModel" width="200">
          <template #default="scope">
            <el-input v-model="scope.row.specificationModel" placeholder="请输入规格型号" />
          </template>
        </el-table-column>
        <el-table-column label="单位" prop="unit" width="100">
          <template #default="scope">
            <el-input v-model="scope.row.unit" placeholder="请输入单位" />
          </template>
        </el-table-column>
        <el-table-column label="供应商" prop="supplierName" width="200">
          <template #default="scope">
            <el-input v-model="scope.row.supplierName" placeholder="请输入供应商" />
          </template>
        </el-table-column>
        <el-table-column label="物品类型" prop="itemType" width="150">
          <template #default="scope">
            <el-select v-model="scope.row.itemType" filterable allow-create placeholder="请选择物品类型" style="width: 100%">
              <el-option
                v-for="item in itemTypeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="入库数量" prop="inboundNum" width="150">
          <template #default="scope">
            <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column label="入库日期" prop="inboundDate" width="180">
          <template #default="scope">
            <el-date-picker
              v-model="scope.row.inboundDate"
              type="date"
              placeholder="请选择入库日期"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              style="width: 100%"
            />
          </template>
        </el-table-column>
        <el-table-column label="数量" prop="quantityStock" width="150">
          <template #default="scope">
            <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column label="单价(元)" prop="taxInclusiveUnitPrice" width="150">
          <template #default="scope">
            <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column
           label="总价(元)"
           prop="taxInclusiveTotalPrice"
           width="150"
         >
        </el-table-column>
        <el-table-column label="操作" width="80" v-if="operationType === 'add'">
          <template #default="scope">
            <el-button type="danger" size="small" @click="removeProductRow(scope.$index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确认</el-button>
        <el-button @click="closeDia">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
import useUserStore from '@/store/modules/user'
import {
  addStockInCustom,
  updateStockInCustom,
} from "@/api/inventoryManagement/stockIn.js";
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close', 'success'])
const operationType = ref('')// æ“ä½œç±»åž‹: 'add' æˆ– 'edit'
const dialogFormVisible = ref(false)// å¼¹æ¡†æ˜¾ç¤ºçŠ¶æ€
const productList = ref([]);// äº§å“åˆ—表数据
const loadingProducts = ref(false);// äº§å“åŠ è½½çŠ¶æ€
const loading = ref(false);
function formatDateTime(date = new Date(), includeTime = true) {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  if (!includeTime) {
    return `${year}-${month}-${day}`;
  }
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  const seconds = String(d.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
function getCurrentDate() {
  return formatDateTime(new Date(), false);
}
const itemTypeOptions = [
  { label: '物料', value: '物料' },
  { label: '原料', value: '原料' },
  { label: '成品', value: '成品' },
  { label: '其他', value: '其他' },
]
const taxRateOptions = [
  { label: '1', value: 1 },
  { label: '6', value: 6 },
  { label: '13', value: 13 },
]
const data = reactive({
  form: {
    id: null,
    supplierId: null,       // ä¾›åº”商ID
    supplierName: '',       // ä¾›åº”商名称
    recorderId: userStore.userId, // å½•入人ID
    recorderName: userStore.name, // å½•入人姓名
    entryDate: getCurrentDate(),  // å½•入日期
    remark: '',             // å¤‡æ³¨
  },
  rules: {
    supplierName: [{ required: true, message: "请输入供应商名称", trigger: "blur" }]
  }
})
const { form, rules } = toRefs(data)
// æ–°å¢žäº§å“è¡Œ
const addProductRow = () => {
  productList.value.push({
    id: null,
    productCategory: '',
    specificationModel: '',
    unit: '',
    supplierName: form.value.supplierName || '',
    itemType: '',
    inboundNum: 0,
    inboundDate: '',
    quantityStock: 0,
    taxInclusiveUnitPrice: 0,
    taxInclusiveTotalPrice: 0,
    taxRate: null,
    taxExclusiveTotalPrice: 0,
  });
};
// åˆ é™¤äº§å“è¡Œ
const removeProductRow = (index) => {
  productList.value.splice(index, 1);
};
// è®¡ç®—总价(根据数量、单价和含税单价)
const calculateTotalPrice = (row) => {
  // è®¡ç®—普通总价:quantityStock * taxInclusiveUnitPrice
  const quantity = Number(row.quantityStock || 0);
  const taxInclusiveUnitPrice = Number(row.taxInclusiveUnitPrice || 0);
  row.taxInclusiveTotalPrice = quantity * taxInclusiveUnitPrice;
  calculateExclusivePrice(row);
};
// è®¡ç®—不含税总价(根据含税总价和税率)
const calculateExclusivePrice = (row) => {
  const taxInclusiveTotalPrice = Number(row.taxInclusiveTotalPrice || 0);
  const taxRate = Number(row.taxRate || 0);
  row.taxExclusiveTotalPrice = taxInclusiveTotalPrice / (1 + taxRate / 100);
};
const submitForm = async () => {
  try {
    await proxy.$refs.formRef.validate()
    if (!productList.value.length) {
      proxy.$modal.msgError('请至少添加一条产品数据')
      return
    }
    // éªŒè¯è‡ªå®šä¹‰æ·»åŠ çš„æ•°æ®å¿…å¡«å­—æ®µ
    for (let i = 0; i < productList.value.length; i++) {
      const product = productList.value[i];
      if (!product.productCategory || !product.specificationModel || !product.unit) {
        proxy.$modal.msgError(`第${i + 1}行产品数据未填写完整(产品大类、规格型号、单位为必填)`)
        return
      }
      if (!product.itemType) {
        proxy.$modal.msgError(`第${i + 1}行请选择物品类型`)
        return
      }
      if (!product.inboundDate) {
        proxy.$modal.msgError(`第${i + 1}行请选择入库日期`)
        return
      }
      const stock = Number(product?.inboundNum ?? 0);
      if (!Number.isFinite(stock) || stock <= 0) {
        proxy.$modal.msgError(`第${i + 1}行本次入库数量需大于0`)
        return
      }
    }
    const payloadList = productList.value.map(product => ({
      id: product.id ?? null,
            inboundNum: Number(product.inboundNum),
      productCategory: product.productCategory,
      specificationModel: product.specificationModel,
      unit: product.unit,
      supplierName: product.supplierName || form.value.supplierName,
      itemType: product.itemType,
      inboundDate: formatDateTime(product.inboundDate, false),
      taxRate: Number(product.taxRate || 0),
      taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0),
            taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice || 0),
            taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice || 0),
    }));
    loading.value = true
    if (operationType.value === 'edit') {
      const editPayload = payloadList[0]
      await updateStockInCustom(editPayload)
    } else {
      await addStockInCustom(payloadList)
    }
    proxy.$modal.msgSuccess(operationType.value === 'edit' ? '编辑自定义入库成功' : '新增自定义入库成功')
    closeDia()
    emit('success')
  } catch (error) {
    console.error('提交失败:', error)
    if (!error.errors) {
      proxy.$modal.msgError('操作失败,请重试')
    }
  } finally {
    loading.value = false
  }
}
const closeDia = () => {
  proxy.$refs.formRef.resetFields()
  dialogFormVisible.value = false
  productList.value = []
  emit('close')
}
const openDialog = async (type, row) => {
  operationType.value = type
  dialogFormVisible.value = true
  if (type === 'add') {
    form.value = {
      id: null,
      supplierId: null,
      supplierName: '',
      recorderId: userStore.userId,
      recorderName: userStore.name,
      entryDate: getCurrentDate(),
      remark: ''
    }
    productList.value = []
  } else {
    // ç¼–辑模式:将行数据填充到表格中以支持修改
    form.value = {
      id: row?.id ?? null,
      supplierId: row?.supplierId ?? null,
      supplierName: row?.supplierName ?? '',
      recorderId: userStore.userId,
      recorderName: userStore.name,
      entryDate: getCurrentDate(),
      remark: row?.remark ?? ''
    }
    productList.value = [{
      id: row?.id ?? null,
      productCategory: row?.productCategory ?? '',
      specificationModel: row?.specificationModel ?? '',
      unit: row?.unit ?? '',
      supplierName: row?.supplierName ?? '',
      itemType: row?.itemType ?? '',
      inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0),
      inboundDate: row?.inboundDate ?? row?.createTime ?? '',
      quantityStock: Number(row?.quantityStock ?? 0),
      taxRate: Number(row?.taxRate ?? 0),
      taxInclusiveUnitPrice: Number(row?.taxInclusiveUnitPrice ?? 0),
      taxInclusiveTotalPrice: Number(row?.taxInclusiveTotalPrice ?? 0),
      taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0),
    }]
  }
}
defineExpose({
  openDialog,
})
</script>
<style scoped lang="scss"></style>
src/views/inventoryManagement/receiptManagement/components/formDiaProduct.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,302 @@
<template>
  <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增自定义入库' : '编辑自定义入库'" width="70%"
    @close="closeDia">
    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
      <div style="margin-bottom: 10px;" v-if="operationType === 'add'">
        <el-button type="primary" @click="addProductRow">新增</el-button>
      </div>
      <el-table
        :data="productList"
        border
        v-loading="loadingProducts"
      >
        <el-table-column
          align="center"
          label="序号"
          type="index"
          width="60"
        />
        <el-table-column label="产品大类" prop="productCategory" width="200">
          <template #default="scope">
            <el-input v-model="scope.row.productCategory" placeholder="请输入产品大类" />
          </template>
        </el-table-column>
        <el-table-column label="规格型号" prop="specificationModel" width="200">
          <template #default="scope">
            <el-input v-model="scope.row.specificationModel" placeholder="请输入规格型号" />
          </template>
        </el-table-column>
        <el-table-column label="单位" prop="unit" width="100">
          <template #default="scope">
            <el-input v-model="scope.row.unit" placeholder="请输入单位" />
          </template>
        </el-table-column>
        <el-table-column label="入库数量" prop="inboundNum" width="150">
          <template #default="scope">
            <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column label="入库日期" prop="inboundDate" width="180">
          <template #default="scope">
            <el-date-picker
              v-model="scope.row.inboundDate"
              type="date"
              placeholder="请选择入库日期"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              style="width: 100%"
            />
          </template>
        </el-table-column>
        <el-table-column label="单价(元)" prop="unitPrice" width="150">
          <template #default="scope">
            <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.unitPrice" @change="() => calculateTotalPrice(scope.row)" />
          </template>
        </el-table-column>
        <el-table-column
           label="总价(元)"
           prop="totalPrice"
           width="150"
         >
        </el-table-column>
        <el-table-column label="操作" width="80" v-if="operationType === 'add'">
          <template #default="scope">
            <el-button type="danger" size="small" @click="removeProductRow(scope.$index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确认</el-button>
        <el-button @click="closeDia">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
import useUserStore from '@/store/modules/user'
import {
    addStockInCustom, updateProduct
} from "@/api/inventoryManagement/stockIn.js";
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close', 'success'])
const operationType = ref('')// æ“ä½œç±»åž‹: 'add' æˆ– 'edit'
const dialogFormVisible = ref(false)// å¼¹æ¡†æ˜¾ç¤ºçŠ¶æ€
const productList = ref([]);// äº§å“åˆ—表数据
const loadingProducts = ref(false);// äº§å“åŠ è½½çŠ¶æ€
const loading = ref(false);
function formatDateTime(date = new Date(), includeTime = true) {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  if (!includeTime) {
    return `${year}-${month}-${day}`;
  }
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  const seconds = String(d.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
function getCurrentDate() {
  return formatDateTime(new Date(), false);
}
const itemTypeOptions = [
  { label: '物料', value: '物料' },
  { label: '原料', value: '原料' },
  { label: '成品', value: '成品' },
  { label: '其他', value: '其他' },
]
const taxRateOptions = [
  { label: '1', value: 1 },
  { label: '6', value: 6 },
  { label: '13', value: 13 },
]
const data = reactive({
  form: {
    id: null,
    supplierId: null,       // ä¾›åº”商ID
    supplierName: '',       // ä¾›åº”商名称
    recorderId: userStore.userId, // å½•入人ID
    recorderName: userStore.name, // å½•入人姓名
    entryDate: getCurrentDate(),  // å½•入日期
    remark: '',             // å¤‡æ³¨
  },
  rules: {
    supplierName: [{ required: true, message: "请输入供应商名称", trigger: "blur" }]
  }
})
const { form, rules } = toRefs(data)
// æ–°å¢žäº§å“è¡Œ
const addProductRow = () => {
  productList.value.push({
    id: null,
    productCategory: '',
    specificationModel: '',
    unit: '',
    supplierName: form.value.supplierName || '',
    itemType: '',
    inboundNum: 0,
    inboundDate: '',
    quantityStock: 0,
    unitPrice: 0,
    totalPrice: 0,
    taxRate: null,
    taxExclusiveTotalPrice: 0,
  });
};
// åˆ é™¤äº§å“è¡Œ
const removeProductRow = (index) => {
  productList.value.splice(index, 1);
};
// è®¡ç®—总价(根据数量、单价和含税单价)
const calculateTotalPrice = (row) => {
  // è®¡ç®—普通总价:inboundNum * unitPrice
  const quantity = Number(row.inboundNum || 0);
  const unitPrice = Number(row.unitPrice || 0);
  row.totalPrice = quantity * unitPrice;
  calculateExclusivePrice(row);
};
// è®¡ç®—不含税总价(根据含税总价和税率)
const calculateExclusivePrice = (row) => {
  const totalPrice = Number(row.totalPrice || 0);
  const taxRate = Number(row.taxRate || 0);
  row.taxExclusiveTotalPrice = totalPrice / (1 + taxRate / 100);
};
const submitForm = async () => {
  try {
    await proxy.$refs.formRef.validate()
    if (!productList.value.length) {
      proxy.$modal.msgError('请至少添加一条产品数据')
      return
    }
    // éªŒè¯è‡ªå®šä¹‰æ·»åŠ çš„æ•°æ®å¿…å¡«å­—æ®µ
    for (let i = 0; i < productList.value.length; i++) {
      const product = productList.value[i];
      if (!product.productCategory || !product.specificationModel || !product.unit) {
        proxy.$modal.msgError(`第${i + 1}行产品数据未填写完整(产品大类、规格型号、单位为必填)`)
        return
      }
      if (!product.inboundDate) {
        proxy.$modal.msgError(`第${i + 1}行请选择入库日期`)
        return
      }
      const stock = Number(product?.inboundNum ?? 0);
      if (!Number.isFinite(stock) || stock <= 0) {
        proxy.$modal.msgError(`第${i + 1}行本次入库数量需大于0`)
        return
      }
    }
    const payloadList = productList.value.map(product => ({
      id: product.id ?? null,
            inboundNum: Number(product.inboundNum),
      productCategory: product.productCategory,
      specificationModel: product.specificationModel,
      unit: product.unit,
      supplierName: product.supplierName || form.value.supplierName,
      itemType: product.itemType,
      inboundDate: formatDateTime(product.inboundDate, false),
      taxRate: Number(product.taxRate || 0),
      taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0),
            unitPrice: Number(product.unitPrice || 0),
    }));
    loading.value = true
    if (operationType.value === 'edit') {
      const editPayload = payloadList[0]
      await updateProduct(editPayload)
    } else {
      await addStockInCustom(payloadList)
    }
    proxy.$modal.msgSuccess(operationType.value === 'edit' ? '编辑自定义入库成功' : '新增自定义入库成功')
    closeDia()
    emit('success')
  } catch (error) {
    console.error('提交失败:', error)
    if (!error.errors) {
      proxy.$modal.msgError('操作失败,请重试')
    }
  } finally {
    loading.value = false
  }
}
const closeDia = () => {
  proxy.$refs.formRef.resetFields()
  dialogFormVisible.value = false
  productList.value = []
  emit('close')
}
const openDialog = async (type, row) => {
  operationType.value = type
  dialogFormVisible.value = true
  if (type === 'add') {
    form.value = {
      id: null,
      supplierId: null,
      supplierName: '',
      recorderId: userStore.userId,
      recorderName: userStore.name,
      entryDate: getCurrentDate(),
      remark: ''
    }
    productList.value = []
  } else {
    // ç¼–辑模式:将行数据填充到表格中以支持修改
    form.value = {
      id: row?.id ?? null,
      supplierId: row?.supplierId ?? null,
      supplierName: row?.supplierName ?? '',
      recorderId: userStore.userId,
      recorderName: userStore.name,
      entryDate: getCurrentDate(),
      remark: row?.remark ?? ''
    }
    productList.value = [{
      id: row?.id ?? null,
      productCategory: row?.productCategory ?? '',
      specificationModel: row?.specificationModel ?? '',
      unit: row?.unit ?? '',
      supplierName: row?.supplierName ?? '',
      itemType: row?.itemType ?? '',
      inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0),
      inboundDate: row?.inboundDate ?? row?.createTime ?? '',
      taxRate: Number(row?.taxRate ?? 0),
      unitPrice: Number(row?.unitPrice ?? 0),
      taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0),
    }]
  }
}
defineExpose({
  openDialog,
})
</script>
<style scoped lang="scss"></style>
src/views/inventoryManagement/receiptManagement/index.vue
@@ -1,162 +1,206 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">供应商名称:</span>
        <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请输入" @change="handleQuery"
          clearable prefix-icon="Search" />
        <span class="search_title ml10">入库日期:</span>
                <el-date-picker
                    v-model="searchForm.timeStr"
                    type="date"
                    placeholder="请选择日期"
                    value-format="YYYY-MM-DD"
                    format="YYYY-MM-DD"
                    clearable
                    @change="handleQuery"
                />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
      </div>
      <div>
        <el-button type="primary" @click="openForm('add')">新增入库</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
        :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="入库时间" prop="createTime" width="100" show-overflow-tooltip />
        <el-table-column label="入库批次" prop="inboundBatches" width="160" show-overflow-tooltip />
        <el-table-column label="供应商名称" prop="supplierName" width="240" show-overflow-tooltip />
        <el-table-column label="产品大类" prop="productCategory" width="100" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="specificationModel" width="200" show-overflow-tooltip />
        <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
        <el-table-column label="入库数量" prop="inboundNum" width="90" show-overflow-tooltip />
        <el-table-column label="含税单价" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip />
        <el-table-column label="含税总价" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip />
        <el-table-column label="税率(%)" prop="taxRate" width="80" show-overflow-tooltip />
        <el-table-column label="不含税总价" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip />
        <el-table-column label="入库人" prop="createBy" width="80" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="60" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="openForm('edit', scope.row);" :disabled="scope.row.createUser !== userStore.id">编辑</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
        :page="page.current" :limit="page.size" @pagination="paginationChange" />
    </div>
    <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增入库' : '编辑入库'" width="70%"
      @close="closeDia">
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-form-item label="采购订单号" prop="purchaseContractNumber">
              <el-select
                  v-model="form.purchaseContractNumber"
                  placeholder="请选择采购订单号"
                  clearable
                  filterable
                  remote
                  :remote-method="loadPurchaseOptions"
                  :loading="loadingPurchaseOptions"
                  @change="handlePurchaseChange"
                  :disabled="operationType === 'edit'"
                  style="width: 100%"
              >
                <el-option
                    v-for="item in purchaseOptions"
                    :key="item.purchaseContractNumber"
                    :label="formatPurchaseOption(item)"
                    :value="item.purchaseContractNumber"
                />
              </el-select>
            </el-form-item>
        <el-table
          :data="productList"
          border
          v-loading="loadingProducts"
          @selection-change="handleSelectionChange"
        >
          <el-table-column align="center" type="selection" width="55" />
          <el-table-column
            align="center"
            label="序号"
            type="index"
            width="60"
          />
          <el-table-column label="产品大类" prop="productCategory" />
          <el-table-column label="规格型号" prop="specificationModel" />
          <el-table-column label="单位" prop="unit" width="70" />
          <el-table-column label="供应商" prop="supplierName" width="100" />
          <el-table-column label="采购数量" prop="quantity" width="100" />
          <el-table-column label="待入库数量" prop="quantity0" width="100" />
          <el-table-column label="本次入库数量" prop="quantityStock" width="150">
            <template #default="scope">
              <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" />
            </template>
          </el-table-column>
          <el-table-column label="税率(%)" prop="taxRate" width="120" />
          <el-table-column
            label="含税单价(元)"
            prop="taxInclusiveUnitPrice"
            :formatter="formattedNumber"
            width="150"
          />
          <el-table-column
            label="含税总价(元)"
            prop="taxInclusiveTotalPrice"
            :formatter="formattedNumber"
            width="150"
          />
          <el-table-column
            label="不含税总价(元)"
            prop="taxExclusiveTotalPrice"
            :formatter="formattedNumber"
            width="150"
          />
        </el-table>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
    <el-tabs v-model="activeTab" @tab-change="handleTabChange">
      <el-tab-pane label="成品入库" name="production">
        <div class="search_form">
          <div>
            <span class="search_title ml10">入库日期:</span>
            <el-date-picker
              v-model="searchForm.timeStr"
              type="date"
              placeholder="请选择日期"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              clearable
              @change="handleQuery"
            />
            <span class="search_title ml10">产品大类:</span>
            <el-input
              v-model="searchForm.productCategory"
              style="width: 240px"
              placeholder="请输入"
              clearable
            />
            <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
          </div>
          <div>
            <el-button @click="handleOut">导出</el-button>
            <el-button type="danger" plain @click="handleDelete">删除</el-button>
          </div>
        </div>
      </template>
    </el-dialog>
        <div class="table_list">
          <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
            :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
            :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
            <el-table-column align="center" type="selection" width="55" />
            <el-table-column align="center" label="序号" type="index" width="60" />
            <el-table-column label="入库时间" prop="createTime" show-overflow-tooltip />
                        <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
            <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
            <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
            <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
                        <el-table-column label="入库数量" prop="inboundNum" width="100" show-overflow-tooltip />
                        <el-table-column label="单价(元)" prop="unitPrice" width="150"></el-table-column>
                        <el-table-column label="总价(元)" prop="totalPrice" width="150"></el-table-column>
            <el-table-column fixed="right" label="操作" min-width="60" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="openForm('edit', scope.row, 'production');">编辑</el-button>
              </template>
            </el-table-column>
          </el-table>
          <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
            :page="page.current" :limit="page.size" @pagination="paginationChange" />
        </div>
      </el-tab-pane>
     <el-tab-pane label="原料入库" name="purchase">
       <div class="search_form">
         <div>
           <span class="search_title ml10">入库日期:</span>
           <el-date-picker
             v-model="searchForm.timeStr"
             type="date"
             placeholder="请选择日期"
             value-format="YYYY-MM-DD"
             format="YYYY-MM-DD"
             clearable
             @change="handleQuery"
           />
            <span class="search_title ml10">产品大类:</span>
            <el-input
              v-model="searchForm.productCategory"
              style="width: 240px"
              placeholder="请输入"
              clearable
            />
           <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
         </div>
         <div>
           <el-button type="primary" @click="openForm('add', 'purchase')">新增入库</el-button>
           <el-button @click="handleOut">导出</el-button>
           <el-button type="danger" plain @click="handleDelete">删除</el-button>
         </div>
       </div>
       <div class="table_list">
         <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
           :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
           :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
           <el-table-column align="center" type="selection" width="55" />
           <el-table-column align="center" label="序号" type="index" width="60" />
           <el-table-column label="入库时间" prop="createTime" width="100" show-overflow-tooltip />
                     <el-table-column label="采购合同号" prop="purchaseContractNumber" width="180" show-overflow-tooltip />
<el-table-column label="供应商名称" prop="supplierName" width="240" show-overflow-tooltip />
           <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
           <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
           <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
                     <el-table-column label="入库数量" prop="inboundNum" width="100" show-overflow-tooltip />
                     <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" width="150"></el-table-column>
                     <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" width="150"></el-table-column>
           <el-table-column label="入库人" prop="createBy" width="80" show-overflow-tooltip />
           <el-table-column fixed="right" label="操作" min-width="60" align="center">
             <template #default="scope">
               <el-button link type="primary" size="small" @click="openForm('edit', scope.row, 'purchase');">编辑</el-button>
             </template>
           </el-table-column>
         </el-table>
         <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
           :page="page.current" :limit="page.size" @pagination="paginationChange" />
       </div>
     </el-tab-pane>
      <el-tab-pane label="材料入库" name="manual">
        <div class="search_form">
          <div>
            <span class="search_title ml10">入库日期:</span>
            <el-date-picker
              v-model="searchForm.timeStr"
              type="date"
              placeholder="请选择日期"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              clearable
              @change="handleQuery"
            />
            <span class="search_title ml10">产品大类:</span>
            <el-input
              v-model="searchForm.productCategory"
              style="width: 240px"
              placeholder="请输入"
              clearable
            />
            <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
          </div>
          <div>
            <el-button type="primary" @click="openForm('add', 'manual')">新增入库</el-button>
            <el-button @click="handleOut">导出</el-button>
            <el-button type="danger" plain @click="handleDelete">删除</el-button>
          </div>
        </div>
        <div class="table_list">
          <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
            :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
            :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
            <el-table-column align="center" type="selection" width="55" />
            <el-table-column align="center" label="序号" type="index" width="60" />
            <el-table-column label="入库时间" prop="inboundDate" width="100" show-overflow-tooltip />
                        <el-table-column label="批次号" prop="code" width="130" show-overflow-tooltip />
            <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
            <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
            <el-table-column label="单位" prop="unit" width="70" show-overflow-tooltip />
            <el-table-column label="物品类型" prop="itemType" show-overflow-tooltip />
                        <el-table-column label="入库数量" prop="inboundNum" width="100" show-overflow-tooltip />
                        <el-table-column label="剩余库存" prop="inboundNum0" show-overflow-tooltip />
                        <el-table-column label="单价(元)" prop="taxInclusiveUnitPrice" width="150"></el-table-column>
                        <el-table-column label="总价(元)" prop="taxInclusiveTotalPrice" width="150"></el-table-column>
            <el-table-column label="入库人" prop="createBy" width="80" show-overflow-tooltip />
            <el-table-column fixed="right" label="操作" width="100" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="openForm('edit', scope.row, 'manual');">编辑</el-button>
              </template>
            </el-table-column>
          </el-table>
          <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
            :page="page.current" :limit="page.size" @pagination="paginationChange" />
        </div>
      </el-tab-pane>
    </el-tabs>
    <form-dia ref="formDia" @close="handleQuery" @success="handleQuery"></form-dia>
    <form-dia-manual ref="formDiaManual" @close="handleQuery" @success="handleQuery"></form-dia-manual>
    <form-dia-product ref="formDiaProduct" @close="handleQuery" @success="handleQuery"></form-dia-product>
  </div>
</template>
<script setup>
import pagination from '@/components/PIMTable/Pagination.vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance, nextTick } from 'vue'
import { ElMessageBox } from "element-plus";
import useUserStore from '@/store/modules/user'
import dayjs from 'dayjs'
import {
  getStockInPage,
  updateStockIn,
  addSutockIn,
  delStockIn,
  selectProductRecordListByPuechaserId
    getStockInPage,
    getStockInPageByProduction,
    delStockIn,
    delStockInCustom, getInPageByCustom,
} from "@/api/inventoryManagement/stockIn.js";
import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js";
import FormDia from './components/formDia.vue'
import FormDiaManual from './components/formDiaManual.vue'
import FormDiaProduct from './components/formDiaProduct.vue'
const userStore = useUserStore()
// èŽ·å–å½“å‰æ—¥æœŸ
function getCurrentDate() {
  return dayjs().format('YYYY-MM-DD')
}
const { proxy } = getCurrentInstance()
const tableData = ref([])
const selectedRows = ref([])
const userList = ref([])
const purchaseOptions = ref([])
const loadingPurchaseOptions = ref(false)
const loading = ref(false);
const tableLoading = ref(false)
const formDia = ref()
const formDiaManual = ref()
const formDiaProduct = ref()
const activeTab = ref('production') // å½“前激活的 tab
const page = reactive({
  current: 1,
@@ -164,107 +208,15 @@
})
const total = ref(0)
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref('')// æ“ä½œç±»åž‹: 'add' æˆ– 'edit'
const dialogFormVisible = ref(false)// å¼¹æ¡†æ˜¾ç¤ºçŠ¶æ€
const productList = ref([]);// äº§å“åˆ—表数据
const loadingProducts = ref(false);// äº§å“åŠ è½½çŠ¶æ€
const productSelectedRows = ref([]) // äº§å“è¡¨æ ¼é€‰ä¸­è¡Œ
const data = reactive({
  searchForm: {
    supplierName: '',
        timeStr: '',
    customerName: '',
    productCategory:'',
    timeStr: getCurrentDate(),
  },
  form: {
    id: null,
    purchaseContractNumber: '', // é‡‡è´­è®¢å•号
    supplierId: null,       // ä¾›åº”商ID
    supplierName: '',       // ä¾›åº”商名称
    inboundTime: '',        // å…¥åº“æ—¶é—´
    inboundBatch: '',       // å…¥åº“批次
    recorderId: userStore.userId, // å½•入人ID
    recorderName: userStore.name, // å½•入人姓名
    entryDate: getCurrentDate(),  // å½•入日期
    remark: '',             // å¤‡æ³¨
  },
  rules: {
    purchaseContractNumber: [{ required: true, message: "请输入采购合同号", trigger: "blur" }],
    supplierId: [{ required: true, message: "请选择供应商", trigger: "change" }],
    inboundTime: [{ required: true, message: "请选择入库时间", trigger: "change" }],
    inboundBatch: [{ required: true, message: "请输入入库批次", trigger: "blur" }]
  }
})
const { searchForm, form, rules } = toRefs(data)
const formatPurchaseOption = (item = {}) => {
  const contract = item.purchaseContractNumber || '--';
  const supplier = item.supplierName ? ` Â· ${item.supplierName}` : '';
  return `${contract}${supplier}`;
};
const loadPurchaseOptions = async (keyword = '') => {
  try {
    loadingPurchaseOptions.value = true;
    const res = await purchaseListPage({
      current: -1,
      size: -1,
      purchaseContractNumber: keyword,
    });
    const records = res.data?.records || [];
    purchaseOptions.value = records;
    if (
      form.value.purchaseContractNumber &&
      !purchaseOptions.value.find(
        (item) => item.purchaseContractNumber === form.value.purchaseContractNumber
      )
    ) {
      purchaseOptions.value.push({
        purchaseContractNumber: form.value.purchaseContractNumber,
        supplierName: form.value.supplierName,
        supplierId: form.value.supplierId,
      });
    }
  } finally {
    loadingPurchaseOptions.value = false;
  }
};
const handlePurchaseChange = (value) => {
  form.value.purchaseContractNumber = value || '';
  const matched = purchaseOptions.value.find(
    (item) => item.purchaseContractNumber === value
  );
  if (matched) {
    form.value.supplierName = matched.supplierName || form.value.supplierName;
    form.value.supplierId = matched.supplierId || form.value.supplierId;
  }
  if (!value) {
    productList.value = [];
    return;
  }
  fetchProductsByContract();
};
const exceedsAddLimit = (product) => {
  const stock = Number(product?.quantityStock ?? 0);
  const waiting = Number(product?.quantity0 ?? 0);
  if (!Number.isFinite(stock) || !Number.isFinite(waiting)) {
    return false;
  }
  return stock > waiting;
};
const exceedsEditLimit = (product) => {
  const stock = Number(product?.quantityStock ?? 0);
  const waiting = Number(product?.quantity0 ?? 0);
  const original = Number(product?.originalQuantityStock ?? 0);
  if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) {
    return false;
  }
  return stock > waiting + original;
};
const formattedNumber = (row, column, cellValue) => {
    return parseFloat(cellValue).toFixed(2);
};
const { searchForm } = toRefs(data)
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
@@ -278,281 +230,158 @@
}
const getList = () => {
  tableLoading.value = true
  getStockInPage({ ...searchForm.value, ...page }).then(res => {
  const params = { ...page }
  // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹ä¼ é€’不同的查询参数
  if (activeTab.value === 'production') {
    params.customerName = searchForm.value.customerName
    params.timeStr = searchForm.value.timeStr
  } else {
    params.supplierName = searchForm.value.supplierName
    params.timeStr = searchForm.value.timeStr
  }
  params.productCategory = searchForm.value.productCategory
  // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹è°ƒç”¨ä¸åŒçš„æŽ¥å£
  const apiCall = activeTab.value === 'production'
    ? getStockInPageByProduction(params)
    : activeTab.value === 'manual'
    ? getInPageByCustom(params)
    : getStockInPage(params)
  apiCall.then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    // å‰ç«¯è®¡ç®—总价:总价 = unitPrice * inboundNum
    tableData.value = tableData.value.map(item => {
      // ä½¿ç”¨å…¥åº“数量计算总价
      const inboundNum = Number(item.inboundNum) || 0
      const unitPrice = Number(item.unitPrice) || 0
      const taxInclusiveUnitPrice = Number(item.taxInclusiveUnitPrice) || 0
      // æ ¹æ®æ ‡ç­¾é¡µç±»åž‹è®¡ç®—不同的总价
      if (activeTab.value === 'production') {
        // æˆå“åº“存:总价 = unitPrice * å…¥åº“数量
        item.totalPrice = (unitPrice * inboundNum).toFixed(2)
      } else {
        // åŽŸæ–™å’Œææ–™åº“å­˜ï¼šå«ç¨Žæ€»ä»· = taxInclusiveUnitPrice * å…¥åº“数量
        item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * inboundNum).toFixed(2)
      }
      return item
    })
    total.value = res.data.total
    console.log('tableData:', tableData.value)
  }).catch(() => {
    tableLoading.value = false
  })
}
// è°ƒç”¨selectProductRecordListByPuechaserId这个方法根据合同查询到id,再调用getProductRecordByhetong这个方法根据id查询到产品订单记录
// æ–°å¢žæ ¹æ®åˆåŒå·æŸ¥è¯¢äº§å“è®°å½•的方法
const fetchProductsByContract = async () =>
{
  if (!form.value.purchaseContractNumber) {
    proxy.$modal.msgWarning('请选择合同号')
    return
  }
  try {
    loadingProducts.value = true
    // æ ¹æ®åˆåŒæŸ¥è¯¢äº§å“è®°å½•
    const productRes = await selectProductRecordListByPuechaserId({
      purchaseContractNumber: form.value.purchaseContractNumber
    });
    console.log('productRes:', productRes)
    if (!productRes.data || productRes.data.length === 0) {
      proxy.$modal.msgWarning('该合同下没有产品记录')
      productList.value = [];
      return
    }
    // å¤„理产品数据,添加本次入库数量字段
    productList.value = productRes.data.map(item => ({
      ...item,
      quantityStock: 0,
      originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0),
    }))
  } catch (error) {
    console.error('查询产品记录失败:', error)
    proxy.$modal.msgError('查询产品记录失败')
    productList.value = [];
  } finally {
    loadingProducts.value = false
  }
// åˆ‡æ¢ tab
const handleTabChange = (tabName) => {
  page.current = 1
  // åˆ‡æ¢ tab æ—¶æ¸…空搜索条件
  searchForm.value.supplierName = ''
  searchForm.value.customerName = ''
  searchForm.value.timeStr = ''
  searchForm.value.productCategory = ''
  getList()
}
// æ‰“开弹框
  const openForm = async (type, row) => {
    operationType.value = type
    dialogFormVisible.value = true
    selectedRows.value = []
        await loadPurchaseOptions();
    if (type === 'add') {
      // æ–°å¢žæ—¶åˆå§‹åŒ–表单
      form.value = {
        id: null,
        purchaseContractNumber: '',
        supplierId: null,
        supplierName: '',
        inboundTime: '',
        inboundBatch: '',
        recorderId: userStore.userId,
        recorderName: userStore.name,
        entryDate: getCurrentDate(),
        remark: ''
      }
      productList.value = [] // æ¸…空产品列表
    } else {
      form.value = JSON.parse(JSON.stringify(row))
      try {
        loadingProducts.value = true
        // æ ¹æ®åˆåŒå·åŠ è½½å¯¹åº”çš„äº§å“åˆ—è¡¨ï¼ˆå‡è®¾ getProductByContract æ˜¯å¯ç”¨æŽ¥å£ï¼‰
        const res = await selectProductRecordListByPuechaserId({
          purchaseContractNumber: form.value.purchaseContractNumber,
          id: row.id
        });
                productList.value = res.data.map(item => ({
                    ...item,
                    quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
                    originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0),
                }))
        selectedRows.value = productList.value
      } catch (error) {
        console.error('加载产品失败:', error)
        proxy.$modal.msgError('加载产品失败')
        productList.value = []
      } finally {
        loadingProducts.value = false
      }
const openForm = async (type, row, tabType) => {
  const currentTab = tabType || activeTab.value
  await nextTick(() => {
    if (currentTab === 'manual') {
      formDiaManual.value?.openDialog(type, row)
    } else if (currentTab === 'production') {
            formDiaProduct.value?.openDialog(type, row)
        }else {
      formDia.value?.openDialog(type, row)
    }
  }
  })
}
  const updatePro = async () => {
     // å‡†å¤‡æäº¤æ•°æ®
     // å‡†å¤‡æäº¤æ•°æ® - ä¿®æ”¹ä¸ºåŽç«¯éœ€è¦çš„æ ¼å¼
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning('请先选择产品');
      return;
    }
    const target = selectedRows.value[0];
    const stock = Number(target?.quantityStock ?? 0);
    if (!Number.isFinite(stock) || stock <= 0) {
      proxy.$modal.msgWarning('请填写有效的入库数量');
      return;
    }
    if (exceedsEditLimit(target)) {
      proxy.$modal.msgError('本次入库数量不能超过原入库数量与待入库数量之和');
      return;
    }
    const stockInData = {
      id: selectedRows.value[0].recordId,
      quantityStock: Number(selectedRows.value[0].quantityStock),// ä½¿ç”¨æ–°æ ¼å¼åŒ–函数
    };
    await updateStockIn(stockInData)
    proxy.$modal.msgSuccess('修改入库成功')
    closeDia()
    getList() // åˆ·æ–°åˆ—表
  }
// æäº¤è¡¨å•
  const submitForm = async () => {
    // éªŒè¯è‡³å°‘选择了一个产品
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning('请先选择采购合同并选择产品')
      return
    }
    if(operationType.value !== 'add'){
      await updatePro()
      return
    }
    try {
      await proxy.$refs.formRef.validate()
      // éªŒè¯å…¥åº“数量
      const invalidProducts = selectedRows.value.filter((product) => {
          const stock = Number(product?.quantityStock ?? 0);
          if (!Number.isFinite(stock) || stock <= 0) {
            return true;
          }
          return exceedsAddLimit(product);
      })
      if (invalidProducts.length > 0) {
        proxy.$modal.msgError('本次入库数量需大于0,且不能超过待入库数量')
        return
      }
      // å‡†å¤‡æäº¤æ•°æ® - ä¿®æ”¹ä¸ºåŽç«¯éœ€è¦çš„æ ¼å¼
      const stockInData = {
        // å…¥åº“单基本信息
        ...form.value,
        inboundTime: formatDateTime(form.value.inboundTime),
        nickName: userStore.nickName,
        details: selectedRows.value.map(product => ({
          id: product.id,
          // id: product.salesLedgerProductId,
          inboundQuantity: Number(product.quantityStock)
        })),
      };
      // è°ƒç”¨API
      loading.value = true
      await addSutockIn(stockInData)
      proxy.$modal.msgSuccess('新增入库成功')
      closeDia()
      getList() // åˆ·æ–°åˆ—表
    } catch (error) {
      console.error('提交失败:', error)
      if (!error.errors) {
        proxy.$modal.msgError('操作失败,请重试')
      }
    } finally {
      loading.value = false
    }
  }
// å…³é—­å¼¹æ¡†
  const closeDia = () => {
    proxy.$refs.formRef.resetFields()
    dialogFormVisible.value = false
  }
// è¡¨æ ¼é€‰æ‹©æ•°æ®
  const handleSelectionChange = (selection) => {
    // è¿‡æ»¤æŽ‰å­æ•°æ®
    selectedRows.value = selection.filter(item => item.id);
  }
const handleSelectionChange = (selection) => {
  selectedRows.value = selection.filter(item => item.id)
}
  const expandedRowKeys = ref([])
const expandedRowKeys = ref([])
// ä¸»è¡¨åˆè®¡æ–¹æ³•
  const summarizeMainTable = (param) => {
    return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice']);
  };
const summarizeMainTable = (param) => {
  return proxy.summarizeTable(param, ['contractAmount', 'taxInclusiveTotalPrice', 'taxExclusiveTotalPrice'])
}
// å¯¼å‡º
  const handleOut = () => {
    ElMessageBox.confirm(
        '是否确认导出?',
        '导出', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        }
    ).then(() => {
      proxy.download("/stockin/export", {}, '入库台账.xlsx')
    }).catch(() => {
      proxy.$modal.msg("已取消")
    })
  }
// åˆ é™¤
  const handleDelete = () => {
    let ids = []
    if (selectedRows.value.length > 0) {
            // æ£€æŸ¥æ˜¯å¦æœ‰ä»–人维护的数据
            const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id);
            if (unauthorizedData.length > 0) {
                proxy.$modal.msgWarning("不可删除他人维护的数据");
                return;
            }
      ids = selectedRows.value.map(item => item.id);
    } else {
      proxy.$modal.msgWarning('请选择数据')
      return
const handleOut = () => {
  ElMessageBox.confirm('是否确认导出?', '导出', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹è°ƒç”¨ä¸åŒçš„导出接口
    let exportUrl = "/stockin/export"
    if (activeTab.value === 'production') {
      exportUrl = "/stockin/exportOne"
    } else if (activeTab.value === 'manual') {
      exportUrl = "/stockin/exportTwo"
    }
    ElMessageBox.confirm(
        '选中的内容将被删除,是否确认删除?',
        '导出', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        }
    ).then(() => {
      delStockIn({ids:ids}).then(res => {
        proxy.$modal.msgSuccess("删除成功")
        getList()
      })
    }).catch(() => {
      proxy.$modal.msg("已取消")
    })
  }
// èŽ·å–å½“å‰æ—¥æœŸå¹¶æ ¼å¼åŒ–ä¸º YYYY-MM-DD
// ä¿®æ”¹ä¸ºæ›´é€šç”¨çš„æ—¥æœŸæ—¶é—´æ ¼å¼åŒ–函数
function formatDateTime(date = new Date(), includeTime = true) {
  const d = new Date(date);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  if (!includeTime) {
    return `${year}-${month}-${day}`; // ä¿æŒåŽŸæœ‰ getCurrentDate åŠŸèƒ½
  }
  // æ–°å¢žæ—¶é—´éƒ¨åˆ†æ ¼å¼åŒ–
  const hours = String(d.getHours()).padStart(2, '0');
  const minutes = String(d.getMinutes()).padStart(2, '0');
  const seconds = String(d.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
// ä¿æŒåŽŸæœ‰ getCurrentDate çš„兼容性
function getCurrentDate() {
  return formatDateTime(new Date(), false);
}
  onMounted(() => {
    getList()
    proxy.download(exportUrl, {}, '入库台账.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
}
// åˆ é™¤
const handleDelete = () => {
  if (selectedRows.value.length === 0) {
    proxy.$modal.msgWarning('请选择数据')
    return
  }
  const ids = selectedRows.value.map(item => item.id)
  ElMessageBox.confirm('选中的内容将被删除,是否确认删除?', '删除', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    // æ ¹æ®å½“前 tab ç±»åž‹é€‰æ‹©ä¸åŒçš„删除接口和type参数
    let deleteApi, deleteParams
    if (activeTab.value === 'production') {
      // æˆå“åˆ é™¤ï¼Œtypeä¼ 2
      deleteApi = delStockIn
      deleteParams = { ids, type: 2 }
    } else if (activeTab.value === 'purchase') {
      // åŽŸæ–™åˆ é™¤ï¼Œtypeä¼ 1
      deleteApi = delStockIn
      deleteParams = { ids, type: 1 }
    } else {
      // ææ–™å…¥åº“
      deleteApi = delStockInCustom
      deleteParams = { ids }
    }
    deleteApi(deleteParams).then(() => {
      proxy.$modal.msgSuccess("删除成功")
      getList()
    }).catch(() => {
      proxy.$modal.msgError("删除失败")
    })
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
}
onMounted(() => {
  getList()
})
</script>
<style scoped lang="scss"></style>
src/views/inventoryManagement/stockManagement/components/FormDiaManual.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,154 @@
<template>
  <el-dialog :model-value="dialogFormVisible" :title="operationType === 'add' ? '新增材料库存' : '编辑材料库存'" width="70%"
    @update:model-value="$emit('update:dialogFormVisible', $event)" @close="closeDia">
    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="产品大类:" prop="productCategory">
            <el-input disabled v-model="form.productCategory" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="规格型号:" prop="specificationModel">
            <el-input disabled v-model="form.specificationModel" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="单位:" prop="unit">
            <el-input disabled v-model="form.unit" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="物品类型:" prop="itemType">
            <el-input disabled v-model="form.itemType" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="入库时间:" prop="createTime">
            <el-date-picker style="width: 100%" v-model="form.createTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
                            type="date" placeholder="请选择" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="库存数量:" prop="inboundNum">
            <el-input v-model="form.inboundNum" placeholder="请输入" clearable @input="calculateTotalPrice" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="已出库数量:" prop="totalInboundNum">
            <el-input disabled v-model="form.totalInboundNum" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="待出库数量:" prop="inboundNum0">
            <el-input disabled v-model="form.inboundNum0" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="单价(元):" prop="taxInclusiveUnitPrice">
            <el-input v-model="form.taxInclusiveUnitPrice" placeholder="请输入" clearable @input="calculateTotalPrice" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="总价(元):" prop="taxInclusiveTotalPrice">
            <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="自动计算" clearable />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确认</el-button>
        <el-button @click="closeDia">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, reactive, toRefs, watch } from 'vue'
const props = defineProps({
  dialogFormVisible: Boolean,
  operationType: String,
  formData: Object
})
const emit = defineEmits(['update:dialogFormVisible', 'submit', 'close'])
const formRef = ref()
const data = reactive({
  form: {
    productCategory: '',
    specificationModel: '',
    unit: '',
    itemType: '',
    createTime: '',
    inboundNum: '',
    totalInboundNum: '',
    inboundNum0: '',
    taxInclusiveUnitPrice: '',
    taxInclusiveTotalPrice: ''
  },
  rules: {
    productCategory: [{ required: true, message: '请输入产品大类', trigger: 'blur' }],
    specificationModel: [{ required: true, message: '请输入规格型号', trigger: 'blur' }],
    unit: [{ required: true, message: '请输入单位', trigger: 'blur' }],
    itemType: [{ required: true, message: '请输入物品类型', trigger: 'blur' }],
    createTime: [{ required: true, message: '请选择入库时间', trigger: 'change' }],
    inboundNum: [{ required: true, message: '请输入库存数量', trigger: 'blur' }],
    taxInclusiveUnitPrice: [{ required: true, message: '请输入单价', trigger: 'blur' }]
  }
})
const { form, rules } = toRefs(data)
// è®¡ç®—总价:总价 = å•ä»· Ã— å‰©ä½™åº“å­˜
const calculateTotalPrice = () => {
  const unitPrice = parseFloat(form.value.taxInclusiveUnitPrice) || 0
  const stockQuantity = parseFloat(form.value.inboundNum) || 0 // åº“存数量
  const outboundQuantity = parseFloat(form.value.totalInboundNum) || 0 // å·²å‡ºåº“数量
  const remainingStock = stockQuantity - outboundQuantity // å‰©ä½™åº“å­˜
  form.value.taxInclusiveTotalPrice = (unitPrice * remainingStock).toFixed(2)
}
// ç›‘听formData变化
watch(() => props.formData, (newVal) => {
  if (newVal) {
    form.value = { ...newVal }
    // æ•°æ®å˜åŒ–后重新计算总价
    calculateTotalPrice()
  }
}, { immediate: true })
// æäº¤è¡¨å•
const submitForm = () => {
  formRef.value.validate(valid => {
    if (valid) {
      emit('submit', form.value)
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  emit('close')
  emit('update:dialogFormVisible', false)
}
</script>
<style scoped lang="scss">
.dialog-footer {
  text-align: center;
}
</style>
src/views/inventoryManagement/stockManagement/components/FormDiaProduction.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,147 @@
<template>
  <el-dialog :model-value="dialogFormVisible" :title="operationType === 'add' ? '新增成品库存' : '编辑成品库存'" width="70%"
    @update:model-value="$emit('update:dialogFormVisible', $event)" @close="closeDia">
    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="产品大类:" prop="productCategory">
            <el-input disabled v-model="form.productCategory" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="规格型号:" prop="specificationModel">
            <el-input disabled v-model="form.specificationModel" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="单位:" prop="unit">
            <el-input disabled v-model="form.unit" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="入库时间:" prop="createTime">
            <el-date-picker style="width: 100%" v-model="form.createTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
                            type="date" placeholder="请选择" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="库存数量:" prop="inboundNum">
            <el-input v-model="form.inboundNum" placeholder="请输入" clearable @input="calculateTotalPrice" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="已出库数量:" prop="totalInboundNum">
            <el-input disabled v-model="form.totalInboundNum" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="待出库数量:" prop="inboundNum0">
            <el-input disabled v-model="form.inboundNum0" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="单价(元):" prop="unitPrice">
            <el-input v-model="form.unitPrice" placeholder="请输入" clearable @input="calculateTotalPrice" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="总价(元):" prop="totalPrice">
            <el-input disabled v-model="form.totalPrice" placeholder="自动计算" clearable />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确认</el-button>
        <el-button @click="closeDia">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, reactive, toRefs, watch } from 'vue'
const props = defineProps({
  dialogFormVisible: Boolean,
  operationType: String,
  formData: Object
})
const emit = defineEmits(['update:dialogFormVisible', 'submit', 'close'])
const formRef = ref()
const data = reactive({
  form: {
    productCategory: '',
    specificationModel: '',
    unit: '',
    createTime: '',
    inboundNum: '',
    totalInboundNum: '',
    inboundNum0: '',
    unitPrice: '',
    totalPrice: ''
  },
  rules: {
    productCategory: [{ required: true, message: '请输入产品大类', trigger: 'blur' }],
    specificationModel: [{ required: true, message: '请输入规格型号', trigger: 'blur' }],
    unit: [{ required: true, message: '请输入单位', trigger: 'blur' }],
    createTime: [{ required: true, message: '请选择入库时间', trigger: 'change' }],
    inboundNum: [{ required: true, message: '请输入库存数量', trigger: 'blur' }],
    unitPrice: [{ required: true, message: '请输入单价', trigger: 'blur' }]
  }
})
const { form, rules } = toRefs(data)
// è®¡ç®—总价:总价 = å•ä»· Ã— å‰©ä½™åº“å­˜
const calculateTotalPrice = () => {
  const unitPrice = parseFloat(form.value.unitPrice) || 0
  const stockQuantity = parseFloat(form.value.inboundNum) || 0 // åº“存数量
  const outboundQuantity = parseFloat(form.value.totalInboundNum) || 0 // å·²å‡ºåº“数量
  const remainingStock = stockQuantity - outboundQuantity // å‰©ä½™åº“å­˜
  form.value.totalPrice = (unitPrice * remainingStock).toFixed(2)
}
// ç›‘听formData变化
watch(() => props.formData, (newVal) => {
  if (newVal) {
    form.value = { ...newVal }
    // æ•°æ®å˜åŒ–后重新计算总价
    calculateTotalPrice()
  }
}, { immediate: true })
// æäº¤è¡¨å•
const submitForm = () => {
  formRef.value.validate(valid => {
    if (valid) {
      emit('submit', form.value)
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  emit('close')
  emit('update:dialogFormVisible', false)
}
</script>
<style scoped lang="scss">
.dialog-footer {
  text-align: center;
}
</style>
src/views/inventoryManagement/stockManagement/components/FormDiaPurchase.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,147 @@
<template>
  <el-dialog :model-value="dialogFormVisible" :title="operationType === 'add' ? '新增原料库存' : '编辑原料库存'" width="70%"
    @update:model-value="$emit('update:dialogFormVisible', $event)" @close="closeDia">
    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="产品大类:" prop="productCategory">
            <el-input disabled v-model="form.productCategory" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="规格型号:" prop="specificationModel">
            <el-input disabled v-model="form.specificationModel" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="单位:" prop="unit">
            <el-input disabled v-model="form.unit" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="入库时间:" prop="createTime">
            <el-date-picker style="width: 100%" v-model="form.createTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
                            type="date" placeholder="请选择" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="库存数量:" prop="inboundNum">
            <el-input v-model="form.inboundNum" placeholder="请输入" clearable @input="calculateTotalPrice" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="已出库数量:" prop="totalInboundNum">
            <el-input disabled v-model="form.totalInboundNum" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="待出库数量:" prop="inboundNum0">
            <el-input disabled v-model="form.inboundNum0" placeholder="请输入" clearable />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="含税单价(元):" prop="taxInclusiveUnitPrice">
            <el-input v-model="form.taxInclusiveUnitPrice" placeholder="请输入" clearable @input="calculateTotalPrice" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="含税总价(元):" prop="taxInclusiveTotalPrice">
            <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="自动计算" clearable />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确认</el-button>
        <el-button @click="closeDia">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, reactive, toRefs, watch } from 'vue'
const props = defineProps({
  dialogFormVisible: Boolean,
  operationType: String,
  formData: Object
})
const emit = defineEmits(['update:dialogFormVisible', 'submit', 'close'])
const formRef = ref()
const data = reactive({
  form: {
    productCategory: '',
    specificationModel: '',
    unit: '',
    createTime: '',
    inboundNum: '',
    totalInboundNum: '',
    inboundNum0: '',
    taxInclusiveUnitPrice: '',
    taxInclusiveTotalPrice: ''
  },
  rules: {
    productCategory: [{ required: true, message: '请输入产品大类', trigger: 'blur' }],
    specificationModel: [{ required: true, message: '请输入规格型号', trigger: 'blur' }],
    unit: [{ required: true, message: '请输入单位', trigger: 'blur' }],
    createTime: [{ required: true, message: '请选择入库时间', trigger: 'change' }],
    inboundNum: [{ required: true, message: '请输入库存数量', trigger: 'blur' }],
    taxInclusiveUnitPrice: [{ required: true, message: '请输入含税单价', trigger: 'blur' }]
  }
})
const { form, rules } = toRefs(data)
// è®¡ç®—总价:含税总价 = å«ç¨Žå•ä»· Ã— å‰©ä½™åº“å­˜
const calculateTotalPrice = () => {
  const unitPrice = parseFloat(form.value.taxInclusiveUnitPrice) || 0
  const stockQuantity = parseFloat(form.value.inboundNum) || 0 // åº“存数量
  const outboundQuantity = parseFloat(form.value.totalInboundNum) || 0 // å·²å‡ºåº“数量
  const remainingStock = stockQuantity - outboundQuantity // å‰©ä½™åº“å­˜
  form.value.taxInclusiveTotalPrice = (unitPrice * remainingStock).toFixed(2)
}
// ç›‘听formData变化
watch(() => props.formData, (newVal) => {
  if (newVal) {
    form.value = { ...newVal }
    // æ•°æ®å˜åŒ–后重新计算总价
    calculateTotalPrice()
  }
}, { immediate: true })
// æäº¤è¡¨å•
const submitForm = () => {
  formRef.value.validate(valid => {
    if (valid) {
      emit('submit', form.value)
    }
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  emit('close')
  emit('update:dialogFormVisible', false)
}
</script>
<style scoped lang="scss">
.dialog-footer {
  text-align: center;
}
</style>
src/views/inventoryManagement/stockManagement/index.vue
@@ -1,151 +1,191 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">供应商名称:</span>
        <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请输入" @change="handleQuery"
          clearable prefix-icon="Search" />
                <span class="search_title ml10">入库日期:</span>
                <el-date-picker
                    v-model="searchForm.timeStr"
                    type="date"
                    placeholder="请选择日期"
                    value-format="YYYY-MM-DD"
                    format="YYYY-MM-DD"
                    clearable
                    @change="handleQuery"
                />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
      </div>
      <div>
        <!-- <el-button type="primary" @click="openForm('add')">新增</el-button> -->
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
        :row-class-name="tableRowClassName"
        :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="入库日期" prop="createTime" width="100" show-overflow-tooltip />
        <el-table-column label="供应商名称" prop="supplierName" width="240" show-overflow-tooltip />
        <el-table-column label="产品大类" prop="productCategory" width="100" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="specificationModel" width="200" show-overflow-tooltip />
        <el-table-column label="单位" prop="unit" width="80" show-overflow-tooltip />
        <el-table-column label="库存数量" prop="inboundNum0" width="100" show-overflow-tooltip />
        <el-table-column label="库存预警数量" prop="warnNum" width="130" show-overflow-tooltip />
        <el-table-column label="含税单价" prop="taxInclusiveUnitPrice" width="100" show-overflow-tooltip />
        <el-table-column label="含税总价" prop="taxInclusiveTotalPrice" width="100" show-overflow-tooltip />
        <el-table-column label="税率(%)" prop="taxRate" width="100" show-overflow-tooltip />
        <el-table-column label="不含税总价" prop="taxExclusiveTotalPrice" width="100" show-overflow-tooltip />
        <el-table-column label="入库人" prop="createBy" width="80" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="60" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="openForm('edit', scope.row);" :disabled="scope.row.createUser !== userStore.id">编辑</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
        :page="page.current" :limit="page.size" @pagination="paginationChange" />
    </div>
    <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增库存' : '编辑库存'" width="70%"
      @close="closeDia">
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="供应商名称:" prop="supplierName">
              <el-input disabled v-model="form.supplierName" placeholder="请输入" clearable />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="产品大类:" prop="productId">
              <el-select disabled v-model="form.productCategory" placeholder="请选择" clearable filterable>
                <el-option v-for="item in productList" :key="item.id" :label="item.productName"
                           :value="item.productName" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="productManageId">
              <el-select disabled v-model="form.specificationModel" placeholder="请先选择产品大类" clearable filterable :disabled="!form.productCategory">
                <el-option v-for="item in productModelList" :key="item.id" :label="item.model"
                           :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item  label="单位:" prop="customerId">
              <el-input disabled v-model="form.unit" placeholder="请输入" clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="库存时间:" prop="projectName">
              <el-date-picker style="width: 100%" v-model="form.updateTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
                type="date" placeholder="请选择" clearable />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="入库时间:" prop="projectName">
              <el-date-picker style="width: 100%" v-model="form.createTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
                type="date" placeholder="请选择" clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item  label="含税单价:" prop="customerId">
              <el-input disabled v-model="form.taxInclusiveUnitPrice" placeholder="请输入" clearable />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item  label="含税总价:" prop="customerContractNo">
              <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="请输入" clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item  label="税率:" prop="customerId">
              <el-input disabled v-model="form.taxRate" placeholder="请输入" clearable />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="不含税总价:" prop="entryDate">
              <el-input disabled v-model="form.taxExclusiveTotalPrice" placeholder="请输入" clearable />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="出库人:" prop="entryPerson">
              <el-select v-model="form.createUser" placeholder="请选择" clearable>
                <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
              </el-select>
            </el-form-item>
          </el-col>
<!--          <el-col :span="12">-->
<!--          <el-form-item label="库存预警数量:" prop="warnNum">-->
<!--            <el-input v-model="form.warnNum" placeholder="请输入最低库存" clearable />-->
<!--          </el-form-item>-->
<!--        </el-col>-->
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
    <el-tabs v-model="activeTab" @tab-change="handleTabChange">
      <el-tab-pane label="成品库存" name="production">
        <div class="search_form">
          <div>
            <span class="search_title ml10">入库日期:</span>
            <el-date-picker
              v-model="searchForm.timeStr"
              type="date"
              placeholder="请选择日期"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              clearable
              @change="handleQuery"
            />
                            <span class="search_title ml10">产品大类:</span>
                            <el-input
                                v-model="searchForm.productCategory"
                                style="width: 240px"
                                placeholder="请输入"
                                clearable
                            />
            <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
          </div>
          <div>
            <el-button @click="handleOut">导出</el-button>
<!--            <el-button type="danger" plain @click="handleDelete">删除</el-button>-->
          </div>
        </div>
      </template>
    </el-dialog>
        <div class="table_list">
          <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
            :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
            :row-class-name="tableRowClassName"
            :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
            <el-table-column align="center" type="selection" width="55" />
            <el-table-column align="center" label="序号" type="index" width="60" />
            <el-table-column label="入库日期" prop="createTime" width="100" show-overflow-tooltip />
                        <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
            <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
            <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
            <el-table-column label="单位" prop="unit" width="80" show-overflow-tooltip />
            <el-table-column label="已出库数量" prop="totalInboundNum" width="100" show-overflow-tooltip />
            <el-table-column label="剩余库存" prop="inboundNum0" width="100" show-overflow-tooltip />
                            <el-table-column label="单价(元)" prop="unitPrice" width="150"></el-table-column>
                            <el-table-column label="总价(元)" prop="totalPrice" width="150"></el-table-column>
            <el-table-column fixed="right" label="操作" min-width="60" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="openForm('edit', scope.row);">编辑</el-button>
              </template>
            </el-table-column>
          </el-table>
          <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
            :page="page.current" :limit="page.size" @pagination="paginationChange" />
        </div>
      </el-tab-pane>
     <el-tab-pane label="原料库存" name="purchase">
       <div class="search_form">
         <div>
           <span class="search_title ml10">入库日期:</span>
           <el-date-picker
             v-model="searchForm.timeStr"
             type="date"
             placeholder="请选择日期"
             value-format="YYYY-MM-DD"
             format="YYYY-MM-DD"
             clearable
             @change="handleQuery"
           />
                            <span class="search_title ml10">产品大类:</span>
                            <el-input
                                v-model="searchForm.productCategory"
                                style="width: 240px"
                                placeholder="请输入"
                                clearable
                            />
           <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
         </div>
         <div>
           <el-button @click="handleOut">导出</el-button>
<!--           <el-button type="danger" plain @click="handleDelete">删除</el-button>-->
         </div>
       </div>
       <div class="table_list">
         <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
           :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
           :row-class-name="tableRowClassName"
           :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
           <el-table-column align="center" type="selection" width="55" />
           <el-table-column align="center" label="序号" type="index" width="60" />
           <el-table-column label="入库日期" prop="createTime" width="100" show-overflow-tooltip />
                     <el-table-column label="采购合同号" prop="purchaseContractNumber" width="180" show-overflow-tooltip />
           <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
           <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
           <el-table-column label="单位" prop="unit" width="80" show-overflow-tooltip />
                            <el-table-column label="已出库数量" prop="totalInboundNum" show-overflow-tooltip />
                            <el-table-column label="剩余库存" prop="inboundNum0" show-overflow-tooltip />
                         <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" width="150"></el-table-column>
                         <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" width="150"></el-table-column>
         </el-table>
         <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
           :page="page.current" :limit="page.size" @pagination="paginationChange" />
       </div>
     </el-tab-pane>
      <el-tab-pane label="材料库存" name="manual">
        <div class="search_form">
          <div>
            <span class="search_title ml10">入库日期:</span>
            <el-date-picker
              v-model="searchForm.timeStr"
              type="date"
              placeholder="请选择日期"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              clearable
              @change="handleQuery"
            />
                            <span class="search_title ml10">产品大类:</span>
                            <el-input
                                v-model="searchForm.productCategory"
                                style="width: 240px"
                                placeholder="请输入"
                                clearable
                            />
            <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
          </div>
          <div>
            <el-button @click="handleOut">导出</el-button>
<!--            <el-button type="danger" plain @click="handleDelete">删除</el-button>-->
          </div>
        </div>
        <div class="table_list">
          <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
            :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%"
            :row-class-name="tableRowClassName"
            :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)">
            <el-table-column align="center" type="selection" width="55" />
            <el-table-column align="center" label="序号" type="index" width="60" />
            <el-table-column label="入库日期" prop="inboundDate" width="100" show-overflow-tooltip />
                        <el-table-column label="批次号" prop="code" width="130" show-overflow-tooltip />
            <el-table-column label="产品大类" prop="productCategory" show-overflow-tooltip />
            <el-table-column label="规格型号" prop="specificationModel" show-overflow-tooltip />
            <el-table-column label="单位" prop="unit" width="80" show-overflow-tooltip />
            <el-table-column label="物品类型" prop="itemType" width="120" show-overflow-tooltip />
                            <el-table-column label="已出库数量" prop="totalInboundNum" width="100" show-overflow-tooltip />
                            <el-table-column label="剩余库存" prop="inboundNum0" width="100" show-overflow-tooltip />
                            <el-table-column label="单价(元)" prop="taxInclusiveUnitPrice" width="150"></el-table-column>
                            <el-table-column label="总价(元)" prop="taxInclusiveTotalPrice" width="150"></el-table-column>
            <el-table-column fixed="right" label="操作" width="100" align="center">
              <template #default="scope">
                <el-button link type="primary" size="small" @click="openForm('edit', scope.row);">编辑</el-button>
              </template>
            </el-table-column>
          </el-table>
          <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
            :page="page.current" :limit="page.size" @pagination="paginationChange" />
        </div>
      </el-tab-pane>
    </el-tabs>
    <!-- æˆå“åº“存弹框 -->
    <FormDiaProduction
      v-model:dialogFormVisible="productionDialogVisible"
      :operationType="operationType"
      :formData="form"
      @submit="submitForm"
      @close="closeDia"
    />
    <!-- åŽŸæ–™åº“å­˜å¼¹æ¡† -->
    <FormDiaPurchase
      v-model:dialogFormVisible="purchaseDialogVisible"
      :operationType="operationType"
      :formData="form"
      @submit="submitForm"
      @close="closeDia"
    />
    <!-- ææ–™åº“存弹框 -->
    <FormDiaManual
      v-model:dialogFormVisible="manualDialogVisible"
      :operationType="operationType"
      :formData="form"
      @submit="submitForm"
      @close="closeDia"
    />
  </div>
</template>
@@ -158,13 +198,18 @@
import { productTreeList,modelList } from "@/api/basicData/product.js"
import {
  getStockManagePage,
  getStockManagePageByProduction,
  getStockManagePageByCustom,
  delStockManage,
} from "@/api/inventoryManagement/stockManage.js";
import {
  updateManagement,updateStockIn
    updateManagement, updateManagementByCustom, updateStockIn
} from "@/api/inventoryManagement/stockIn.js";
// å¯¼å…¥ä¸‰ä¸ªç‹¬ç«‹çš„弹框组件
import FormDiaProduction from './components/FormDiaProduction.vue'
import FormDiaPurchase from './components/FormDiaPurchase.vue'
import FormDiaManual from './components/FormDiaManual.vue'
const userStore = useUserStore()
const { proxy } = getCurrentInstance()
@@ -185,15 +230,23 @@
const loading = ref(false);
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref('')
const dialogFormVisible = ref(false)
const activeTab = ref('production')
// ä¸‰ä¸ªç‹¬ç«‹çš„弹框显示状态
const productionDialogVisible = ref(false)
const purchaseDialogVisible = ref(false)
const manualDialogVisible = ref(false)
const data = reactive({
  searchForm: {
    supplierName: '',
        timeStr: '',
    // supplierName: '',
    productCategory:'',
    customerName: '',
    timeStr: getCurrentDate(),
  },
  form: {
    supplierId: null,
    supplierName: '',
    // supplierName: '',
    productId: null,
    productName: '',
    userId: userStore.userId,
@@ -202,6 +255,7 @@
    model: '',
    unit: '',
    productrecordId: null,
    unitPrice: '', // æ·»åŠ æˆå“åº“å­˜çš„å•ä»·å­—æ®µ
    taxInclusiveUnitPrice: '',
    taxInclusiveTotalPrice: '',
    taxRate: '',
@@ -214,11 +268,12 @@
    salesLedgerProductId: null,
  },
  rules: {
    supplierName: [{ required: true, message: '请输入供应商名称', trigger: 'blur' }],
    // supplierName: [{ required: true, message: '请输入供应商名称', trigger: 'blur' }],
    productCategory: [{ required: true, message: '请选择产品大类', trigger: 'change' }],
    specificationModel: [{ required: true, message: '请输入规格型号', trigger: 'blur' }],
    unit: [{ required: true, message: '请输入单位', trigger: 'blur' }],
    stockQuantity: [{ required: true, message: '请输入出库数量', trigger: 'blur' }],
    unitPrice: [{ required: true, message: '请输入单价', trigger: 'blur' }], // æ·»åŠ æˆå“åº“å­˜å•ä»·çš„éªŒè¯è§„åˆ™
    taxInclusiveUnitPrice: [{ required: true, message: '请输入含税单价', trigger: 'blur' }],
    taxInclusiveTotalPrice: [{ required: true, message: '请输入含税总价', trigger: 'blur' }],
    taxRate: [{ required: true, message: '请输入税率', trigger: 'blur' }],
@@ -242,17 +297,77 @@
  page.size = obj.limit;
  getList()
}
const buildQueryParams = () => {
  const params = {
    ...page,
    timeStr: searchForm.value.timeStr,
  }
  params.productCategory = searchForm.value.productCategory
  if (activeTab.value === 'production') {
    params.customerName = searchForm.value.customerName
  } else {
    // params.supplierName = searchForm.value.supplierName
  }
  return params
}
const getList = () => {
  tableLoading.value = true
  getStockManagePage({ ...searchForm.value, ...page }).then(res => {
  const params = buildQueryParams()
  let apiCall
  if (activeTab.value === 'production') {
    apiCall = getStockManagePageByProduction(params)
  } else if (activeTab.value === 'manual') {
    apiCall = getStockManagePageByCustom(params)
  } else {
    apiCall = getStockManagePage(params)
  }
  apiCall.then(res => {
    tableLoading.value = false
    tableData.value = res.data.records
    // ä¸ºè¡¨æ ¼æ•°æ®è‡ªåŠ¨è®¡ç®—æ€»ä»·
    tableData.value = tableData.value.map(item => {
      // è®¡ç®—剩余库存
      const stockQuantity = parseFloat(item.inboundNum) || 0
      const outboundQuantity = parseFloat(item.totalInboundNum) || 0
      const remainingStock = Math.max(stockQuantity - outboundQuantity, 0)
      // æ ¹æ®æ ‡ç­¾é¡µç±»åž‹è®¡ç®—总价
      if (activeTab.value === 'production') {
        // æˆå“åº“存:总价 = å•ä»· Ã— å‰©ä½™åº“å­˜
        const unitPrice = parseFloat(item.unitPrice) || 0
        item.totalPrice = (unitPrice * remainingStock).toFixed(2)
      } else if (activeTab.value === 'purchase') {
        // åŽŸæ–™åº“å­˜ï¼šå«ç¨Žæ€»ä»· = å«ç¨Žå•ä»· Ã— å‰©ä½™åº“å­˜
        const taxInclusiveUnitPrice = parseFloat(item.taxInclusiveUnitPrice) || 0
        item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * remainingStock).toFixed(2)
      } else if (activeTab.value === 'manual') {
        // ææ–™åº“存:含税总价 = å«ç¨Žå•ä»· Ã— å‰©ä½™åº“å­˜
        const taxInclusiveUnitPrice = parseFloat(item.taxInclusiveUnitPrice) || 0
        item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * remainingStock).toFixed(2)
      }
      return item
    })
    total.value = res.data.total
    // æ•°æ®åŠ è½½å®ŒæˆåŽæ£€æŸ¥åº“å­˜
    // checkStockAndCreatePurchase();
  }).catch(() => {
    tableLoading.value = false
  })
}
// åˆ‡æ¢ tab
const handleTabChange = () => {
  page.current = 1
  // searchForm.value.supplierName = ''
  searchForm.value.customerName = ''
  searchForm.value.timeStr = ''
  selectedRows.value = []
  searchForm.value.productCategory = ''
  getList()
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
@@ -300,23 +415,63 @@
    })
  }
  form.value.entryDate = getCurrentDate() // è®¾ç½®é»˜è®¤å½•入日期为当前日期
  dialogFormVisible.value = true
  // æ ¹æ®å½“前标签页显示对应的弹框
  if (activeTab.value === 'production') {
    productionDialogVisible.value = true
  } else if (activeTab.value === 'purchase') {
    purchaseDialogVisible.value = true
  } else if (activeTab.value === 'manual') {
    manualDialogVisible.value = true
  }
}
// æäº¤è¡¨å•
const submitForm = () => {
  console.log(form.value)
  proxy.$refs["formRef"].validate(valid => {
    if (valid) {
      updateManagement(form.value).then(res => {
        proxy.$modal.msgSuccess("提交成功")
        closeDia()
        getList()
        // æäº¤åŽæ£€æŸ¥åº“存并尝试创建请购单
        // checkStockAndCreatePurchase();
      })
    }
const submitForm = (submittedData) => {
  console.log('子组件提交的数据:', submittedData)
  // ä½¿ç”¨å­ç»„件提交的数据,而不是父组件的form对象
  const submitData = { ...submittedData }
  // æ ¹æ®å½“前标签页移除对应的总价字段
  if (activeTab.value === 'production') {
    // æˆå“åº“存:移除总价字段
    delete submitData.totalPrice
  } else if (activeTab.value === 'purchase') {
    // åŽŸæ–™åº“å­˜ï¼šç§»é™¤å«ç¨Žæ€»ä»·å­—æ®µ
    delete submitData.taxInclusiveTotalPrice
  } else if (activeTab.value === 'manual') {
    // ææ–™åº“存:移除含税总价字段
    delete submitData.taxInclusiveTotalPrice
  }
  // ç§»é™¤å…¶ä»–可能的总价字段
  delete submitData.taxExclusiveTotalPrice
  console.log('提交给后端的数据(已移除总价字段):', submitData)
  // æ ¹æ®å½“前标签页调用不同的提交接口
  let apiCall
  if (activeTab.value === 'production') {
    // æˆå“åº“存使用 updateManagement æŽ¥å£
    apiCall = updateManagement(submitData)
  } else if (activeTab.value === 'manual') {
    // ææ–™åº“存使用 updateManagementByCustom æŽ¥å£
    apiCall = updateManagementByCustom(submitData)
  } else {
    // åŽŸæ–™åº“å­˜ä½¿ç”¨ updateManagementByCustom æŽ¥å£
    apiCall = updateManagementByCustom(submitData)
  }
  apiCall.then(res => {
    proxy.$modal.msgSuccess("提交成功")
    closeDia()
    getList()
    // æäº¤åŽæ£€æŸ¥åº“存并尝试创建请购单
    // checkStockAndCreatePurchase();
  }).catch(error => {
    console.error('提交失败:', error)
    proxy.$modal.msgError("提交失败,请重试")
  })
}
// æ£€æŸ¥åº“存并创建请购单
@@ -344,7 +499,9 @@
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef")
  dialogFormVisible.value = false
  productionDialogVisible.value = false
  purchaseDialogVisible.value = false
  manualDialogVisible.value = false
}
// å¯¼å‡º
@@ -357,7 +514,15 @@
    type: 'warning',
  }
  ).then(() => {
    proxy.download("/stockin/exportCopy", {}, '库存信息.xlsx')
    const exportParams = buildQueryParams()
    // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹è°ƒç”¨ä¸åŒçš„导出接口
    let exportUrl = "/stockin/exportCopy"
    if (activeTab.value === 'production') {
      exportUrl = "/stockin/exportCopyOne"
    } else if (activeTab.value === 'manual') {
      exportUrl = "/stockin/exportCopyTwo"
    }
    proxy.download(exportUrl, exportParams, '库存信息.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  })
@@ -366,12 +531,6 @@
const handleDelete = () => {
  let ids = []
  if (selectedRows.value.length > 0) {
        // æ£€æŸ¥æ˜¯å¦æœ‰ä»–人维护的数据
        const unauthorizedData = selectedRows.value.filter(item => item.createUser !== userStore.id);
        if (unauthorizedData.length > 0) {
            proxy.$modal.msgWarning("不可删除他人维护的数据");
            return;
        }
    ids = selectedRows.value.map(item => item.id);
  } else {
    proxy.$modal.msgWarning('请选择数据')
@@ -423,4 +582,4 @@
:deep(.row-low-stock:hover > td) {
  background-color: #fcd4d4;
}
</style>
</style>
src/views/personnelManagement/contractManagement/filesDia.vue
@@ -30,16 +30,10 @@
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="500"
                    :page="page"
                    @pagination="pagination"
      >
      </PIMTable>
            <pagination
                style="margin: 10px 0"
                v-show="total > 0"
                @pagination="paginationSearch"
                :total="total"
                :page="page.current"
                :limit="page.size"
            />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
@@ -98,6 +92,7 @@
const page = reactive({
    current: 1,
    size: 100,
    total: 0
});
const total = ref(0);
const tableData = ref([]);
@@ -116,7 +111,7 @@
  currentId.value = row.id;
  getList()
}
const paginationSearch = (obj) => {
const pagination = (obj) => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
@@ -124,7 +119,7 @@
const getList = () => {
  fileListPage({accountId: currentId.value,accountType:accountType.value, ...page}).then(res => {
    tableData.value = res.data.records;
        total.value = res.data.total;
        page.total = res.data.total;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
src/views/personnelManagement/contractManagement/index.vue
@@ -70,11 +70,11 @@
</template>
<script setup>
import { Search } from "@element-plus/icons-vue";
import { onMounted, ref } from "vue";
import { Search, UploadFilled } from "@element-plus/icons-vue";
import { onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick } from "vue";
import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue";
import { ElMessageBox } from "element-plus";
import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js";
import { staffOnJobListPage, staffOnJobExportCopy } from "@/api/personnelManagement/employeeRecord.js";
import dayjs from "dayjs";
import { getToken } from "@/utils/auth.js";
import FilesDia from "./filesDia.vue";
@@ -183,7 +183,7 @@
    label: "操作",
    align: "center",
    fixed: 'right',
    width: 120,
    width: 180,
    operation: [
      {
        name: "详情",
@@ -197,6 +197,13 @@
        type: "text",
        clickFun: (row) => {
          openFilesFormDia(row);
        },
      },
      {
        name: "下载合同",
        type: "text",
        clickFun: (row) => {
          handleDownloadContract(row);
        },
      },
    ],
@@ -278,6 +285,33 @@
      proxy.$modal.msg("已取消");
    });
};
// ä¸‹è½½åˆåŒ
const handleDownloadContract = (row) => {
  const fileName = `${row.staffName || "合同"}劳动合同.docx`;
  proxy.$modal?.loading?.("正在生成合同,请稍候...");
  staffOnJobExportCopy({ ...row })
    .then((res) => {
      proxy.$modal?.closeLoading?.();
      if (res?.code === 200 && res?.msg) {
        const javaApi = proxy.javaApi || import.meta.env.VITE_JAVA_API || "";
        const downloadPath = res.msg.startsWith("/") ? res.msg : `/${res.msg}`;
        const downloadUrl = `${javaApi}${downloadPath}`;
        const link = document.createElement("a");
        link.href = downloadUrl;
        link.download = fileName;
        link.target = "_blank";
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      } else {
        proxy.$modal.msgError(res?.msg || "合同生成失败");
      }
    })
    .catch(() => {
      proxy.$modal?.closeLoading?.();
      proxy.$modal.msgError("合同生成失败,请稍后重试");
    });
};
const upload = reactive({
  // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚(合同导入)
  open: false,
src/views/personnelManagement/dimission/components/formDia.vue
@@ -13,7 +13,9 @@
          <el-col :span="12">
            <div class="info-item">
              <span class="info-label">姓名:</span>
              <el-select v-model="form.staffName" placeholder="请选择人员" style="width: 100%" @change="handleSelect">
              <el-select v-model="form.staffName"                 filterable
                         default-first-option
                         :reserve-keyword="false" placeholder="请选择人员" style="width: 100%" @change="handleSelect">
                <el-option
                  v-for="item in personList"
                  :key="item.id"
src/views/personnelManagement/employeeRecord/components/formDia.vue
@@ -6,16 +6,56 @@
        width="70%"
        @close="closeDia"
    >
      <PIMTable
          rowKey="id"
          :column="tableColumn"
          :tableData="tableData"
          :tableLoading="tableLoading"
          height="600"
      ></PIMTable>
      <el-descriptions class="detail-descriptions" :column="2" border size="small">
        <el-descriptions-item label="员工编号">{{ formData.staffNo || '-' }}</el-descriptions-item>
        <el-descriptions-item label="姓名">{{ formData.staffName || '-' }}</el-descriptions-item>
        <el-descriptions-item label="性别">{{ formData.sex || '-' }}</el-descriptions-item>
        <el-descriptions-item label="年龄">{{ formData.age || '-' }}</el-descriptions-item>
        <el-descriptions-item label="身份证号">{{ formData.identityCard || '-' }}</el-descriptions-item>
        <el-descriptions-item label="户籍住址" :span="2">{{ formData.nativePlace || '-' }}</el-descriptions-item>
        <el-descriptions-item label="现住址" :span="2">{{ formData.adress || '-' }}</el-descriptions-item>
        <el-descriptions-item label="岗位">{{ formData.postJob || '-' }}</el-descriptions-item>
        <el-descriptions-item label="第一学历">{{ formData.firstStudy || '-' }}</el-descriptions-item>
        <el-descriptions-item label="专业">{{ formData.profession || '-' }}</el-descriptions-item>
        <el-descriptions-item label="联系电话">{{ formData.phone || '-' }}</el-descriptions-item>
        <el-descriptions-item label="紧急联系人">{{ formData.emergencyContact || '-' }}</el-descriptions-item>
        <el-descriptions-item label="紧急联系人电话">{{ formData.emergencyContactPhone || '-' }}</el-descriptions-item>
        <el-descriptions-item label="合同签订日期">{{ formData.signDate || '-' }}</el-descriptions-item>
        <el-descriptions-item label="劳动合同期限选择">
          <span v-if="formData.dateSelect === 'A'">A、有固定期限</span>
          <span v-else-if="formData.dateSelect === 'B'">B、无固定期限</span>
          <span v-else-if="formData.dateSelect === 'C'">C、以完成一定工作任务为期限</span>
          <span v-else>-</span>
        </el-descriptions-item>
        <el-descriptions-item label="合同年限">{{ formattedContractTerm }}</el-descriptions-item>
        <el-descriptions-item label="试用期开始日期" v-if="formData.dateSelect === 'A' || formData.dateSelect === 'B'">
          {{ formData.trialStartDate || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="试用期结束日期" v-if="formData.dateSelect === 'A' || formData.dateSelect === 'B'">
          {{ formData.trialEndDate || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="试用期工资" v-if="formData.dateSelect === 'A' || formData.dateSelect === 'B'">
          {{ formData.proSalary ? formData.proSalary.toFixed(2) : '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="合同开始日期">{{ calculatedContractStart }}</el-descriptions-item>
        <el-descriptions-item label="合同结束日期">{{ formData.contractEndTime || '-' }}</el-descriptions-item>
        <el-descriptions-item label="工资报酬" :span="2">
          <span v-if="formData.salarySelect === 'A'">
            A、乙方的工资报酬按照甲方依法制定的规章制度中的内部工资分配办法确定,根据乙方的工作岗位确定其每月工资。
          </span>
          <span v-else-if="formData.salarySelect === 'B'">
            B、甲方对乙方实行基本工资和绩效工资相结合的内部工资分配办法,乙方的收入包括基本工资、误餐、交通、生活住宿等各项补助,如有变动根据内部工资分配办法调整其工资;绩效工资根据乙方的工作业绩、劳动成果和实际贡献按照内部分配办法考核确定。
          </span>
          <span v-else-if="formData.salarySelect === 'C'">
            C、甲方实行计件工资制,以甲方接到订单及公司生产计划,按照定额和计件单价,根据乙方完成的业绩,按时足额支付乙方的工资报酬。
          </span>
          <span v-else>-</span>
        </el-descriptions-item>
        <el-descriptions-item label="福利待遇" :span="2">{{ formData.remark || '-' }}</el-descriptions-item>
      </el-descriptions>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
          <el-button @click="closeDia">关闭</el-button>
        </div>
      </template>
    </el-dialog>
@@ -23,38 +63,82 @@
</template>
<script setup>
import {ref} from "vue";
import {staffOnJobInfo} from "@/api/personnelManagement/employeeRecord.js";
const { proxy } = getCurrentInstance()
import {ref, reactive, computed} from "vue";
import dayjs from "dayjs";
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const tableColumn = ref([
  // {
  //   label: "合同年限",
  //   prop: "contractTerm",
  // },
  {
    label: "合同开始日期",
    prop: "contractStartTime",
  },
  {
    label: "合同结束日期",
    prop: "contractEndTime",
  },
]);
const tableData = ref([]);
const tableLoading = ref(false);
const formData = reactive({
  staffNo: "",
  staffName: "",
  sex: "",
  identityCard: "",
  nativePlace: "",
  postJob: "",
  adress: "",
  firstStudy: "",
  profession: "",
  age: 0,
  phone: "",
  emergencyContact: "",
  emergencyContactPhone: "",
  dateSelect: "",
  trialStartDate: "",
  trialEndDate: "",
  proSalary: null,
  signDate: "",
  salarySelect: "",
  contractStartTime: "",
  contractEndTime: "",
  contractTerm: null,
  remark: "",
});
const formattedContractTerm = computed(() => {
  const value = formData.contractTerm;
  if (value === null || value === undefined || value === "") {
    return "-";
  }
  const numberValue = Number(value);
  if (!isNaN(numberValue)) {
    return `${numberValue}å¹´`;
  }
  return value;
});
const calculatedContractStart = computed(() => {
  const endDate = formData.contractEndTime;
  const termValue = formData.contractTerm;
  const numberValue = Number(termValue);
  if (!endDate || isNaN(numberValue)) {
    return formData.contractStartTime || "-";
  }
  const start = dayjs(endDate).subtract(numberValue, "year");
  if (!start.isValid()) {
    return formData.contractStartTime || "-";
  }
  return start.format("YYYY-MM-DD");
});
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  if (operationType.value === 'edit') {
    staffOnJobInfo({staffNo: row.staffNo}).then(res => {
      tableData.value = res.data
    })
  // é‡ç½®è¡¨å•数据
  Object.keys(formData).forEach(key => {
    if (key === 'age') {
      formData[key] = 0;
    } else if (["proSalary", "contractTerm"].includes(key)) {
      formData[key] = null;
    } else {
      formData[key] = "";
    }
  });
  if (operationType.value === 'edit' && row) {
    // ç›´æŽ¥ä½¿ç”¨ row æ•°æ®èµ‹å€¼
    Object.assign(formData, row);
  }
}
@@ -69,5 +153,25 @@
</script>
<style scoped>
.detail-descriptions {
  margin-bottom: 16px;
  border-radius: 6px;
  overflow: hidden;
}
.detail-descriptions :deep(.el-descriptions__cell) {
  padding: 12px 16px !important;
}
.detail-descriptions :deep(.el-descriptions__label) {
  width: 140px;
  color: #606266;
  background-color: #f7f9fc;
  font-weight: 500;
}
.detail-descriptions :deep(.el-descriptions__content) {
  color: #303133;
  line-height: 20px;
}
</style>
src/views/personnelManagement/onboarding/components/formDia.vue
@@ -83,11 +83,11 @@
              <el-input v-model="form.emergencyContactPhone" placeholder="请输入" clearable/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="合同年限:" prop="contractTerm">
              <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>
            </el-form-item>
          </el-col>
<!--          <el-col :span="12">-->
<!--            <el-form-item label="合同年限:" prop="contractTermcontractTerm">-->
<!--              <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>-->
<!--            </el-form-item>-->
<!--          </el-col>-->
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
@@ -100,7 +100,6 @@
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
                                    @change="calculateContractTerm"
              />
            </el-form-item>
          </el-col>
@@ -114,7 +113,6 @@
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
                                    @change="calculateContractTerm"
              />
            </el-form-item>
          </el-col>
@@ -181,15 +179,14 @@
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
    form.value.id = ''
  if (operationType.value === 'edit') {
    getStaffJoinInfo(row.id).then(res => {
      form.value = {...res.data}
      // ç¼–辑时也计算一次合同年限
      calculateContractTerm();
      // calculateContractTerm();
    })
  } else {
        form.value.id = ''
    }
  }
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
src/views/personnelManagement/onboarding/components/formDiaXJHT.vue
@@ -59,6 +59,11 @@
          </el-col>
        </el-row>
        <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="身份证号:" prop="identityCard">
                            <el-input v-model="form.identityCard" placeholder="请输入身份证号码" clearable maxlength="18" />
                        </el-form-item>
                    </el-col>
          <el-col :span="12">
            <el-form-item label="年龄:" prop="age">
              <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/>
@@ -84,9 +89,9 @@
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="合同签订日期:" prop="trialStartDate">
            <el-form-item label="合同签订日期:" prop="signDate">
              <el-date-picker
                  v-model="form.trialStartDate"
                  v-model="form.signDate"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
@@ -116,9 +121,9 @@
        </el-row>
        <el-row :gutter="30" v-if="showProbationDates">
          <el-col :span="12">
            <el-form-item label="试用期开始日期:" prop="signDate">
            <el-form-item label="试用期开始日期:" prop="trialStartDate">
              <el-date-picker
                  v-model="form.signDate"
                  v-model="form.trialStartDate"
                  type="date"
                  placeholder="请选择日期"
                  value-format="YYYY-MM-DD"
@@ -142,13 +147,13 @@
            </el-form-item>
          </el-col>
        </el-row>
<!--        <el-row :gutter="30">-->
<!--          <el-col :span="12">-->
<!--            <el-form-item label="合同年限:" prop="contractTerm">-->
<!--              <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>-->
<!--            </el-form-item>-->
<!--          </el-col>-->
<!--        </el-row>-->
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="合同年限:" prop="contractTerm">
              <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="合同开始日期:" prop="contractStartTime">
@@ -160,6 +165,7 @@
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
                                    @change="calculateContractTerm"
              />
            </el-form-item>
          </el-col>
@@ -173,6 +179,7 @@
                  format="YYYY-MM-DD"
                  clearable
                  style="width: 100%"
                                    @change="calculateContractTerm"
              />
            </el-form-item>
          </el-col>
@@ -234,6 +241,7 @@
    staffNo: "",
    staffName: "",
    sex: "",
    identityCard: "",
    nativePlace: "",
    postJob: "",
    adress: "",
@@ -244,20 +252,22 @@
    emergencyContact: "",
    emergencyContactPhone: "",
    dateSelect: "",
    signDate: "",
        trialStartDate: "",
    trialEndDate: "",
    proSalary: null,
    trialStartDate: "",
    signDate: "",
    salarySelect: "",
    // contractTerm: 0,
    contractTerm: 0,
    contractStartTime: "",
    contractEndTime: "",
    staffState: "",
        remark: "无",
  },
  rules: {
    staffNo: [{ required: true, message: "请输入", trigger: "blur" },],
    staffName: [{ required: true, message: "请输入", trigger: "blur" }],
    sex: [{ required: true, message: "请输入", trigger: "blur" }],
    identityCard: [{ required: true, message: "请输入身份证号码", trigger: "blur" }],
    nativePlace: [{ required: true, message: "请输入", trigger: "blur" }],
    postJob: [{ required: true, message: "请输入", trigger: "blur" }],
    adress: [{ required: true, message: "请输入", trigger: "blur" }],
@@ -268,13 +278,14 @@
    emergencyContact: [{ required: true, message: "请输入", trigger: "blur" }],
        remark: [{ required: false, message: "请输入", trigger: "blur" }],
    dateSelect: [{ required: true, message: "请选择劳动合同期限", trigger: "change" }],
    signDate: [{ required: true, message: "请选择", trigger: "change" }],
        trialStartDate: [{ required: true, message: "请选择", trigger: "change" }],
    trialEndDate: [{ required: true, message: "请选择", trigger: "change" }],
    trialStartDate: [{ required: true, message: "请选择", trigger: "change" }],
    signDate: [{ required: true, message: "请选择", trigger: "change" }],
    salarySelect: [{ required: true, message: "请选择工资报酬方式", trigger: "change" }],
    // contractTerm: [{ required: true, message: "请输入", trigger: "blur" }],
    contractTerm: [{ required: true, message: "请输入", trigger: "blur" }],
    contractStartTime: [{ required: true, message: "请输入", trigger: "blur" }],
    contractEndTime: [{ required: true, message: "请输入", trigger: "blur" }],
        proSalary: [{ required: true, message: "请输入", trigger: "blur" }],
  },
});
const { form, rules } = toRefs(data);
@@ -298,11 +309,12 @@
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
    form.value.id = ''
  if (operationType.value === 'edit') {
    getStaffJoinInfo(row.id).then(res => {
      form.value = {...res.data}
      // ç¼–辑时也计算一次合同年限
      // calculateContractTerm();
      calculateContractTerm();
    })
  }
}
@@ -326,32 +338,32 @@
  })
}
// è®¡ç®—合同年限
// const calculateContractTerm = () => {
//   if (form.value.contractStartTime && form.value.contractEndTime) {
//     const startDate = new Date(form.value.contractStartTime);
//     const endDate = new Date(form.value.contractEndTime);
//
//     if (endDate > startDate) {
//       // è®¡ç®—年份差
//       const yearDiff = endDate.getFullYear() - startDate.getFullYear();
//       const monthDiff = endDate.getMonth() - startDate.getMonth();
//       const dayDiff = endDate.getDate() - startDate.getDate();
//
//       let years = yearDiff;
//
//       // å¦‚果结束日期的月日小于开始日期的月日,则减去1å¹´
//       if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
//         years = yearDiff - 1;
//       }
//
//       form.value.contractTerm = Math.max(0, years);
//     } else {
//       form.value.contractTerm = 0;
//     }
//   } else {
//     form.value.contractTerm = 0;
//   }
// };
const calculateContractTerm = () => {
  if (form.value.contractStartTime && form.value.contractEndTime) {
    const startDate = new Date(form.value.contractStartTime);
    const endDate = new Date(form.value.contractEndTime);
    if (endDate > startDate) {
      // è®¡ç®—年份差
      const yearDiff = endDate.getFullYear() - startDate.getFullYear();
      const monthDiff = endDate.getMonth() - startDate.getMonth();
      const dayDiff = endDate.getDate() - startDate.getDate();
      let years = yearDiff;
      // å¦‚果结束日期的月日小于开始日期的月日,则减去1å¹´
      if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
        years = yearDiff - 1;
      }
      form.value.contractTerm = Math.max(0, years);
    } else {
      form.value.contractTerm = 0;
    }
  } else {
    form.value.contractTerm = 0;
  }
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
src/views/personnelManagement/onboarding/index.vue
@@ -57,8 +57,8 @@
<script setup>
import { Search } from "@element-plus/icons-vue";
import {onMounted, ref} from "vue";
import FormDia from "@/views/personnelManagement/onboarding/components/formDia.vue";
// import FormDia from "@/views/personnelManagement/onboarding/components/formDiaXJHT.vue"; // æ–°ç–†é£Ÿå“å…¬å¸ç”¨çš„表单
// import FormDia from "@/views/personnelManagement/onboarding/components/formDia.vue";
import FormDia from "@/views/personnelManagement/onboarding/components/formDiaXJHT.vue"; // æ–°ç–†é£Ÿå“å…¬å¸ç”¨çš„表单
import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js";
import {ElMessageBox} from "element-plus";
import dayjs from "dayjs";
src/views/personnelManagement/payrollManagement/components/formDia.vue
@@ -27,128 +27,15 @@
                            <el-select v-model="form.staffId" placeholder="请选择人员" style="width: 100%" @change="handleSelect" :disabled="operationType === 'edit'">
                                <el-option
                                    v-for="item in personList"
                                    :key="item.id"
                                    :label="item.staffName"
                                    :value="item.id"
                                    :key="item.userId"
                                    :label="item.nickName"
                                    :value="item.userId"
                                />
                            </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="应出勤天数:" prop="shouldAttendedNum">
                            <el-input v-model="form.shouldAttendedNum" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="实际出勤天数:" prop="actualAttendedNum">
              <el-input v-model="form.actualAttendedNum" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="基本工资:" prop="basicSalary">
              <el-input v-model="form.basicSalary" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="岗位工资:" prop="postSalary">
              <el-input v-model="form.postSalary" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="入离职缺勤扣款:" prop="deductionAbsenteeism">
              <el-input v-model="form.deductionAbsenteeism" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="病假扣款:" prop="sickLeaveDeductions">
              <el-input v-model="form.sickLeaveDeductions" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="事假扣款:" prop="deductionPersonalLeave">
              <el-input v-model="form.deductionPersonalLeave" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="忘记打卡扣款:" prop="forgetClockDeduct">
              <el-input v-model="form.forgetClockDeduct" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="绩效得分:" prop="performanceScore">
              <el-input v-model="form.performanceScore" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="绩效工资:" prop="performancePay">
              <el-input v-model="form.performancePay" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="应发合计:" prop="payableWages">
              <el-input v-model="form.payableWages" placeholder="请输入" clearable type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="社保个人:" prop="socialSecurityIndividuals">
              <el-input v-model="form.socialSecurityIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="社保公司:" prop="socialSecurityCompanies">
                            <el-input v-model="form.socialSecurityCompanies" :precision="0" :step="1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="社保合计:" prop="socialSecurityTotal">
                            <el-input v-model="form.socialSecurityTotal" :precision="0" :step="1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="公积金个人:" prop="providentFundIndividuals">
                            <el-input v-model="form.providentFundIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="公积金公司:" prop="providentFundCompany">
                            <el-input v-model="form.providentFundCompany" :precision="0" :step="1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="公积金合计:" prop="providentFundTotal">
                            <el-input v-model="form.providentFundTotal" :precision="0" :step="1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="应税工资:" prop="taxableWaget">
                            <el-input v-model="form.taxableWaget" :precision="0" :step="1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="个人所得税:" prop="personalIncomeTax">
                            <el-input v-model="form.personalIncomeTax" :step="0.1" style="width: 100%" type="number"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="实发工资:" prop="actualWages">
                            <el-input v-model="form.actualWages" style="width: 100%" type="number"/>
@@ -170,6 +57,7 @@
import {ref} from "vue";
import {getStaffJoinInfo, getStaffOnJob, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js";
import {compensationAdd, compensationUpdate} from "@/api/personnelManagement/payrollManagement.js";
import {listUser} from "@/api/system/user.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
@@ -180,50 +68,11 @@
        payDate: "",
    staffId: "",
        name: "",
        shouldAttendedNum: "",
        actualAttendedNum: "",
        basicSalary: "",
        postSalary: "",
        deductionAbsenteeism: "",
        sickLeaveDeductions: "",
        deductionPersonalLeave: "",
        forgetClockDeduct: "",
        performanceScore: "",
        performancePay: "",
        payableWages: "",
        socialSecurityIndividuals: "",
        socialSecurityCompanies: "",
        socialSecurityTotal: "",
        providentFundIndividuals: "",
        providentFundCompany: "",
        providentFundTotal: "",
        taxableWaget: "",
        personalIncomeTax: "",
        actualWages: "",
  },
  rules: {
        payDate: [{ required: true, message: "请选择", trigger: "change" },],
        staffId: [{ required: true, message: "请选择", trigger: "change" },],
    staffName: [{ required: true, message: "请输入", trigger: "blur" }],
        shouldAttendedNum: [{ required: true, message: "请输入", trigger: "blur" }],
        actualAttendedNum: [{ required: true, message: "请输入", trigger: "blur" }],
        basicSalary: [{ required: true, message: "请输入", trigger: "blur" }],
        postSalary: [{ required: true, message: "请输入", trigger: "blur" }],
        deductionAbsenteeism: [{ required: true, message: "请输入", trigger: "blur" }],
        sickLeaveDeductions: [{ required: true, message: "请输入", trigger: "blur" }],
        deductionPersonalLeave: [{ required: true, message: "请输入", trigger: "blur" }],
        forgetClockDeduct: [{ required: true, message: "请输入", trigger: "blur" }],
        performanceScore: [{ required: true, message: "请输入", trigger: "blur" }],
        performancePay: [{ required: true, message: "请输入", trigger: "blur" }],
        payableWages: [{ required: true, message: "请输入", trigger: "blur" }],
        socialSecurityIndividuals: [{ required: true, message: "请输入", trigger: "blur" }],
        socialSecurityCompanies: [{ required: true, message: "请输入", trigger: "blur" }],
        socialSecurityTotal: [{ required: true, message: "请输入", trigger: "blur" }],
        providentFundIndividuals: [{ required: true, message: "请输入", trigger: "blur" }],
        providentFundCompany: [{ required: true, message: "请输入", trigger: "blur" }],
        providentFundTotal: [{ required: true, message: "请输入", trigger: "blur" }],
        taxableWaget: [{ required: true, message: "请输入", trigger: "blur" }],
        personalIncomeTax: [{ required: true, message: "请输入", trigger: "blur" }],
        actualWages: [{ required: true, message: "请输入", trigger: "blur" }],
  },
});
@@ -234,8 +83,8 @@
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
    getStaffOnJob().then(res => {
        personList.value = res.data
    listUser().then(res => {
        personList.value = res.rows
    })
    form.value = {}
  if (operationType.value === 'edit') {
@@ -246,10 +95,9 @@
  }
}
const handleSelect = (value) => {
    console.log('value', value)
    const index = personList.value.findIndex(row => row.id === value)
    const index = personList.value.findIndex(row => row.userId === value)
    if (index > -1) {
        form.value.name = personList.value[index].staffName
        form.value.name = personList.value[index].nickName
    }
}
// æäº¤äº§å“è¡¨å•
src/views/personnelManagement/payrollManagement/index.vue
@@ -27,9 +27,10 @@
                >
            </div>
            <div>
                <el-button @click="handleExport" style="margin-right: 10px">导出</el-button>
                <el-button @click="handleImport">导入</el-button>
                <el-button type="primary" @click="openForm('add')">新增薪资</el-button>
                <el-button type="danger" plain @click="handleDelete">删除</el-button>
                <el-button @click="handleExport">导出</el-button>
            </div>
        </div>
        <div class="table_list">
@@ -46,17 +47,56 @@
            ></PIMTable>
        </div>
        <form-dia ref="formDia" @close="handleQuery"></form-dia>
        <!-- å¯¼å…¥å¼¹çª— -->
        <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body @close="handleUploadClose">
            <el-upload
                ref="uploadRef"
                :limit="1"
                accept=".xlsx, .xls"
                :headers="upload.headers"
                :action="upload.url"
                :disabled="upload.isUploading"
                :on-progress="upload.onProgress"
                :on-success="upload.onSuccess"
                :on-error="upload.onError"
                :on-change="upload.onChange"
                :auto-upload="false"
                drag
            >
                <el-icon class="el-icon--upload"><upload-filled /></el-icon>
                <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                <template #tip>
                    <div class="el-upload__tip text-center">
                        <span>仅允许导入xls、xlsx格式文件。</span>
                        <el-link
                            type="primary"
                            :underline="false"
                            style="font-size: 12px; vertical-align: baseline"
                            @click="importTemplate"
                        >下载模板</el-link>
                    </div>
                </template>
            </el-upload>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitFileForm">ç¡® å®š</el-button>
                    <el-button @click="handleUploadCancel">取 æ¶ˆ</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>
<script setup>
import { Search } from "@element-plus/icons-vue";
import { Search, UploadFilled } from "@element-plus/icons-vue";
import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue";
import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue";
import {staffJoinDel} from "@/api/personnelManagement/onboarding.js";
import {ElMessageBox} from "element-plus";
import dayjs from "dayjs";
import {compensationDelete, compensationListPage} from "@/api/personnelManagement/payrollManagement.js";
import { getToken } from "@/utils/auth.js";
const data = reactive({
    searchForm: {
@@ -73,98 +113,6 @@
    {
        label: "姓名",
        prop: "name",
    },
    {
        label: "应出勤天数",
        prop: "shouldAttendedNum",
        width:100
    },
    {
        label: "实际出勤天数",
        prop: "actualAttendedNum",
        width:110
    },
    {
        label: "基本工资",
        prop: "basicSalary",
    },
    {
        label: "岗位工资",
        prop: "postSalary",
        width:100
    },
    {
        label: "入离职缺勤扣款",
        prop: "deductionAbsenteeism",
        width:130
    },
    {
        label: "病假扣款",
        prop: "sickLeaveDeductions",
        width:100
    },
    {
        label: "事假扣款",
        prop: "deductionPersonalLeave",
        width:100
    },
    {
        label: "忘记打卡扣款",
        prop: "forgetClockDeduct",
        width:110
    },
    {
        label: "绩效得分",
        prop: "performanceScore",
        width:150
    },
    {
        label: "绩效工资",
        prop: "performancePay",
        width: 120
    },
    {
        label: "应发合计",
        prop: "payableWages",
        width:150
    },
    {
        label: "社保个人",
        prop: "socialSecurityIndividuals",
    },
    {
        label: "社保公司",
        prop: "socialSecurityCompanies",
        width: 120
    },
    {
        label: "社保合计",
        prop: "socialSecurityTotal",
        width: 120
    },
    {
        label: "公积金个人",
        prop: "providentFundIndividuals",
        width: 120
    },
    {
        label: "公积金公司",
        prop: "providentFundCompany",
        width: 120
    },
    {
        label: "公积金合计",
        prop: "providentFundTotal",
        width: 120
    },
    {
        label: "应税工资",
        prop: "taxableWaget",
    },
    {
        label: "个人所得税",
        prop: "personalIncomeTax",
        width: 120
    },
    {
        label: "实发工资",
@@ -197,6 +145,56 @@
});
const formDia = ref()
const { proxy } = getCurrentInstance()
// å¯¼å…¥åŠŸèƒ½é…ç½®
const upload = reactive({
  // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚(薪资导入)
  open: false,
  // å¼¹å‡ºå±‚标题(薪资导入)
  title: "",
  // æ˜¯å¦ç¦ç”¨ä¸Šä¼ 
  isUploading: false,
  // è®¾ç½®ä¸Šä¼ çš„请求头部
  headers: { Authorization: "Bearer " + getToken() },
  // ä¸Šä¼ çš„地址
  url: import.meta.env.VITE_APP_BASE_API + "/compensationPerformance/importData",
  // æ–‡ä»¶ä¸Šä¼ å‰çš„回调
  beforeUpload: (file) => {
    // å¯ä»¥åœ¨æ­¤å¤„做文件类型或大小校验
    const isValid = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
    if (!isValid) {
      proxy.$modal.msgError("只能上传 Excel æ–‡ä»¶");
    }
    return isValid;
  },
  // æ–‡ä»¶çŠ¶æ€æ”¹å˜æ—¶çš„å›žè°ƒ
  onChange: (file, fileList) => {
    console.log('文件状态改变', file, fileList);
  },
  // æ–‡ä»¶ä¸Šä¼ æˆåŠŸæ—¶çš„å›žè°ƒ
  onSuccess: (response, file, fileList) => {
    upload.isUploading = false;
    if(response.code === 200){
      proxy.$modal.msgSuccess("文件上传成功");
      handleUploadClose();
      getList();
    }else if(response.code === 500){
      proxy.$modal.msgError(response.msg);
    }else{
      proxy.$modal.msgWarning(response.msg);
    }
  },
  // æ–‡ä»¶ä¸Šä¼ å¤±è´¥æ—¶çš„回调
  onError: (error, file, fileList) => {
    console.error('上传失败', error, file, fileList);
    upload.isUploading = false;
    proxy.$modal.msgError("文件上传失败");
  },
  // æ–‡ä»¶ä¸Šä¼ è¿›åº¦å›žè°ƒ
  onProgress: (event, file, fileList) => {
    console.log('上传中...', event.percent);
  }
});
const handleDateChange = (value,type) => {
    searchForm.value.entryDateEnd = null
@@ -299,6 +297,39 @@
        });
};
/** å¯¼å…¥æŒ‰é’®æ“ä½œ */
function handleImport() {
  upload.title = "薪资导入";
  upload.open = true;
}
/** æäº¤ä¸Šä¼ æ–‡ä»¶ */
function submitFileForm() {
  upload.isUploading = true;
  proxy.$refs["uploadRef"].submit();
}
/** ä¸‹è½½æ¨¡æ¿ */
function importTemplate() {
  proxy.download("/compensationPerformance/exportTemplate", {}, "薪资导入模板.xlsx");
}
// å¤„理上传弹框取消
function handleUploadCancel() {
  upload.open = false;
  handleUploadClose();
}
// å¤„理上传弹框关闭
function handleUploadClose() {
  upload.open = false;
  upload.isUploading = false;
  // æ¸…空上传文件缓存
  if (proxy.$refs.uploadRef) {
    proxy.$refs.uploadRef.clearFiles();
  }
}
onMounted(() => {
    getList();
});
src/views/personnelManagement/scheduling/index.vue
@@ -11,34 +11,14 @@
              style="width: 150px"
          />
        </el-form-item>
        <el-form-item label="班次类型:">
          <el-select v-model="filterForm.shiftType" placeholder="请选择班次" clearable style="width: 120px">
            <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/>
          </el-select>
        </el-form-item>
        <el-form-item label="日期范围:">
          <el-date-picker
              v-model="filterForm.dateRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              style="width: 250px"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleFilter">
            <el-icon><Search/></el-icon>
            ç­›é€‰
            æœç´¢
          </el-button>
          <el-button @click="resetFilter">
            <el-icon><Refresh/></el-icon>
            é‡ç½®
          </el-button>
          <el-button @click="handleExport">
            <el-icon><Download/></el-icon>
            å¯¼å‡º
          </el-button>
          <el-button type="primary" @click="openScheduleDialog('add')">
@@ -61,48 +41,53 @@
          @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55"/>
        <el-table-column prop="staffName" label="员工姓名" width="120"/>
        <el-table-column prop="staffNo" label="员工工号" width="100"/>
        <el-table-column prop="department" label="部门" width="120">
        <el-table-column prop="staffName" label="员工姓名"/>
        <!-- <el-table-column prop="staffNo" label="员工工号" width="100"/> -->
        <!-- <el-table-column prop="department" label="部门" width="120">
          <template #default="scope">
              {{ (department_type.find(i => i.value === String(scope.row.department)) || {}).label }}
          </template>
        </el-table-column>
        <el-table-column prop="shiftType" label="班次类型" width="100">
        </el-table-column> -->
        <el-table-column prop="shiftType" label="班次类型" width="120">
          <template #default="scope">
            <el-tag :type="getShiftTagType(scope.row.shiftType)">
              {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label }}
              {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label || '未知' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="workDate" label="工作日期" width="120"/>
        <el-table-column prop="startTime" label="开始时间" width="100"/>
        <el-table-column prop="endTime" label="结束时间" width="100"/>
        <el-table-column prop="workHours" label="工作时长" width="100">
        <!-- <el-table-column prop="workDate" label="工作日期" width="120"/> -->
        <el-table-column prop="workStartTime" label="开始时间"/>
        <el-table-column prop="workEndTime" label="结束时间"/>
        <el-table-column prop="lunchTime" label="午休时间(h)">
          <template #default="scope">
            {{ scope.row.lunchTime }}小时
          </template>
        </el-table-column>
        <!-- <el-table-column prop="workHours" label="工作时长" width="100">
          <template #default="scope">
            {{ scope.row.workHours }}小时
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="100">
        </el-table-column> -->
        <!-- <el-table-column prop="status" label="状态" width="100">
          <template #default="scope">
            <el-tag :type="getStatusTagType(scope.row.status)">
              {{ (schedule_status.find(i => i.value === String(scope.row.status)) || {}).label }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="remark" label="备注" min-width="150"/>
        <el-table-column label="操作" width="200" fixed="right">
        </el-table-column> -->
        <!-- <el-table-column prop="remark" label="备注" min-width="150"/> -->
        <el-table-column label="操作" width="200" fixed="right" align="center">
          <template #default="scope">
            <el-button
                type="primary"
                size="small"
                            link
                            type="primary"
                @click="openScheduleDialog('edit', scope.row)"
            >
              ç¼–辑
            </el-button>
            <el-button
                type="danger"
                size="small"
                            link
                            type="danger"
                @click="handleDelete(scope.row)"
            >
              åˆ é™¤
@@ -144,22 +129,36 @@
          label-width="120px"
      >
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="员工姓名:" prop="staffId">
              <el-select v-model="scheduleForm.staffId" placeholder="请输入员工姓名" style="width: 100%"
          <el-col :span="24">
            <el-form-item label="员工姓名:" prop="staffIds">
          <el-select v-model="scheduleForm.staffIds" placeholder="请选择员工姓名" style="width: 100%"
                         multiple filterable collapse-tags-tooltip
                         @change="handleSelectStaff">
                <el-option v-for="item in personList" :label="item.staffName" :value="item.id" :key="item.id"/>
              </el-select>
            </el-form-item>
            <el-option v-for="item in personList" :label="item.nickName" :value="item.userId" :key="item.userId"/>
          </el-select>
        </el-form-item>
          </el-col>
        </el-row>
        <!-- <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="员工工号:" prop="staffNo">
              <el-input :disabled="true" v-model="scheduleForm.staffNo" placeholder=""/>
            </el-form-item>
          </el-col>
        </el-row>
        </el-row> -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="班次类型:" prop="shiftType">
              <el-select v-model="scheduleForm.shiftType" placeholder="请选择班次类型" style="width: 100%">
                <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <!-- <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="部门:" prop="department">
              <el-select v-model="scheduleForm.department" placeholder="请选择部门" style="width: 100%">
@@ -174,9 +173,9 @@
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        </el-row> -->
        <el-row :gutter="20">
        <!-- <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="工作日期:" prop="workDate">
              <el-date-picker
@@ -196,34 +195,49 @@
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        </el-row> -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="开始时间:" prop="startTime">
            <el-form-item label="开始时间:" prop="workStartTime">
              <el-time-picker
                  v-model="scheduleForm.startTime"
                  v-model="scheduleForm.workStartTime"
                  placeholder="选择开始时间"
                  style="width: 100%"
                  format="HH:mm"
                  value-format="HH:mm"
                  value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="结束时间:" prop="endTime">
            <el-form-item label="结束时间:" prop="workEndTime">
              <el-time-picker
                  v-model="scheduleForm.endTime"
                  v-model="scheduleForm.workEndTime"
                  placeholder="选择结束时间"
                  style="width: 100%"
                  format="HH:mm"
                  value-format="HH:mm"
                  value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="午休时间(h):" prop="lunchTime">
              <el-input-number
                  v-model="scheduleForm.lunchTime"
                  :min="0"
                  :max="8"
                  :step="0.5"
                  placeholder="请输入午休时间"
                  style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="备注:" prop="remark">
              <el-input
@@ -234,7 +248,7 @@
              />
            </el-form-item>
          </el-col>
        </el-row>
        </el-row> -->
      </el-form>
      <template #footer>
@@ -248,7 +262,7 @@
</template>
<script setup>
import {ref, reactive, computed, onMounted, getCurrentInstance} from 'vue'
import {ref, reactive, computed, onMounted, getCurrentInstance, watch} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {useDict} from "@/utils/dict.js"
import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue'
@@ -256,6 +270,7 @@
import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js";
import dayjs from "dayjs";
import pagination from "@/components/PIMTable/Pagination.vue";
import {listUser} from "@/api/system/user.js";
const { proxy } = getCurrentInstance();
@@ -269,8 +284,6 @@
// ç­›é€‰è¡¨å•
const filterForm = reactive({
  staffName: '',
  shiftType: '',
  dateRange: [],
  current:1,
  size: 10
})
@@ -278,29 +291,31 @@
// æŽ’班表单
const scheduleForm = reactive({
  id: '',
  staffId: '',
  staffNo: '',
  department: '',
  staffIds: [],
  // staffNo: '',
  // department: '',
  shiftType: '',
  workDate: '',
  startTime: '',
  endTime: '',
  // workDate: '',
  workStartTime: '',
  workEndTime: '',
  workHours: 0,
  status: '',
  remark: ''
  lunchTime: 3,
  // workStartTime: '',
  // workEndTime: '',
  // workHours: 0,
  // status: '',
  // remark: ''
})
// è¡¨å•验证规则
const scheduleRules = reactive({
  staffId: [{required: true, message: '请选择员工', trigger: 'change'}],
  department: [{required: true, message: '请选择部门', trigger: 'change'}],
  staffIds: [{required: true, message: '请选择员工', trigger: 'change'}],
  // department: [{required: true, message: '请选择部门', trigger: 'change'}],
  shiftType: [{required: true, message: '请选择班次类型', trigger: 'change'}],
  workDate: [{required: true, message: '请选择工作日期', trigger: 'change'}],
  startTime: [{required: true, message: '请选择开始时间', trigger: 'change'}],
  endTime: [{required: true, message: '请选择结束时间', trigger: 'change'}],
  status: [{required: true, message: '请选择状态', trigger: 'change'}]
  // workDate: [{required: true, message: '请选择工作日期', trigger: 'change'}],
  workStartTime: [{required: true, message: '请选择开始时间', trigger: 'change'}],
  workEndTime: [{required: true, message: '请选择结束时间', trigger: 'change'}],
  lunchTime: [{required: true, message: '请输入午休时间', trigger: 'blur'}],
  // status: [{required: true, message: '请选择状态', trigger: 'change'}]
})
const tableLoading = ref(false)
@@ -317,9 +332,9 @@
 * èŽ·å–å½“å‰åœ¨èŒäººå‘˜åˆ—è¡¨
 */
const getPersonList = () => {
  getStaffOnJob().then(res => {
    personList.value = res.data
  })
    listUser().then(res => {
        personList.value = res.rows
    })
};
const paginationChange = (obj) => {
  filterForm.current = obj.page;
@@ -328,9 +343,9 @@
};
const handleSelectStaff = (val) => {
  let obj = personList.value.find(item => item.id === val)
  scheduleForm.staffNo = obj.staffNo
  // å¤šé€‰å‘˜å·¥ï¼Œä¸å†è‡ªåŠ¨è®¾ç½®å‘˜å·¥å·¥å·
  // let obj = personList.value.find(item => item.id === val)
  // scheduleForm.staffNo = obj.staffNo
}
// èŽ·å–ç­æ¬¡æ ‡ç­¾ç±»åž‹
@@ -349,19 +364,19 @@
const handleFilter = async () => {
  tableLoading.value = true
  let searchForm = {
    ...filterForm,
    ...(filterForm.dateRange.length > 0 && {
      startDate: filterForm.dateRange[0],
      endDate: filterForm.dateRange[1],
    })
    ...filterForm
  }
  let resp = await listPage(searchForm)
  tableCount.value = resp.data.total
  scheduleList.value = resp.data.records.map(it => {
    return {
      ...it,
      'startTime': dayjs(it.workStartTime).format('HH:mm'),
      'endTime': dayjs(it.workEndTime).format('HH:mm'),
      // ä¿å­˜åŽŸå§‹æ—¶é—´æ ¼å¼ç”¨äºŽç¼–è¾‘
      'originalWorkStartTime': it.workStartTime,
      'originalWorkEndTime': it.workEndTime,
      // æ ¼å¼åŒ–时间用于表格显示
      'workStartTime': dayjs(it.workStartTime).format('HH:mm'),
      'workEndTime': dayjs(it.workEndTime).format('HH:mm'),
    }
  })
  tableLoading.value = false
@@ -371,8 +386,6 @@
// é‡ç½®ç­›é€‰
const resetFilter = () => {
  filterForm.staffName = ''
  filterForm.shiftType = ''
  filterForm.dateRange = []
}
// æ‰“开排班对话框
@@ -381,16 +394,29 @@
  scheduleDialog.value = true
  getPersonList()
  if (type === 'edit' && data) {
    // ç¼–辑模式,复制数据
    Object.assign(scheduleForm, {...data})
  } else {
    // æ–°å¢žæ¨¡å¼ï¼Œé‡ç½®è¡¨å•
    Object.keys(scheduleForm).forEach(key => {
      scheduleForm[key] = ''
    // ç¼–辑模式,复制数据,将员工ID字符串转换为数组格式,并处理时间字段
    Object.assign(scheduleForm, {
      ...data,
        lunchTime: Number(data.lunchTime),
      staffIds: data.staffId ? data.staffId.split(',').map(id => parseInt(id)) : [],
      // ä½¿ç”¨åŽŸå§‹æ—¶é—´å­—ç¬¦ä¸²ï¼Œå› ä¸ºè¡¨æ ¼ä¸­æ˜¾ç¤ºçš„æ˜¯æ ¼å¼åŒ–åŽçš„HH:mm
      workStartTime: data.originalWorkStartTime || '',
      workEndTime: data.originalWorkEndTime || ''
    })
    // scheduleForm.status = '已安排'
    scheduleForm.workDate = new Date().toISOString().split('T')[0]
  }
  } else {
      // æ–°å¢žæ¨¡å¼ï¼Œé‡ç½®è¡¨å•
      Object.keys(scheduleForm).forEach(key => {
        if (key === 'staffIds') {
          scheduleForm[key] = []
        } else if (key === 'lunchTime') {
          scheduleForm[key] = 3
        } else {
          scheduleForm[key] = ''
        }
      })
      // scheduleForm.status = '已安排'
      // scheduleForm.workDate = new Date().toISOString().split('T')[0]
    }
}
// å…³é—­æŽ’班对话框
@@ -401,37 +427,86 @@
// è®¡ç®—工作时长
const calculateWorkHours = () => {
  if (scheduleForm.workDate && scheduleForm.startTime && scheduleForm.endTime) {
    // ä½¿ç”¨ workDate ä¸Ž startTime å’Œ endTime ç»„合
    const startDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.startTime}`)
    const endDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.endTime}`)
  if (!scheduleForm.workStartTime || !scheduleForm.workEndTime) {
    return;
  }
  try {
    // ä½¿ç”¨dayjs正确解析时间
    const startDayjs = dayjs(scheduleForm.workStartTime);
    const endDayjs = dayjs(scheduleForm.workEndTime);
    if (!startDayjs.isValid() || !endDayjs.isValid()) {
      return;
    }
    const startDateTime = startDayjs.toDate();
    const endDateTime = endDayjs.toDate();
    // å¤„理跨天情况(结束时间早于开始时间)
    if (endDateTime < startDateTime) {
      // è·¨å¤©ï¼Œå°†ç»“束日期加一天
      endDateTime.setDate(endDateTime.getDate() + 1)
      endDateTime.setDate(endDateTime.getDate() + 1);
    }
    // è®¡ç®—工作时长(小时)
    const diffMs = endDateTime - startDateTime
    const diffHours = diffMs / (1000 * 60 * 60)
    scheduleForm.workHours = Math.round(diffHours * 100) / 100
    scheduleForm.workStartTime = dayjs(startDateTime).format("YYYY-MM-DD HH:mm:ss")
    scheduleForm.workEndTime = dayjs(endDateTime).format("YYYY-MM-DD HH:mm:ss")
    // è®¡ç®—工作时长(小时)
    const diffMs = endDateTime - startDateTime;
    const diffHours = diffMs / (1000 * 60 * 60);
    scheduleForm.workHours = Math.round(diffHours * 100) / 100;
  } catch (error) {
    console.error('时间计算错误:', error);
  }
}
// ç›‘听时间字段变化,自动计算工作时长
watch(
  () => [scheduleForm.workStartTime, scheduleForm.workEndTime],
  () => {
    calculateWorkHours()
  },
  { deep: true }
)
// æäº¤æŽ’班表单
const submitScheduleForm = async () => {
  const valid = await scheduleFormRef.value.validate()
  if (!valid) return
  calculateWorkHours()
  const newSchedule = {...scheduleForm}
  // ç”±äºŽå‘˜å·¥æ˜¯å¤šé€‰ï¼Œéœ€è¦ä¸ºæ¯ä¸ªé€‰ä¸­çš„员工创建排班记录
  const selectedStaffIds = scheduleForm.staffIds || []
  if (selectedStaffIds.length === 0) {
    ElMessage.warning('请至少选择一个员工')
    return
  }
  try {
    // èŽ·å–é€‰ä¸­çš„å‘˜å·¥å§“ååˆ—è¡¨
    const selectedStaffNames = selectedStaffIds.map(staffId => {
      const staff = personList.value.find(item => item.userId === staffId)
      return staff ? staff.nickName : ''
    }).filter(name => name !== '')
    // å°†å‘˜å·¥å§“名组装成逗号分隔的字符串
    const staffNameString = selectedStaffNames.join(',')
    // åˆ›å»ºæŽ’班记录,将员工姓名保存为字符串格式
    const newSchedule = {
      ...scheduleForm,
      staffName: staffNameString,
      staffId: selectedStaffIds.join(','), // å°†å‘˜å·¥ID也保存为逗号分隔的字符串
      // è®¾ç½®å…¶ä»–必要字段的默认值
      staffNo: '', // å¯ä»¥æ ¹æ®éœ€è¦ä»ŽpersonList中获取
      department: '',
      shiftType: scheduleForm.shiftType,
      workDate: '',
      status: '',
      remark: ''
    }
    await save(newSchedule)
    ElMessage.success('保存排班成功')
    ElMessage.success(`成功为 ${selectedStaffNames.length} ä¸ªå‘˜å·¥åˆ›å»ºæŽ’班`)
    handleFilter()
    closeScheduleDialog()
@@ -491,11 +566,7 @@
// å¯¼å‡º
const handleExport = () => {
  let searchForm = {
    ...filterForm,
    ...(filterForm.dateRange.length > 0 && {
      startDate: filterForm.dateRange[0],
      endDate: filterForm.dateRange[1],
    })
    ...filterForm
  }
  proxy.download('/staff/staffScheduling/export', {}, '人员排班.xlsx')
}
src/views/procurementManagement/invoiceEntry/components/Modal.vue
@@ -1,160 +1,202 @@
<template>
  <el-dialog :title="modalOptions.title" v-model="visible" width="70%">
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="120px"
      label-position="top"
    >
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="采购合同号:" prop="purchaseLedgerNo">
            <el-input v-model="form.purchaseLedgerNo" disabled />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="销售合同号:" prop="salesContractNo">
            <el-input
              v-model="form.salesContractNo"
              placeholder="自动填充"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="供应商名称:" prop="supplierName">
            <el-input
              v-model="form.supplierName"
              placeholder="自动填充"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="项目名称:" prop="projectName">
            <el-input
              v-model="form.projectName"
              placeholder="自动填充"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="发票号:" prop="invoiceNumber">
            <el-input
              v-model="form.invoiceNumber"
              placeholder="请输入"
              clearable
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="发票金额(元):" prop="invoiceAmount">
            <el-input-number :step="0.01" :min="0" style="width: 100%"
              v-model="form.invoiceAmount"
              placeholder="自动填充"
              clearable
              :disabled="true"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="录入人:" prop="issUer">
            <el-input
              v-model="form.issUer"
              placeholder="请输入"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="开票日期:" prop="entryDate">
            <el-date-picker
              style="width: 100%"
              v-model="form.entryDate"
              type="date"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              clearable
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="上传附件">
            <FileUpload
              :showTip="false"
              accept="*"
              :autoUpload="true"
              :action="action"
              :headers="{
    <el-dialog :title="modalOptions.title" v-model="visible" width="70%">
        <el-form
            ref="formRef"
            :model="form"
            :rules="rules"
            label-width="120px"
            label-position="top"
        >
            <el-row :gutter="30">
                <el-col :span="12">
                    <el-form-item label="采购合同号:" prop="purchaseLedgerNo">
                        <el-input v-model="form.purchaseLedgerNo" disabled placeholder="多合同批量处理(具体合同号见产品列表)" />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="销售合同号:" prop="salesContractNo">
                        <el-input
                            v-model="form.salesContractNo"
                            placeholder="自动填充"
                            clearable
                            disabled
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="供应商名称:" prop="supplierName">
                        <el-input
                            v-model="form.supplierName"
                            placeholder="自动填充"
                            clearable
                            disabled
                        />
                    </el-form-item>
                </el-col>
<!--                <el-col :span="12">-->
<!--                    <el-form-item label="项目名称:" prop="projectName">-->
<!--                        <el-input-->
<!--                            v-model="form.projectName"-->
<!--                            placeholder="自动填充"-->
<!--                            clearable-->
<!--                            disabled-->
<!--                        />-->
<!--                    </el-form-item>-->
<!--                </el-col>-->
                <el-col :span="12">
                    <el-form-item label="发票号:" prop="invoiceNumber">
                        <el-input
                            v-model="form.invoiceNumber"
                            placeholder="请输入"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="发票金额(元):" prop="invoiceAmount">
                        <el-input-number :step="0.01" :min="0" style="width: 100%"
                                                         v-model="form.invoiceAmount"
                                                         placeholder="请输入发票金额"
                                                         clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="录入人:" prop="issUer">
                        <el-input
                            v-model="form.issUer"
                            placeholder="请输入"
                            clearable
                            disabled
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="开票日期:" prop="entryDate">
                        <el-date-picker
                            style="width: 100%"
                            v-model="form.entryDate"
                            type="date"
                            value-format="YYYY-MM-DD"
                            format="YYYY-MM-DD"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="录入日期:" prop="enterDate">
                        <el-date-picker
                            style="width: 100%"
                            v-model="form.enterDate"
                            type="date"
                            value-format="YYYY-MM-DD"
                            format="YYYY-MM-DD"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="上传附件">
                        <FileUpload
                            :showTip="false"
                            accept="*"
                            :autoUpload="true"
                            :action="action"
                            :headers="{
                Authorization: 'Bearer ' + getToken(),
              }"
              :limit="10"
              @success="uploadSuccess"
              @remove="removeFile"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="录入日期:" prop="enterDate">
            <el-date-picker
              style="width: 100%"
              v-model="form.enterDate"
              type="date"
              value-format="YYYY-MM-DD"
              format="YYYY-MM-DD"
              clearable
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="产品信息:"> </el-form-item>
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="form.productData"
                :summaryMethod="summarizeChildrenTable"
                :isShowSummary="true"
        height="auto"
      >
        <template #ticketsNumRef="{ row }">
          <el-input-number
            v-model="row.ticketsNum"
            placeholder="请输入"
            :min="0"
            :step="0.1"
                        :precision="2"
            clearable
            style="width: 100%"
            @change="invoiceNumBlur(row)"
          />
        </template>
        <template #ticketsAmountRef="{ row }">
          <el-input-number
            v-model="row.ticketsAmount"
            placeholder="请输入"
            :min="0"
                        :precision="2"
            :step="0.1"
            clearable
            style="width: 100%"
            @change="invoiceAmountBlur(row)"
          />
        </template>
      </PIMTable>
    </el-form>
    <template #footer>
                            :limit="10"
                            @success="uploadSuccess"
                            @remove="removeFile"
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-form-item label="产品信息:"> </el-form-item>
            <el-table
                :data="form.productData"
                border
                show-summary
                :summary-method="summarizeChildrenTable"
            >
                <el-table-column align="center" label="序号" type="index" width="60" />
                <el-table-column label="所属合同" prop="purchaseLedgerNo" width="200">
                    <template #default="{ row }">
                        <el-tag type="primary">{{ row.purchaseLedgerNo }}</el-tag>
                    </template>
                </el-table-column>
                <el-table-column label="产品大类" prop="productCategory" />
                <el-table-column label="规格型号" prop="specificationModel" width="150" />
                <el-table-column label="单位" prop="unit" width="70" />
                <el-table-column label="数量" prop="quantity" width="70" />
                <el-table-column label="税率(%)" prop="taxRate" width="80" />
                <el-table-column
                    label="含税单价(元)"
                    prop="taxInclusiveUnitPrice"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="含税总价(元)"
                    prop="taxInclusiveTotalPrice"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="不含税总价(元)"
                    prop="taxExclusiveTotalPrice"
                    :formatter="formattedNumber"
                />
                <el-table-column label="本次开票数" prop="ticketsNum" width="180">
                    <template #default="scope">
                        <el-input-number :step="0.1" :min="0" style="width: 100%"
                                                         :precision="2"
                                                         v-model="scope.row.ticketsNum"
                                                         @change="invoiceNumBlur(scope.row)"
                        />
                    </template>
                </el-table-column>
                <el-table-column
                    label="本次开票金额(元)"
                    prop="ticketsAmount"
                    width="180"
                >
                    <template #default="scope">
                        <el-input-number :step="0.01" :min="0" style="width: 100%"
                                                         :precision="2"
                                                         v-model="scope.row.ticketsAmount"
                                                         @change="invoiceAmountBlur(scope.row)"
                        />
                    </template>
                </el-table-column>
                <el-table-column
                    label="未来票数"
                    prop="futureTickets"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="本次来票金额(元)"
                    prop="ticketsAmount"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="未来票数"
                    prop="futureTickets"
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="未来票金额(元)"
                    prop="futureTicketsAmount"
                    :formatter="formattedNumber"
                />
            </el-table>
        </el-form>
        <template #footer>
            <el-button type="primary" :loading="modalLoading" @click="submitForm">
                {{ modalOptions.confirmText }}
                ç¡®è®¤
            </el-button>
      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
    </template>
  </el-dialog>
            <el-button @click="closeModal">取消</el-button>
        </template>
    </el-dialog>
</template>
<script setup>
@@ -164,9 +206,9 @@
import useFormData from "@/hooks/useFormData";
import FileUpload from "@/components/Upload/FileUpload.vue";
import {
  getPurchaseNoById,
  getInfo,
  addOrUpdateRegistration,
    getPurchaseNoById,
    getInfo,
    addOrUpdateRegistration,
} from "@/api/procurementManagement/invoiceEntry.js";
import { getPurchaseById } from "@/api/procurementManagement/procurementLedger.js";
import { getToken } from "@/utils/auth";
@@ -174,7 +216,7 @@
import dayjs from "dayjs";
defineOptions({
  name: "来票登记模态框",
    name: "来票登记模态框",
});
const userStore = useUserStore();
@@ -182,155 +224,218 @@
const formRef = ref();
const { proxy } = getCurrentInstance();
const { form } = useFormData({
  purchaseLedgerNo: undefined, // é‡‡è´­åˆåŒå·
  salesContractNo: undefined, // é”€å”®åˆåŒå·
  supplierName: undefined, // ä¾›åº”商名称
  projectName: undefined, // é¡¹ç›®åç§°
  invoiceNumber: undefined, // å‘票号
  invoiceAmount: undefined, // å‘票金额(元)
  issUerId: userStore.id, // å½•入人
  issUer: userStore.nickName, // å½•入人
  entryDate: undefined, // å¼€ç¥¨æ—¥æœŸ
  salesContractNoId: undefined, // å¼€ç¥¨æ—¥æœŸ
  enterDate: dayjs().format("YYYY-MM-DD"),
  productData: [], // è¡¨æ ¼
  tempFileIds: [], // æ–‡ä»¶
    purchaseLedgerNo: undefined, // é‡‡è´­åˆåŒå·
    salesContractNo: undefined, // é”€å”®åˆåŒå·
    supplierName: undefined, // ä¾›åº”商名称
    projectName: undefined, // é¡¹ç›®åç§°
    invoiceNumber: undefined, // å‘票号
    invoiceAmount: undefined, // å‘票金额(元)
    issUerId: userStore.id, // å½•入人
    issUer: userStore.nickName, // å½•入人
    entryDate: undefined, // å¼€ç¥¨æ—¥æœŸ
    salesContractNoId: undefined, // å¼€ç¥¨æ—¥æœŸ
    enterDate: dayjs().format("YYYY-MM-DD"),
    productData: [], // è¡¨æ ¼
    tempFileIds: [], // æ–‡ä»¶
});
const selectedContracts = ref([]); // å­˜å‚¨é€‰ä¸­çš„合同数据
const rules = ref({
  invoiceNumber: [
    { required: true, message: "请输入发票号", trigger: "blur" },
    { type: "string" },
  ],
  invoiceAmount: [
    { required: true, message: "请输入发票金额", trigger: "blur" },
  ],
  entryDate: [{ required: true, message: "请选择开票日期", trigger: "change" }],
  enterDate: [{ required: true, message: "请选择录入日期", trigger: "change" }],
    invoiceNumber: [
        { required: true, message: "请输入发票号", trigger: "blur" },
        { type: "string" },
    ],
    invoiceAmount: [
        { required: true, message: "请输入发票金额", trigger: "blur" },
    ],
    entryDate: [{ required: true, message: "请选择开票日期", trigger: "change" }],
    enterDate: [{ required: true, message: "请选择录入日期", trigger: "change" }],
});
const {
  id,
  visible,
  loading: modalLoading,
  openModal,
  modalOptions,
  handleConfirm,
  closeModal,
    id,
    visible,
    loading: modalLoading,
    openModal,
    modalOptions,
    handleConfirm,
    closeModal,
} = useModal({
  title: "来票登记",
    title: "来票登记",
});
const emit = defineEmits(['refreshList']);
const columns = [
  {
    label: "产品大类",
    prop: "productCategory",
    {
        label: "产品大类",
        prop: "productCategory",
        width: 120,
  },
  {
    label: "规格型号",
    prop: "specificationModel",
    },
    {
        label: "规格型号",
        prop: "specificationModel",
        width: 120,
  },
  {
    label: "单位",
    prop: "unit",
    width: 80,
  },
  {
    label: "数量",
    prop: "quantity",
    width: 80,
  },
  {
    label: "税率(%)",
    prop: "taxRate",
    width: 80,
  },
  {
    label: "录入日期",
    prop: "registerDate",
    width: 120,
  },
  {
    label: "含税单价(元)",
    prop: "taxInclusiveUnitPrice",
    width: 150,
    formatData: (val) => {
      return val ? parseFloat(val).toFixed(2) : 0;
    },
  },
  {
    label: "含税总价(元)",
    prop: "taxInclusiveTotalPrice",
    width: 150,
    formatData: (val) => {
      return parseFloat(val).toFixed(2) ?? 0;
    },
  },
  {
    label: "不含税总价(元)",
    prop: "taxExclusiveTotalPrice",
    width: 150,
    formatData: (val) => {
      return parseFloat(val).toFixed(2) ?? 0;
    },
  },
  {
    label: "本次来票数",
    prop: "ticketsNum",
    dataType: "slot",
    slot: "ticketsNumRef",
    width: 180,
    align: "center",
  },
  {
    label: "本次来票金额(元)",
    prop: "ticketsAmount",
    dataType: "slot",
    slot: "ticketsAmountRef",
    width: 180,
    align: "center",
  },
  {
    label: "未来票数",
    prop: "futureTickets",
    },
    {
        label: "单位",
        prop: "unit",
        width: 80,
    },
    {
        label: "数量",
        prop: "quantity",
        width: 80,
    },
    {
        label: "税率(%)",
        prop: "taxRate",
        width: 80,
    },
    {
        label: "录入日期",
        prop: "registerDate",
        width: 120,
    },
    {
        label: "含税单价(元)",
        prop: "taxInclusiveUnitPrice",
        width: 150,
        formatData: (val) => {
            return val ? parseFloat(val).toFixed(2) : 0;
        },
    },
    {
        label: "含税总价(元)",
        prop: "taxInclusiveTotalPrice",
        width: 150,
        formatData: (val) => {
            return parseFloat(val).toFixed(2) ?? 0;
        },
    },
    {
        label: "不含税总价(元)",
        prop: "taxExclusiveTotalPrice",
        width: 150,
        formatData: (val) => {
            return parseFloat(val).toFixed(2) ?? 0;
        },
    },
    {
        label: "本次来票数",
        prop: "ticketsNum",
        dataType: "slot",
        slot: "ticketsNumRef",
        width: 180,
        align: "center",
    },
    {
        label: "本次来票金额(元)",
        prop: "ticketsAmount",
        dataType: "slot",
        slot: "ticketsAmountRef",
        width: 180,
        align: "center",
    },
    {
        label: "未来票数",
        prop: "futureTickets",
        width: 100,
  },
  {
    label: "未来票金额(元)",
    prop: "futureTicketsAmount",
    },
    {
        label: "未来票金额(元)",
        prop: "futureTicketsAmount",
        width: 200,
  },
    },
];
const getTableData = async (type, id) => {
  if (type == "add") {
    const { data } = await getPurchaseNoById({ id });
    form.purchaseLedgerNo = data.purchaseContractNumber;
    form.invoiceAmount = data.invoiceAmount;
    form.invoiceNumber = data.invoiceNumber;
    form.entryDate = data.entryDate;
    form.salesContractNoId = data.salesContractNoId;
    const { data: infoData } = await getInfo({ id });
    form.salesContractNo = infoData.salesContractNo;
    form.projectName = infoData.projectName;
    form.supplierName = infoData.supplierName;
    form.productData = infoData.productData;
  } else if (type == "edit") {
    const data = await getPurchaseById({ id, type: 2 });
    form.purchaseLedgerNo = data.purchaseContractNumber;
    form.invoiceAmount = data.invoiceAmount;
    form.invoiceNumber = data.invoiceNumber;
    form.salesContractNo = data.salesContractNo;
    form.projectName = data.projectName;
    form.supplierName = data.supplierName;
    form.entryDate = data.entryDate;
    form.productData = data.productData;
  }
const formattedNumber = (row, column, cellValue) => {
    if (cellValue == 0) {
        return parseFloat(cellValue).toFixed(2);
    }
    if (cellValue) {
        return parseFloat(cellValue).toFixed(2);
    } else {
        return cellValue;
    }
};
const getTableData = async (type, selectedRows) => {
    if (type == "add") {
        // æ£€æŸ¥æ‰€æœ‰é€‰æ‹©çš„合同是否具有相同的供应商名称
        const firstRow = selectedRows[0];
        const isSameSupplier = selectedRows.every(row =>
            row.supplierName === firstRow.supplierName
        );
        if (!isSameSupplier) {
            proxy.$modal.msgError("请选择相同供应商名称的合同");
            return;
        }
        // å…è®¸ä¸åŒçš„采购合同号批量处理,无需检查重复
        // æ¸…空表单数据
        Object.keys(form).forEach(key => {
            if (key !== 'productData') {
                form[key] = undefined;
            }
        });
        form.productData = [];
        // åŠ è½½æ‰€æœ‰é€‰ä¸­åˆåŒçš„äº§å“æ•°æ®
        const promises = selectedRows.map(row =>
            getInfo({ id: row.id })
        );
        Promise.all(promises).then(results => {
            // åˆå¹¶æ‰€æœ‰åˆåŒçš„产品数据,并为每个产品添加对应的合同信息
            const allProductData = [];
            results.forEach((result, index) => {
                const contract = selectedRows[index];
                const contractId = contract.id;
                if (result.data && result.data.productData) {
                    result.data.productData.forEach(item => {
                        allProductData.push({
                            ...item,
                            id: contractId, // æ˜Žç¡®è®¾ç½®åˆåŒID
                            purchaseLedgerNo: contract.purchaseContractNumber, // æ·»åŠ é‡‡è´­åˆåŒå·
                            supplierName: contract.supplierName, // æ·»åŠ ä¾›åº”å•†åç§°
                            projectName: contract.projectName // æ·»åŠ é¡¹ç›®åç§°
                        });
                    });
                }
            });
            // è®¾ç½®è¡¨å•数据(使用第一个合同的基本信息,采购合同号留空)
            form.purchaseLedgerNo = ""; // é‡‡è´­åˆåŒå·ç•™ç©ºï¼Œå› ä¸ºä¼šåœ¨äº§å“è¡¨æ ¼ä¸­åˆ†åˆ«æ˜¾ç¤º
            form.invoiceAmount = 0;
            form.invoiceNumber = "";
            form.entryDate = dayjs().format("YYYY-MM-DD");
            form.enterDate = dayjs().format("YYYY-MM-DD");
            form.salesContractNo = results[0].data.salesContractNo;
            form.projectName = results[0].data.projectName;
            form.supplierName = results[0].data.supplierName;
            // ä¿ç•™å½•入人信息
            form.issUerId = userStore.id;
            form.issUer = userStore.nickName;
            form.productData = allProductData;
            // å­˜å‚¨é€‰ä¸­çš„合同数据
            selectedContracts.value = selectedRows;
        });
    } else if (type == "edit") {
        const id = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows;
        const data = await getPurchaseById({ id, type: 2 });
        form.purchaseLedgerNo = data.purchaseContractNumber;
        form.invoiceAmount = data.invoiceAmount;
        form.invoiceNumber = data.invoiceNumber;
        form.salesContractNo = data.salesContractNo;
        form.projectName = data.projectName;
        form.supplierName = data.supplierName;
        form.entryDate = data.entryDate;
        form.productData = data.productData;
    }
};
// å­è¡¨åˆè®¡æ–¹æ³•
const summarizeChildrenTable = (param) => {
@@ -347,109 +452,186 @@
};
//本次来票数失焦操作
const invoiceNumBlur = (row) => {
  if (!row.ticketsNum || row.ticketsNum === "") {
    row.ticketsNum = 0;
  }
  if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
    proxy.$modal.msgWarning("本次开票数不得大于未开票数");
    row.ticketsNum = 0;
    return;
  }
  // è®¡ç®—本次来票金额
  row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2)
  // è®¡ç®—未来票数
  row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2)
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2)
  calculateinvoiceAmount();
    if (!row.ticketsNum || row.ticketsNum === "") {
        row.ticketsNum = 0;
    }
    if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
        proxy.$modal.msgWarning("本次开票数不得大于未开票数");
        row.ticketsNum = 0;
        return;
    }
    // è®¡ç®—本次来票金额
    row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2)
    // è®¡ç®—未来票数
    row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2)
    // è®¡ç®—未来票金额
    row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2)
    calculateinvoiceAmount();
};
// æœ¬æ¬¡æ¥ç¥¨é‡‘额失焦操作
const invoiceAmountBlur = (row) => {
  if (!row.ticketsAmount) {
    row.ticketsAmount = 0;
  }
  // è®¡ç®—是否超过来票总金额
  if (row.ticketsAmount > row.tempFutureTicketsAmount) {
    proxy.$modal.msgWarning("本次来票金额不得大于未来票金额");
    row.ticketsAmount = 0;
  }
  // è®¡ç®—本次来票数
  row.ticketsNum = Number(
    (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2)
  );
  // è®¡ç®—未来票数
  row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2)
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2)
  calculateinvoiceAmount();
    if (!row.ticketsAmount) {
        row.ticketsAmount = 0;
    }
    // è®¡ç®—是否超过来票总金额
    if (row.ticketsAmount > row.tempFutureTicketsAmount) {
        proxy.$modal.msgWarning("本次来票金额不得大于未来票金额");
        row.ticketsAmount = 0;
    }
    // è®¡ç®—本次来票数
    row.ticketsNum = Number(
        (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2)
    );
    // è®¡ç®—未来票数
    row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2)
    // è®¡ç®—未来票金额
    row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2)
    calculateinvoiceAmount();
};
const calculateinvoiceAmount = () => {
  let invoiceAmountTotal = 0;
  form.productData.forEach((item) => {
    if (item.ticketsAmount) {
      invoiceAmountTotal += Number(item.ticketsAmount);
    }
  });
  form.invoiceAmount = invoiceAmountTotal.toFixed(2);
    let invoiceAmountTotal = 0;
    form.productData.forEach((item) => {
        if (item.ticketsAmount) {
            invoiceAmountTotal += Number(item.ticketsAmount);
        }
    });
    form.invoiceAmount = invoiceAmountTotal.toFixed(2);
};
const open = (type, eid) => {
  openModal();
  getTableData(type, eid);
  id.value = eid;
const open = async (type, selectedRows) => {
    visible.value = true;
    // å¦‚果是批量操作,设置标题
    if (Array.isArray(selectedRows) && selectedRows.length > 1) {
        modalOptions.title = `批量新增 (${selectedRows.length}条)`;
    } else {
        modalOptions.title = type == "add" ? "新增" : "编辑";
    }
    // å¦‚果是单个操作,获取id
    if (!Array.isArray(selectedRows) || selectedRows.length === 1) {
        const idValue = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows;
        id.value = idValue;
    }
    await getTableData(type, selectedRows);
};
const uploadSuccess = (response) => {
  form.tempFileIds.push(response.data.tempId);
  console.log(form);
    form.tempFileIds.push(response.data.tempId);
    console.log(form);
};
const removeFile = (file) => {
  const { tempId } = file.response.data;
  form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId);
    const { tempId } = file.response.data;
    form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId);
};
const closeAndRefresh = () => {
  closeModal();
  emit('refreshList');
    closeModal();
    emit('refreshList');
};
const submitForm = () => {
  formRef.value.validate(async (valid, fields) => {
    if (valid) {
      // modalLoading.value = true;
      const { code } = await addOrUpdateRegistration({
        purchaseLedgerId: id.value,
        purchaseContractNumber: form.purchaseLedgerNo,
        invoiceNumber: form.invoiceNumber,
        invoiceAmount: form.invoiceAmount,
        salesContractNo: form.salesContractNo,
        projectName: form.projectName,
        productData: form.productData,
        issueDate: form.entryDate,
        issUerId: form.issUerId, // å½•入人id
        issUer: form.issUer, // å½•入人
        salesContractNoId: form.salesContractNoId,
        supplierName: form.supplierName,
        tempFileIds: form.tempFileIds,
        enterDate: form.enterDate,
        type: 4,
      });
      modalLoading.value = false;
      if (code == 200) {
        closeAndRefresh();
      }
    } else {
      modalLoading.value = false;
    }
  });
    proxy.$refs["formRef"].validate((valid) => {
        if (valid) {
            // å¦‚果是批量操作,将所有合同的数据放在一个数组里,只调用一次接口
            if (selectedContracts.value.length > 1) {
                // åˆ›å»ºåŒ…含所有合同数据的数组
                const batchData = selectedContracts.value.map(contract => {
                    // ç­›é€‰å‡ºå±žäºŽå½“前合同的产品数据
                    const contractProductData = form.productData.filter(item =>
                        item.id === contract.id
                    );
                    // ä¸ºæ¯ä¸ªé‡‡è´­åˆåŒåˆ›å»ºç‹¬ç«‹çš„对象
                    return {
                        // åŸºç¡€è¡¨å•数据
                        invoiceNumber: form.invoiceNumber,
                        invoiceAmount: form.invoiceAmount,
                        entryDate: form.entryDate,
                        enterDate: form.enterDate,
                        issUerId: form.issUerId, // å½•入人id
                        issUer: form.issUer, // å½•入人
                        tempFileIds: form.tempFileIds,
                        // åˆåŒå®žé™…信息
                        purchaseLedgerId: contract.id, // ä½¿ç”¨id作为字段名,值为purchaseLedgerId
                        purchaseContractNumber: contract.purchaseContractNumber, // ä½¿ç”¨å®žé™…的采购合同号
                        salesContractNo: contract.salesContractNo, // ä½¿ç”¨å®žé™…的销售合同号
                        supplierName: contract.supplierName, // ä½¿ç”¨å®žé™…的供应商名称
                        projectName: contract.projectName, // ä½¿ç”¨å®žé™…的项目名称
                        // äº§å“æ•°æ®
                        productData: proxy.HaveJson(contractProductData),
                        // æ‰¹é‡æ ‡è¯†
                        isBatch: true,
                        type: 4
                    };
                });
                // åªè°ƒç”¨ä¸€æ¬¡æŽ¥å£ï¼Œä¼ é€’包含所有合同数据的数组
                modalLoading.value = true;
                addOrUpdateRegistration(batchData).then((res) => {
                    modalLoading.value = false;
                    if (res.code === 200) {
                        proxy.$modal.msgSuccess("批量登记成功");
                        closeAndRefresh();
                    }
                }).catch(() => {
                    modalLoading.value = false;
                    proxy.$modal.msgError("批量登记失败");
                });
            } else {
                    // å•个合同提交逻辑 - ä»¥æ•°ç»„格式传递
                    const singleContract = selectedContracts.value[0];
                    const singleFormArray = [{
                        // åŸºç¡€è¡¨å•数据
                        invoiceNumber: form.invoiceNumber,
                        invoiceAmount: form.invoiceAmount,
                        entryDate: form.entryDate,
                        enterDate: form.enterDate,
                        issUerId: form.issUerId, // å½•入人id
                        issUer: form.issUer, // å½•入人
                        tempFileIds: form.tempFileIds,
                        // åˆåŒå®žé™…信息
                        purchaseLedgerId: singleContract.id, // ä½¿ç”¨id作为字段名,值为purchaseLedgerId
                        purchaseContractNumber: singleContract.purchaseContractNumber, // ä½¿ç”¨å®žé™…的采购合同号
                        salesContractNo: singleContract.salesContractNo, // ä½¿ç”¨å®žé™…的销售合同号
                        supplierName: singleContract.supplierName, // ä½¿ç”¨å®žé™…的供应商名称
                        projectName: singleContract.projectName, // ä½¿ç”¨å®žé™…的项目名称
                        // äº§å“æ•°æ®
                        productData: proxy.HaveJson(form.productData),
                        // æ‰¹é‡æ ‡è¯†
                        isBatch: false,
                        type: 4
                    }];
                    modalLoading.value = true;
                    addOrUpdateRegistration(singleFormArray).then((res) => {
                        modalLoading.value = false;
                        if (res.code === 200) {
                            proxy.$modal.msgSuccess("登记成功");
                            closeAndRefresh();
                        }
                    }).catch(() => {
                        modalLoading.value = false;
                        proxy.$modal.msgError("登记失败");
                    });
                }
        }
    });
};
defineExpose({
  open,
  closeAndRefresh,
    open,
    closeAndRefresh,
});
</script>
src/views/procurementManagement/invoiceEntry/index.vue
@@ -28,13 +28,6 @@
              clearable
          />
        </el-form-item>
        <el-form-item label="项目名称">
          <el-input
              v-model="filters.projectName"
              placeholder="请输入项目名称"
              clearable
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="getTableData"> æœç´¢ </el-button>
          <el-button @click="resetFilters"> é‡ç½® </el-button>
@@ -143,11 +136,6 @@
      width:300
    },
    {
      label: "项目名称",
      prop: "projectName",
      width:400
    },
    {
      label: "录入人",
      prop: "recorderName",
    },
@@ -198,11 +186,11 @@
};
const handleAdd = (type) => {
  if (selectedRows.value.length !== 1) {
    proxy.$modal.msgWarning("请先选中一条数据");
    return;
  }
  modalRef.value.open(type, selectedRows.value[0].id);
    if (selectedRows.value.length < 1) {
        proxy.$modal.msgWarning("请至少选中一条数据");
        return;
    }
    modalRef.value.open(type, selectedRows.value);
};
const handleEdit = (type, id) => {
src/views/procurementManagement/paymentEntry/index.vue
@@ -104,7 +104,6 @@
                                    size="small"
                                    @click="changeEditType(scope.row)"
                                    v-if="!scope.row.editType"
                                    :disabled="scope.row.registrant !== userStore.nickName"
                                >编辑</el-button
                                >
                                <el-button
@@ -113,7 +112,6 @@
                                    size="small"
                                    @click="saveReceiptPayment(scope.row)"
                                    v-if="scope.row.editType"
                                    :disabled="scope.row.registrant !== userStore.nickName"
                                >保存</el-button
                                >
                                <el-button
@@ -121,7 +119,6 @@
                                    type="primary"
                                    size="small"
                                    @click="handleDelete(scope.row)"
                                    :disabled="scope.row.registrant !== userStore.nickName"
                                >删除</el-button
                                >
                            </template>
@@ -243,7 +240,6 @@
                                v-model="form.registrant"
                                placeholder="请输入"
                                clearable
                                disabled
                            />
                        </el-form-item>
                    </el-col>
src/views/procurementManagement/paymentHistory/index.vue
@@ -118,9 +118,10 @@
const { form: searchForm } = useFormData({
  searchText: undefined,
    purchaseContractNumber: undefined,
  paymentDate: [],
  paymentDateStart: undefined,
  paymentDateEnd: undefined,
  // è®¾ç½®ä»˜æ¬¾æ—¥æœŸèŒƒå›´ä¸ºå½“天
  paymentDate: [dayjs().startOf('day').format('YYYY-MM-DD'), dayjs().endOf('day').format('YYYY-MM-DD')],
  paymentDateStart: dayjs().startOf('day').format('YYYY-MM-DD'),
  paymentDateEnd: dayjs().endOf('day').format('YYYY-MM-DD'),
});
// æŸ¥è¯¢åˆ—表
@@ -137,7 +138,8 @@
const getList = () => {
  tableLoading.value = true;
  const { paymentDate, ...rest } = searchForm;
  paymentHistoryListPage({ ...rest, ...page }).then((res) => {
  const { total, ...pageParams } = page;
  paymentHistoryListPage({ ...rest, ...pageParams }).then((res) => {
    tableLoading.value = false;
    tableData.value = res.records;
        page.total = res.total;
src/views/procurementManagement/procurementInvoiceLedger/Form/EditForm.vue
@@ -23,7 +23,7 @@
      </el-col>
      <el-col :span="12">
        <el-form-item label="发票号:">
          <el-input disabled v-model="form.invoiceNumber" />
          <el-input v-model="form.invoiceNumber" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
@@ -63,6 +63,7 @@
  ticketsNum: undefined, // æ¥ç¥¨æ•°
  ticketsAmount: undefined, // æ¥ç¥¨é‡‘额
    taxInclusiveUnitPrice: undefined, // å«ç¨Žå•ä»·
    ticketRegistrationId: undefined, // å«ç¨Žå•ä»·
});
const load = async (id) => {
@@ -78,6 +79,7 @@
    form.taxInclusiveUnitPrice = data.taxInclusiveUnitPrice;
    form.futureTickets = data.futureTickets;
    temFutureTickets.value = data.futureTickets;
        form.ticketRegistrationId = data.ticketRegistrationId;
  }
};
src/views/procurementManagement/procurementInvoiceLedger/fileList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,91 @@
<template>
  <el-dialog v-model="dialogVisible" title="附件" width="50%" :before-close="handleClose">
    <el-table :data="tableData" border height="40vh">
      <el-table-column label="附件名称" prop="name" min-width="400" show-overflow-tooltip />
      <el-table-column fixed="right" label="操作" width="200" align="center">
        <template #default="scope">
          <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">下载</el-button>
          <el-button link type="primary" size="small" @click="lookFile(scope.row)">预览</el-button>
          <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-dialog>
  <filePreview ref="filePreviewRef" />
  <UploadModal ref="uploadModalRef" @uploadSuccess="handleUploadSuccess" />
</template>
<script setup>
import { ref } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import filePreview from '@/components/filePreview/index.vue'
import UploadModal from './Modal/UploadModal.vue'
import { delCommonFileInvoiceLedger} from '@/api/publicApi/commonFile.js'
const dialogVisible = ref(false)
const tableData = ref([])
const currentId = ref('')
const { proxy } = getCurrentInstance();
const filePreviewRef = ref()
const uploadModalRef = ref()
const handleClose = () => {
  dialogVisible.value = false
}
const open = (list, id = '') => {
  dialogVisible.value = true
  tableData.value = list
  currentId.value = id
}
const handleUpload = () => {
  if (!currentId.value) {
    ElMessage.warning('无法获取当前记录ID,请关闭后重新打开附件窗口')
    return
  }
  uploadModalRef.value.handleImport(currentId.value)
}
const handleUploadSuccess = (data) => {
  ElMessage.success('上传成功')
  // è¿™é‡Œå¯ä»¥æ·»åŠ åˆ·æ–°é™„ä»¶åˆ—è¡¨çš„é€»è¾‘
  // æš‚时先关闭上传模态框
}
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
}
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
}
// åˆ é™¤é™„ä»¶
const handleDelete = (row) => {
  ElMessageBox.confirm(`确认删除附件"${row.name}"吗?`, '删除确认', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
        delCommonFileInvoiceLedger([row.id]).then(() => {
      ElMessage.success('删除成功')
      // ä»Žåˆ—表中移除已删除的附件
      const index = tableData.value.findIndex(item => item.id === row.id)
      if (index !== -1) {
        tableData.value.splice(index, 1)
      }
    }).catch(() => {
      ElMessage.error('删除失败')
    })
  }).catch(() => {
    proxy.$modal.msg('已取消删除')
  })
}
defineExpose({
  open
})
</script>
<style></style>
src/views/procurementManagement/procurementInvoiceLedger/index.vue
@@ -63,13 +63,6 @@
            <el-button link :icon="Files" type="danger"> é™„ä»¶ </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item
                  v-if="row.commonFiles.length !== 0"
                  :icon="Download"
                  command="download"
                >
                  ä¸‹è½½
                </el-dropdown-item>
                <el-dropdown-item :icon="Upload" command="upload">
                  ä¸Šä¼ 
                </el-dropdown-item>
@@ -80,16 +73,15 @@
        <template #operation="{ row }">
          <el-button
            type="primary"
            text
                        link
            @click="openEdit(row)"
                        :disabled="row.issUerId !== userStore.id"
          >
            ç¼–辑
          </el-button>
                    <el-button link type="primary" size="small" @click="downLoadFile(row)">附件</el-button>
          <el-button
            type="primary"
            text
                        :disabled="row.issUerId !== userStore.id"
                        link
            @click="handleDelete(row)"
          >
            åˆ é™¤
@@ -97,6 +89,7 @@
        </template>
      </PIMTable>
    </div>
        <FileList ref="fileListRef" />
    <UploadModal ref="modalRef" @uploadSuccess="uploadSuccess"></UploadModal>
    <EditModal ref="editmodalRef" @success="getTableData"></EditModal>
  </div>
@@ -111,19 +104,21 @@
  Search,
  Upload,
  EditPen,
  Delete,
} from "@element-plus/icons-vue";
import {
    delRegistration,
    productRecordPage,
    productUploadFile,
} from "@/api/procurementManagement/procurementInvoiceLedger.js";
import { delCommonFile } from "@/api/publicApi/commonFile.js";
import { onMounted } from "vue";
import { ElMessageBox } from "element-plus";
import { ElMessageBox, ElMessage } from "element-plus";
import UploadModal from "./Modal/UploadModal.vue";
import EditModal from "./Modal/EditModal.vue";
import useUserStore from "@/store/modules/user.js";
import {delInvoiceLedgerByRegProductId} from "@/api/salesManagement/invoiceLedger.js";
const userStore = useUserStore();
import dayjs from "dayjs";
import FileList from "./fileList.vue";
defineOptions({
  name: "来票台账",
@@ -148,7 +143,8 @@
  {
    purchaseContractNumber: undefined, // é‡‡è´­åˆåŒå·
    supplierName: undefined, // ä¾›åº”商
    createdAt: [], // æ¥ç¥¨æ—¥æœŸ
    // è®¾ç½®æ¥ç¥¨æ—¥æœŸèŒƒå›´ä¸ºå½“天
    createdAt: [dayjs().startOf('day').format('YYYY-MM-DD'), dayjs().endOf('day').format('YYYY-MM-DD')], // æ¥ç¥¨æ—¥æœŸ
  },
  [
    {
@@ -160,11 +156,6 @@
      label: "销售合同号",
      prop: "salesContractNo",
      width: 150,
    },
    {
      label: "项目名称",
      prop: "projectName",
      width: 240,
    },
    {
      label: "供应商名称",
@@ -231,7 +222,7 @@
    },
    {
      fixed: "right",
      width: 150,
      width: 190,
      label: "操作",
      dataType: "slot",
      slot: "operation",
@@ -267,7 +258,12 @@
const handleSelectionChange = (val) => {
  multipleVal.value = val;
};
//附件相关
const fileListRef = ref(null)
//查看附件
const downLoadFile = (row) => {
    fileListRef.value.open(row.commonFiles, row.id)
}
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
@@ -304,6 +300,29 @@
      console.log(row.commonFiles);
      openUoload(row.ticketRegistrationId);
      break;
    case "delete":
      // åˆ é™¤æ‰€æœ‰é™„ä»¶
      if (row.commonFiles.length > 0) {
        ElMessageBox.confirm(`确认删除该记录的所有附件吗?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          // èŽ·å–æ‰€æœ‰é™„ä»¶çš„ID
          const fileIds = row.commonFiles.map(file => file.id);
          delCommonFile(fileIds).then(() => {
            ElMessage.success('删除成功')
            // åˆ·æ–°æ•°æ®
            getTableData();
          }).catch(() => {
            ElMessage.error('删除失败')
          })
        }).catch(() => {
          ElMessage.info('已取消删除')
        })
      }
      break;
  }
};
src/views/procurementManagement/procurementLedger/fileList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
<template>
  <el-dialog v-model="dialogVisible" title="附件" width="40%" :before-close="handleClose">
    <el-table :data="tableData" border height="40vh">
      <el-table-column label="附件名称" prop="name" min-width="400" show-overflow-tooltip />
      <el-table-column fixed="right" label="操作" width="150" align="center">
        <template #default="scope">
          <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">下载</el-button>
          <el-button link type="primary" size="small" @click="lookFile(scope.row)">预览</el-button>
          <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-dialog>
  <filePreview ref="filePreviewRef" />
</template>
<script setup>
import { ref } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import filePreview from '@/components/filePreview/index.vue'
import { delCommonFile } from '@/api/publicApi/commonFile.js'
const dialogVisible = ref(false)
const tableData = ref([])
const { proxy } = getCurrentInstance();
const filePreviewRef = ref()
const handleClose = () => {
  dialogVisible.value = false
}
const open = (list) => {
  dialogVisible.value = true
  tableData.value = list
}
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
}
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
}
// åˆ é™¤é™„ä»¶
const handleDelete = (row) => {
  ElMessageBox.confirm(`确认删除附件"${row.name}"吗?`, '删除确认', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    delCommonFile([row.id]).then(() => {
      ElMessage.success('删除成功')
      // ä»Žåˆ—表中移除已删除的附件
      const index = tableData.value.findIndex(item => item.id === row.id)
      if (index !== -1) {
        tableData.value.splice(index, 1)
      }
    }).catch(() => {
      ElMessage.error('删除失败')
    })
  }).catch(() => {
    proxy.$modal.msg('已取消删除')
  })
}
defineExpose({
  open
})
</script>
<style></style>
src/views/procurementManagement/procurementLedger/index.vue
@@ -21,10 +21,6 @@
            <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search"
                      @change="handleQuery" />
          </el-form-item>
          <el-form-item label="项目名称:">
            <el-input v-model="searchForm.projectName" placeholder="请输入" clearable prefix-icon="Search"
                      @change="handleQuery" />
          </el-form-item>
          <el-form-item label="录入日期:">
            <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                            placeholder="请选择" clearable @change="changeDaterange" />
@@ -53,7 +49,7 @@
        show-summary
        :summary-method="summarizeMainTable"
        @expand-change="expandChange"
        height="calc(100vh - 18.5em)"
        height="calc(100vh - 19em)"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column type="expand">
@@ -103,21 +99,19 @@
        <el-table-column
          label="销售合同号"
          prop="salesContractNo"
          width="200"
          show-overflow-tooltip
        />
        <el-table-column
          label="供应商名称"
          width="240"
          prop="supplierName"
          show-overflow-tooltip
        />
        <el-table-column
          label="项目名称"
          prop="projectName"
          width="420"
          show-overflow-tooltip
        />
                <el-table-column
                    label="签订日期"
                    prop="executionDate"
                    width="100"
                    show-overflow-tooltip
                />
        <el-table-column
          label="付款方式"
          width="100"
@@ -134,7 +128,7 @@
        <el-table-column
          label="录入人"
          prop="recorderName"
           width="100"
           width="120"
          show-overflow-tooltip
        />
        <el-table-column
@@ -146,7 +140,7 @@
        <el-table-column
          fixed="right"
          label="操作"
          min-width="150"
          width="180"
          align="center"
        >
          <template #default="scope">
@@ -155,7 +149,6 @@
              type="primary"
              size="small"
              @click="openForm('edit', scope.row)"
                            :disabled="scope.row.receiptPaymentAmount>0 || scope.row.recorderName !== userStore.nickName"
              >编辑</el-button
            >
            <el-button
@@ -164,6 +157,13 @@
              size="small"
              @click="showQRCode(scope.row)"
              >生成二维码</el-button
            >
            <el-button
              link
              type="primary"
              size="small"
              @click="downLoadFile(scope.row)"
              >附件</el-button
            >
          </template>
@@ -206,8 +206,8 @@
              <el-select
                v-model="form.salesLedgerId"
                placeholder="请选择"
                                filterable
                clearable
                @change="salesLedgerChange"
              >
                <el-option
                  v-for="item in salesContractList"
@@ -225,6 +225,7 @@
              <el-select
                v-model="form.supplierId"
                placeholder="请选择"
                                filterable
                clearable
              >
                <el-option
@@ -236,17 +237,6 @@
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="项目名称:" prop="projectName">
              <el-input
                v-model="form.projectName"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="付款方式">
                            <el-input
@@ -256,6 +246,8 @@
                            />
                        </el-form-item>
                    </el-col>
        </el-row>
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="签订日期:" prop="executionDate">
                            <el-date-picker
@@ -277,7 +269,9 @@
                v-model="form.recorderId"
                placeholder="请选择"
                clearable
                disabled
                filterable
                default-first-option
                :reserve-keyword="false"
              >
                <el-option
                  v-for="item in userList"
@@ -637,15 +631,6 @@
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="项目名称:" prop="projectName">
              <el-input
                v-model="scanAddForm.projectName"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="合同金额(元):" prop="contractAmount">
              <el-input-number
                v-model="scanAddForm.contractAmount"
@@ -724,11 +709,6 @@
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="项目名称:">
              <el-input v-model="scanForm.projectName" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="扫码时间:">
              <el-input v-model="scanForm.scanTime" disabled />
            </el-form-item>
@@ -787,6 +767,7 @@
        </div>
      </template>
    </el-dialog>
        <FileList ref="fileListRef" />
  </div>
</template>
@@ -797,6 +778,7 @@
import { Search } from "@element-plus/icons-vue";
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import FileList from "./fileList.vue";
import {
  getSalesLedgerWithProducts,
  addOrUpdateSalesLedgerProduct,
@@ -851,7 +833,6 @@
    supplierName: "", // ä¾›åº”商名称
    purchaseContractNumber: "", // é‡‡è´­åˆåŒç¼–号
    salesContractNo: "", // é”€å”®åˆåŒç¼–号
    projectName: "", // é¡¹ç›®åç§°
    entryDate: null, // å½•入日期
    entryDateStart: undefined,
    entryDateEnd: undefined,
@@ -859,7 +840,6 @@
  form: {
    purchaseContractNumber: "",
    salesLedgerId: "",
    projectName: "",
    recorderId: "",
    entryDate: "",
    productData: [],
@@ -872,14 +852,19 @@
    purchaseContractNumber: [
      { required: true, message: "请输入", trigger: "blur" },
    ],
    projectName: [{ required: true, message: "请输入", trigger: "blur" }],
    supplierId: [{ required: true, message: "请输入", trigger: "blur" }],
        entryDate: [{ required: true, message: "请选择", trigger: "change" }],
        executionDate: [{ required: true, message: "请选择", trigger: "change" }],
  },
});
const {  form, rules } = toRefs(data);
const { form: searchForm } = useFormData(data.searchForm);
const { form: searchForm } = useFormData({
  ...data.searchForm,
  // è®¾ç½®å½•入日期范围为当天
  entryDate: [dayjs().startOf('day').format('YYYY-MM-DD'), dayjs().endOf('day').format('YYYY-MM-DD')],
  entryDateStart: dayjs().startOf('day').format('YYYY-MM-DD'),
  entryDateEnd: dayjs().endOf('day').format('YYYY-MM-DD')
});
// äº§å“è¡¨å•弹框数据
const productFormVisible = ref(false);
@@ -910,7 +895,7 @@
      { required: true, message: "请输入", trigger: "blur" },
    ],
    taxRate: [{ required: true, message: "请选择", trigger: "change" }],
        warnNum: [{ required: false, message: "请选择", trigger: "change" }],
        warnNum: [{ required: true, message: "请选择", trigger: "change" }],
    taxInclusiveTotalPrice: [
      { required: true, message: "请输入", trigger: "blur" },
    ],
@@ -1121,6 +1106,12 @@
      }
      form.value.tempFileIds = tempFileIds;
      form.value.type = 2;
      // å¦‚æžœsalesLedgerId为空,则不传递salesContractNo
      if (!form.value.salesLedgerId) {
        form.value.salesContractNo = ''
      }
      addOrEditPurchase(form.value).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeDia();
@@ -1398,7 +1389,6 @@
  var index = salesContractList.value.findIndex((item) => item.id == row);
  console.log("index", index);
  if (index > -1) {
    form.value.projectName = salesContractList.value[index].projectName;
    await querygProductInfoByContractNo();
  }
};
@@ -1411,6 +1401,11 @@
    productData.value = data;
  }
};
const fileListRef = ref(null)
const downLoadFile = (row) => {
    fileListRef.value.open(row.salesLedgerFiles)
}
// æ˜¾ç¤ºäºŒç»´ç 
const showQRCode = async (row) => {
@@ -1459,7 +1454,6 @@
  scanContent: "",
  purchaseContractNumber: "",
  supplierName: "",
  projectName: "",
  contractAmount: "",
  paymentMethod: "",
  recorderName: "",
@@ -1468,7 +1462,6 @@
const scanAddRules = {
  purchaseContractNumber: [{ required: true, message: "请输入采购合同号", trigger: "blur" }],
  supplierName: [{ required: true, message: "请输入供应商名称", trigger: "blur" }],
  projectName: [{ required: true, message: "请输入项目名称", trigger: "blur" }],
};
// æ‰«ç ç™»è®°å¯¹è¯æ¡†ç›¸å…³å˜é‡
@@ -1476,7 +1469,6 @@
const scanForm = reactive({
  purchaseContractNumber: "",
  supplierName: "",
  projectName: "",
  scanTime: "",
  scannerName: "",
  scanStatus: "未扫码",
@@ -1492,7 +1484,6 @@
  scanAddForm.scanContent = "";
  scanAddForm.purchaseContractNumber = "";
  scanAddForm.supplierName = "";
  scanAddForm.projectName = "";
  scanAddForm.contractAmount = "";
  scanAddForm.paymentMethod = "";
  scanAddForm.recorderName = userStore.nickName;
@@ -1505,14 +1496,13 @@
  if (!content) return;
  
  // æ¨¡æ‹Ÿè§£æžäºŒç»´ç å†…容,这里可以根据实际需求调整解析逻辑
  // å‡è®¾æ‰«ç å†…容格式为:合同号|供应商|项目|金额|付款方式
  // å‡è®¾æ‰«ç å†…容格式为:合同号|供应商|金额|付款方式
  const parts = content.split('|');
  if (parts.length >= 3) {
  if (parts.length >= 2) {
    scanAddForm.purchaseContractNumber = parts[0] || "";
    scanAddForm.supplierName = parts[1] || "";
    scanAddForm.projectName = parts[2] || "";
    scanAddForm.contractAmount = parts[3] || "";
    scanAddForm.paymentMethod = parts[4] || "";
    scanAddForm.contractAmount = parts[2] || "";
    scanAddForm.paymentMethod = parts[3] || "";
  }
};
@@ -1530,7 +1520,6 @@
      const newData = {
        purchaseContractNumber: scanAddForm.purchaseContractNumber,
        supplierName: scanAddForm.supplierName,
        projectName: scanAddForm.projectName,
        contractAmount: scanAddForm.contractAmount,
        paymentMethod: scanAddForm.paymentMethod,
        recorderName: scanAddForm.recorderName,
@@ -1553,7 +1542,6 @@
const openScanDialog = (row) => {
  scanForm.purchaseContractNumber = row.purchaseContractNumber;
  scanForm.supplierName = row.supplierName;
  scanForm.projectName = row.projectName;
  scanForm.scanTime = getCurrentDateTime();
  scanForm.scannerName = userStore.nickName;
  scanForm.scanStatus = "未扫码";
@@ -1605,4 +1593,4 @@
});
</script>
<style scoped lang="scss"></style>
<style scoped lang="scss"></style>
src/views/procurementManagement/procurementReport/index.vue
@@ -280,6 +280,7 @@
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Document, List, TrendCharts, Shop, Search, Refresh, Download } from '@element-plus/icons-vue'
import dayjs from "dayjs";
// å“åº”式数据
const loading = ref(false)
@@ -690,14 +691,10 @@
}
onMounted(() => {
  // è®¾ç½®é»˜è®¤æ—¶é—´èŒƒå›´ä¸ºæœ€è¿‘30天
  const endDate = new Date()
  const startDate = new Date()
  startDate.setDate(startDate.getDate() - 30)
  // è®¾ç½®é»˜è®¤æ—¶é—´èŒƒå›´ä¸ºå½“天
  searchForm.dateRange = [
    startDate.toISOString().split('T')[0],
    endDate.toISOString().split('T')[0]
    dayjs().startOf('day').format('YYYY-MM-DD'),
    dayjs().endOf('day').format('YYYY-MM-DD')
  ]
})
</script>
src/views/productionManagement/operationScheduling/components/formDia.vue
@@ -8,20 +8,47 @@
    >
      <el-button type="primary" @click="addRow" style="margin-bottom: 10px;">新增</el-button>
            <span style="font-size: 18px;margin-left: 10px">待排产数量:{{pendingNum}}</span>
<!--            <div style="margin-bottom: 10px; margin-left: 10px;">-->
<!--                <el-form-item label="领用:" style="margin-bottom: 0;">-->
<!--                    <el-input v-model="receive" placeholder="请输入领用" style="width: 200px;" />-->
<!--                </el-form-item>-->
<!--            </div>-->
      <el-table :data="tableData" border style="width: 100%" :summary-method="summarizeMainTable" show-summary :row-key="row => row.id">
        <el-table-column label="序号" width="60">
        <el-table-column label="序号" width="60" align="center">
          <template #default="scope">
            {{ scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column label="工序" prop="process">
        <el-table-column label="工序" prop="process" width="150">
          <template #default="scope">
                        <el-input v-model="scope.row.process" placeholder="请输入工序" />
          </template>
        </el-table-column>
        <el-table-column label="单位" prop="unit">
        <el-table-column label="产线" prop="productionLine" width="150">
          <template #default="scope">
            <el-select
              v-model="scope.row.productionLine"
              placeholder="选择产线"
              style="width: 100%;"
              clearable
            >
              <el-option
                v-for="line in productionLines"
                :key="line.value"
                :label="line.label"
                :value="line.value"
              />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="单位" prop="unit" width="90">
          <template #default="scope">
            <el-input v-model="scope.row.unit" placeholder="请输入单位" />
          </template>
        </el-table-column>
        <el-table-column label="口味/品名/规格" prop="type" width="150">
          <template #default="scope">
            <el-input v-model="scope.row.type" placeholder="请输入" />
          </template>
        </el-table-column>
        <el-table-column label="排产数量" width="200" prop="schedulingNum">
@@ -50,17 +77,20 @@
                        />
          </template>
        </el-table-column>
        <el-table-column label="排产日期" prop="schedulingDate">
        <el-table-column label="排产日期" prop="schedulingDate" width="200">
          <template #default="scope">
            <el-date-picker v-model="scope.row.schedulingDate" type="date" placeholder="选择日期" style="width: 100%;" value-format="YYYY-MM-DD" format="YYYY-MM-DD"/>
          </template>
        </el-table-column>
        <el-table-column label="排产人" prop="schedulingUserId">
        <el-table-column label="排产人" prop="schedulingUserId" width="150">
          <template #default="scope">
                        <el-select
                            v-model="scope.row.schedulingUserId"
                            placeholder="选择人员"
                            style="width: 100%;"
              filterable
              default-first-option
              :reserve-keyword="false"
                        >
                            <el-option
                                v-for="user in userList"
@@ -69,6 +99,11 @@
                                :value="user.userId"
                            />
                        </el-select>
          </template>
        </el-table-column>
        <el-table-column label="备注" prop="remark" width="200">
          <template #default="scope">
            <el-input v-model="scope.row.remark" placeholder="请输入备注" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="80">
@@ -88,7 +123,7 @@
</template>
<script setup>
import {ref} from "vue";
import {ref, getCurrentInstance} from "vue";
import {userListNoPageByTenantId} from "@/api/system/user.js";
import {processScheduling} from "@/api/productionManagement/operationScheduling.js";
const { proxy } = getCurrentInstance()
@@ -97,33 +132,56 @@
const dialogFormVisible = ref(false);
const operationType = ref('')
const tableData = ref([
    { process: '', schedulingDate: '', schedulingNum: '', schedulingUserId: '', workHours: '', unit: '' }
]);
const tableData = ref([]);
const unitFromRow = ref('');
const idFromRow = ref('');
const pendingNum = ref('');
const specificationModelFromRow = ref('');
const pendingNum = ref(0);
const userList = ref([])
const receive = ref('')
const sunqianUserId = ref('')
// äº§çº¿é€‰é¡¹
const productionLines = ref([
  { label: '产线1', value: '产线1' },
  { label: '产线2', value: '产线2' },
  { label: '产线3', value: '产线3' },
  { label: '产线4', value: '产线4' }
])
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
  dialogFormVisible.value = true;
    pendingNum.value = row?.pendingNum ?? 0;
    unitFromRow.value = row?.unit ?? '';
    idFromRow.value = row?.id ?? '';
    specificationModelFromRow.value = row?.specificationModel ?? '';
    userListNoPageByTenantId().then((res) => {
        userList.value = res.data;
        // æ‰¾åˆ°å­™å€©çš„用户ID并设置为默认值
        const sunqianUser = userList.value.find(user => user.nickName === '孙倩');
        if (sunqianUser) {
            sunqianUserId.value = sunqianUser.userId;
        }
        // åœ¨ç”¨æˆ·åˆ—表加载完成后创建行数据,并将产线数据带入
        tableData.value = [createRow(row)];
    });
    pendingNum.value = row.pendingNum
  if (row && row.unit !== undefined) {
    unitFromRow.value = row.unit;
    idFromRow.value = row.id;
    tableData.value.forEach(item => {
      item.unit = row.unit;
      item.id = row.id;
    });
  } else {
    unitFromRow.value = '';
  }
}
const createRow = (row) => ({
    id: idFromRow.value,
    process: '包装',
    schedulingDate: '',
    schedulingNum: null,
    schedulingUserId: sunqianUserId.value, // é»˜è®¤è®¾ç½®ä¸ºå­™å€©çš„用户ID
    workHours: null,
    unit: unitFromRow.value,
    remark: '',
    type: specificationModelFromRow.value,
    productionLine: row?.productionLine ?? '', // ä»Žè¡Œæ•°æ®ä¸­èŽ·å–äº§çº¿ä¿¡æ¯
});
const submitForm = () => {
    // 1. æ£€æŸ¥æ¯ä¸€è¡Œæ˜¯å¦å¡«å†™å®Œæ•´
    for (let i = 0; i < tableData.value.length; i++) {
@@ -134,7 +192,8 @@
            row.schedulingNum === '' || row.schedulingNum === null ||
            !row.schedulingUserId ||
            row.workHours === '' || row.workHours === null ||
            !row.unit
            !row.unit ||
            !row.productionLine
        ) {
            proxy.$modal.msgError(`第${i + 1}行数据未填写完整`);
            return;
@@ -148,7 +207,15 @@
        proxy.$modal.msgError('排产数量合计不能超过待排产数量');
        return;
    }
    processScheduling(tableData.value).then((res) => {
    // 3. å°† receive å­—段添加到每条数据中,并移除 loss å­—段
    const submitData = tableData.value.map(row => {
        const { loss, ...rest } = row;
        return {
            ...rest,
            receive: receive.value
        };
    });
    processScheduling(submitData).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeDia();
    })
@@ -159,6 +226,12 @@
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  dialogFormVisible.value = false;
  receive.value = '';
  tableData.value = [];
  unitFromRow.value = '';
  idFromRow.value = '';
  specificationModelFromRow.value = '';
  pendingNum.value = 0;
  emit('close')
};
defineExpose({
@@ -166,7 +239,7 @@
});
const addRow = () => {
  tableData.value.push({ id: idFromRow.value, process: '', unit: unitFromRow.value, schedulingNum: '', workHours: '', schedulingDate: '', schedulingUserId: '' });
  tableData.value.push(createRow());
};
const removeRow = (index) => {
  tableData.value.splice(index, 1);
src/views/productionManagement/operationScheduling/index.vue
@@ -7,11 +7,16 @@
                                        style="width: 200px;"
                                        @change="handleQuery" />
                </el-form-item>
                <el-form-item label="项目名称:">
                    <el-input v-model="searchForm.projectName" placeholder="请输入" clearable prefix-icon="Search"
                <el-form-item label="合同号:">
                    <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search"
                                        style="width: 200px;"
                                        @change="handleQuery" />
                </el-form-item>
<!--                <el-form-item label="项目名称:">-->
<!--                    <el-input v-model="searchForm.projectName" placeholder="请输入" clearable prefix-icon="Search"-->
<!--                                        style="width: 200px;"-->
<!--                                        @change="handleQuery" />-->
<!--                </el-form-item>-->
                <el-form-item label="派工日期:">
                    <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                                                    placeholder="请选择" clearable @change="changeDaterange" />
@@ -60,10 +65,12 @@
const data = reactive({
    searchForm: {
        staffName: "",
        customerName: "",
        salesContractNo: "",
        status: 1,
        entryDate: null, // å½•入日期
        entryDateStart: undefined,
        entryDateEnd: undefined,
        entryDate: [dayjs().format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD")], // å½•入日期,默认当天
        entryDateStart: dayjs().format("YYYY-MM-DD"),
        entryDateEnd: dayjs().format("YYYY-MM-DD"),
    },
});
const { searchForm } = toRefs(data);
@@ -105,21 +112,21 @@
        prop: "salesContractNo",
        width: 200,
    },
    {
        label: "客户合同号",
        prop: "customerContractNo",
        width: 200,
    },
    // {
    //     label: "客户合同号",
    //     prop: "customerContractNo",
    //     width: 200,
    // },
    {
        label: "客户名称",
        prop: "customerName",
        width: 200,
    },
    {
        label: "项目名称",
        prop: "projectName",
        width:300
    },
    // {
    //     label: "项目名称",
    //     prop: "projectName",
    //     width:300
    // },
    {
        label: "产品大类",
        prop: "productCategory",
@@ -131,6 +138,16 @@
        width: 150,
    },
    {
        label: "绑定机器",
        prop: "speculativeTradingName",
        width: 220,
    },
    // {
    //     label: "产线",
    //     prop: "productionLine",
    //     width: 220,
    // },
    {
        label: "单位",
        prop: "unit",
    },
src/views/productionManagement/productionCosting/index.vue
@@ -14,6 +14,15 @@
                    clearable
                    prefix-icon="Search"
                />
                <span class="search_title ml10">合同号:</span>
                <el-input
                    v-model="searchForm.salesContractNo"
                    style="width: 240px"
                    placeholder="请输入"
                    @change="handleQuery"
                    clearable
                    prefix-icon="Search"
                />
                <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
                >搜索</el-button
                >
@@ -61,21 +70,21 @@
        prop: "salesContractNo",
        width: 220,
    },
    {
        label: "客户合同号",
        prop: "customerContractNo",
        width: 250,
    },
    // {
    //     label: "客户合同号",
    //     prop: "customerContractNo",
    //     width: 250,
    // },
    {
        label: "客户名称",
        prop: "customerName",
        width: 250,
    },
    {
        label: "项目名称",
        prop: "projectName",
        width:300
    },
    // {
    //     label: "项目名称",
    //     prop: "projectName",
    //     width:300
    // },
    {
        label: "产品大类",
        prop: "productCategory",
@@ -121,6 +130,7 @@
const data = reactive({
    searchForm: {
        schedulingUserName: "",
        salesContractNo: "",
        entryDate: [
            dayjs().format("YYYY-MM-DD"),
            dayjs().add(1, "day").format("YYYY-MM-DD"),
src/views/productionManagement/productionDispatching/components/autoDispatchDia.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,153 @@
<template>
  <div>
    <el-dialog
        v-model="dialogFormVisible"
        title="自动派工"
        width="80%"
        @close="closeDia"
    >
      <el-form :model="form" label-width="140px" label-position="top" ref="formRef">
        <el-divider content-position="left">派工列表</el-divider>
        <el-table
            :data="dispatchList"
            border
            style="width: 100%; margin-top: 20px;"
            :row-class-name="tableRowClassName"
        >
          <el-table-column label="序号" type="index" width="60" align="center" />
          <el-table-column label="合同号" prop="salesContractNo" width="200" />
          <el-table-column label="客户名称" prop="customerName" width="200" />
          <!-- <el-table-column label="项目名称" prop="projectName" width="250" /> -->
          <el-table-column label="产品大类" prop="productCategory" width="150" />
          <el-table-column label="规格型号" prop="specificationModel" width="200" />
          <el-table-column label="绑定机器" prop="speculativeTradingName" width="120" />
          <el-table-column label="总数量" prop="quantity" width="100" align="right" />
          <el-table-column label="已排产" prop="schedulingNum" width="100" align="right" fixed="right" />
          <el-table-column label="待排产" prop="pendingQuantity" width="100" align="right" fixed="right" />
          <el-table-column label="本次排产" width="150" align="center" fixed="right">
            <template #default="{ row }">
              <el-input-number
                  v-model="row.schedulingNum"
                  :min="0"
                  :max="row.pendingQuantity"
                  :step="1"
                  :precision="0"
                  size="small"
                  style="width: 120px"
                  @change="(value) => changeCurrentNum(value, row)"
              />
            </template>
          </el-table-column>
        </el-table>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认派工</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import {ref, reactive, toRefs, computed} from "vue";
import {productionDispatch, productionDispatchList} from "@/api/productionManagement/productionOrder.js";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
const dialogFormVisible = ref(false);
const operationType = ref('')
const data = reactive({
  form: {},
  dispatchList: [], // æ´¾å·¥åˆ—表数据
});
const { form, dispatchList } = toRefs(data);
// è¡¨æ ¼è¡Œæ ·å¼
const tableRowClassName = ({ rowIndex }) => {
  if (rowIndex % 2 === 1) {
    return 'even-row'
  }
  return ''
}
// ä¿®æ”¹æœ¬æ¬¡æŽ’产数量
const changeCurrentNum = (value, row) => {
  if (value > row.pendingQuantity) {
    row.schedulingNum = row.pendingQuantity
    proxy.$modal.msgWarning('排产数量不可大于待排产数量')
  }
}
// æ‰“开弹框
const openDialog = (type, rows) => {
  operationType.value = type;
  dialogFormVisible.value = true;
  // å¤„理传入的数据
  dispatchList.value = rows.map(row => ({
    ...row,
    schedulingNum: 0, // åˆå§‹åŒ–本次排产数量为0
    pendingQuantity: (Number(row.quantity) || 0) - (Number(row.schedulingNum) || 0) // è®¡ç®—待排产数量
  }))
}
// æäº¤è¡¨å•
const submitForm = () => {
  // æ£€æŸ¥æ˜¯å¦æœ‰æŽ’产数据
  const hasSchedulingData = dispatchList.value.some(item => item.schedulingNum > 0)
  if (!hasSchedulingData) {
    proxy.$modal.msgWarning('请至少为一条记录设置排产数量')
    return
  }
  // æž„造提交数据 - ç›´æŽ¥ä¼ é€’数组,不过滤
  const submitData = dispatchList.value
  console.log('提交自动派工数据:', submitData)
  // è°ƒç”¨API(这里需要根据实际接口调整)
  productionDispatchList(submitData).then(res => {
    proxy.$modal.msgSuccess(res.msg);
    closeDia();
  }).catch(err => {
    proxy.$modal.msgError("派工失败");
    console.error('派工失败:', err);
  })
}
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
  dispatchList.value = []
  emit('close')
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
:deep(.even-row) {
  background-color: #fafafa;
}
:deep(.el-table .cell) {
  padding: 8px 12px;
}
:deep(.el-table th) {
  background-color: #f5f7fa;
  color: #606266;
  font-weight: 600;
}
</style>
src/views/productionManagement/productionDispatching/components/formDia.vue
@@ -7,7 +7,7 @@
        @close="closeDia"
    >
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
        <el-row :gutter="30">
        <!-- <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="项目名称:" prop="projectName">
              <el-input v-model="form.projectName" placeholder="请输入" clearable disabled/>
@@ -16,6 +16,18 @@
          <el-col :span="12">
            <el-form-item label="产品大类:" prop="productCategory">
              <el-input v-model="form.productCategory" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
        </el-row> -->
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="specificationModel">
              <el-input v-model="form.specificationModel" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="绑定机器:" prop="speculativeTradingName">
              <el-input v-model="form.speculativeTradingName" placeholder="自动获取" clearable disabled/>
            </el-form-item>
          </el-col>
        </el-row>
@@ -46,6 +58,11 @@
                            />
                        </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="产品大类:" prop="productCategory">
              <el-input v-model="form.productCategory" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
                    <el-col :span="12">
@@ -54,6 +71,9 @@
                                v-model="form.schedulingUserId"
                                placeholder="选择人员"
                                style="width: 100%;"
                filterable
                default-first-option
                :reserve-keyword="false"
                            >
                                <el-option
                                    v-for="user in userList"
@@ -105,11 +125,13 @@
  form: {
        projectName: "",
        productCategory: "",
        specificationModel: "", // è§„格型号
        quantity: "",
        schedulingNum: "",
        schedulingUserId: "",
        schedulingDate: "",
        pendingQuantity: "",
        speculativeTradingName: "", // ç»‘定机器名称
  },
  rules: {
        schedulingNum: [{ required: true, message: "请输入", trigger: "blur" },],
@@ -121,6 +143,7 @@
const userList = ref([])
const userStore = useUserStore()
// æ‰“开弹框
const openDialog = (type, row) => {
  operationType.value = type;
src/views/productionManagement/productionDispatching/index.vue
@@ -1,5 +1,32 @@
<template>
    <div class="app-container">
        <!-- ç‚’机1-4 å±•示(总量 / æ­£åœ¨ç”Ÿäº§é‡ / ç©ºä½™é‡ï¼‰ -->
        <div class="machines-grid">
            <div v-for="machine in machines" :key="machine.id" class="machine-card">
                <div class="machine-title">{{ machine.name }}</div>
                <div class="machine-metrics">
                <div class="machine-control">
                    <span>总量(kg):</span>
                    <el-input-number v-model="machineData[machine.name].workLoad" :min="0" :step="1" size="small" />
                </div>
                <div><span> é¢„计投入量(kg):</span><span>{{ machineData[machine.name].currentWorkLoad }}</span></div>
                <div><span>空余工作量(kg):</span><span>{{ machineData[machine.name].vacant }}</span></div>
            </div>
            </div>
            <div class="save-button-container">
                <div class="loss-rate-container">
                    <span class="loss-rate-label">损耗率(%):</span>
                    <el-select v-model="rate" placeholder="请选择损耗率" style="width: 120px" size="small">
                        <el-option label="6" :value="6" />
                        <el-option label="7" :value="7" />
                        <el-option label="8" :value="8" />
                        <el-option label="9" :value="9" />
                        <el-option label="10" :value="10" />
                    </el-select>
                </div>
                <el-button type="primary" @click="saveMachineTotals" size="small">保存设置</el-button>
            </div>
        </div>
        <div class="search_form">
            <div>
                <span class="search_title">客户名称:</span>
@@ -11,24 +38,40 @@
                    clearable
                    prefix-icon="Search"
                />
                <span class="search_title ml10">项目名称:</span>
                <span class="search_title ml10">合同号:</span>
                <el-input
                    v-model="searchForm.projectName"
                    v-model="searchForm.salesContractNo"
                    style="width: 240px"
                    placeholder="请输入"
                    @change="handleQuery"
                    clearable
                    prefix-icon="Search"
                />
<!--                <span class="search_title ml10">项目名称:</span>-->
<!--                <el-input-->
<!--                    v-model="searchForm.projectName"-->
<!--                    style="width: 240px"-->
<!--                    placeholder="请输入"-->
<!--                    @change="handleQuery"-->
<!--                    clearable-->
<!--                    prefix-icon="Search"-->
<!--                />-->
                <span class="search_title ml10">录入日期:</span>
                <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                                                placeholder="请选择" clearable @change="changeDaterange" />
                                        placeholder="请选择" clearable @change="changeDaterange" />
                <el-checkbox
                    style="margin-left: 10px"
                    v-model="searchForm.status"
                    label="不显示待排数量为0"
                    @change="handleQuery"
                />
                <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
            </div>
            <div>
                <el-button type="primary" @click="openForm('add')">生产派工</el-button>
                <el-button @click="handleOut">导出</el-button>
            </div>
            <el-button type="primary" @click="openForm('add')">生产派工</el-button>
            <el-button type="success" @click="openAutoDispatch">自动派工</el-button>
            <el-button @click="handleOut">导出</el-button>
        </div>
        </div>
        <div class="table_list">
            <PIMTable
@@ -44,23 +87,27 @@
            ></PIMTable>
        </div>
        <form-dia ref="formDia" @close="handleQuery"></form-dia>
        <auto-dispatch-dia ref="autoDispatchDia" @close="handleQuery"></auto-dispatch-dia>
    </div>
</template>
<script setup>
import {onMounted, ref} from "vue";
import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick, computed, watch} from "vue";
import FormDia from "@/views/productionManagement/productionDispatching/components/formDia.vue";
import AutoDispatchDia from "@/views/productionManagement/productionDispatching/components/autoDispatchDia.vue";
import dayjs from "dayjs";
import {schedulingListPage} from "@/api/productionManagement/productionOrder.js";
import {schedulingListPage, schedulingList, addSpeculatTrading, updateSpeculatTrading, getLossRate, addLossRate, updateLossRate} from "@/api/productionManagement/productionOrder.js";
import { ElMessageBox } from "element-plus";
const data = reactive({
    searchForm: {
        customerName: "",
        salesContractNo: "",
        projectName: "",
        entryDate: null, // å½•入日期
        entryDateStart: undefined,
        entryDateEnd: undefined,
        status: true,
        entryDate: [dayjs().format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD")], // å½•入日期,默认当天
        entryDateStart: dayjs().format("YYYY-MM-DD"),
        entryDateEnd: dayjs().format("YYYY-MM-DD"),
    },
});
const { searchForm } = toRefs(data);
@@ -71,19 +118,9 @@
        width: 220,
    },
    {
        label: "客户合同号",
        prop: "customerContractNo",
        width: 250,
    },
    {
        label: "客户名称",
        prop: "customerName",
        width: 250,
    },
    {
        label: "项目名称",
        prop: "projectName",
        width:300
    },
    {
        label: "产品大类",
@@ -93,7 +130,12 @@
    {
        label: "规格型号",
        prop: "specificationModel",
        width: 220,
        width: 120,
    },
    {
        label: "绑定机器",
        prop: "speculativeTradingName",
        width: 160,
    },
    {
        label: "单位",
@@ -104,6 +146,32 @@
        label: "录入日期",
        prop: "entryDate",
        width: 120,
    },
    {
        label: "状态",
        prop: "status",
        dataType: "tag",
        formatType: (params) => {
            if (params == '生产中') {
                return "warning";
            } else if (params == '未开始') {
                return "danger";
            } else {
                return "success";
            }
        },
    },
    {
        label: "生产进度",
        prop: "progress",
        formatData: (cellValue) => {
            // å¦‚果值为空或undefined,显示空字符串
            if (cellValue === null || cellValue === undefined || cellValue === '') {
                return '';
            }
            // ç›´æŽ¥åœ¨æ•°å­—后面添加百分号
            return `${cellValue}%`;
        }
    },
    {
        label: "数量",
@@ -118,6 +186,7 @@
        label: "待排数量",
        prop: "pendingQuantity",
        width: 100,
        fixed: 'right',
    },
]);
const tableData = ref([]);
@@ -129,7 +198,140 @@
    total: 0,
});
const formDia = ref()
const autoDispatchDia = ref()
const { proxy } = getCurrentInstance()
// ç‚’机数据
const machineData = reactive({
    "炒机1": { workLoad: 0, currentWorkLoad: 0, vacant: 0 },
    "炒机2": { workLoad: 0, currentWorkLoad: 0, vacant: 0 },
    "炒机3": { workLoad: 0, currentWorkLoad: 0, vacant: 0 },
    "炒机4": { workLoad: 0, currentWorkLoad: 0, vacant: 0 }
})
// ç‚’机配置数组
const machines = [
    { id: 1, name: '炒机1' },
    { id: 2, name: '炒机2' },
    { id: 3, name: '炒机3' },
    { id: 4, name: '炒机4' }
]
// ä¿å­˜ç‚’机总量设置
const saveMachineTotals = () => {
    // éªŒè¯æŸè€—率是否已选择
    if (rate.value === null || rate.value === undefined || isNaN(rate.value)) {
        proxy.$message.warning('请选择损耗率');
        return;
    }
    // æž„造保存数据数组,使用machines数组循环构建
    const saveData = machines.map(machine => {
        const saveItem = {
            name: machine.name, // ç‚’机名称
            workLoad: machineData[machine.name].workLoad,  // æ€»é‡
            currentWorkLoad: machineData[machine.name].currentWorkLoad, //  é¢„计投入量
            vacant: machineData[machine.name].vacant   // ç©ºä½™é‡
        };
        // å¦‚果是修改操作,需要传递id字段
        if (hasQueryData.value) {
            const queryData = getMachineQueryData(machine.id);
            if (queryData && queryData.id) {
                saveItem.id = queryData.id;
            }
        }
        return saveItem;
    });
    // æž„造损耗率数据
    const rateData = {
        rate: rate.value
    };
    // å¦‚果有ID,说明是修改操作
    if (rateId.value) {
        rateData.id = rateId.value;
    }
    // æ ¹æ®æ˜¯å¦æœ‰æŸ¥è¯¢æ•°æ®å†³å®šè°ƒç”¨æ–°å¢žæŽ¥å£è¿˜æ˜¯ä¿®æ”¹æŽ¥å£
    const saveApi = hasQueryData.value ? updateSpeculatTrading : addSpeculatTrading;
    const successMessage = hasQueryData.value ? '炒机设置修改成功' : '炒机设置新增成功';
    // æ ¹æ®æ˜¯å¦æœ‰ID决定调用新增接口还是修改接口
    const rateApi = rateId.value ? updateLossRate : addLossRate;
    const rateSuccessMessage = rateId.value ? '损耗率修改成功' : '损耗率新增成功';
    // å¹¶è¡Œè°ƒç”¨ä¸¤ä¸ªæŽ¥å£
    Promise.all([
        saveApi(saveData),
        rateApi(rateData)
    ]).then(([saveRes, rateRes]) => {
        proxy.$message.success(successMessage);
        proxy.$message.success(rateSuccessMessage);
        // ä¿å­˜æˆåŠŸåŽï¼Œè®¾ç½®hasQueryData为true,下次保存将调用修改接口
        if (!hasQueryData.value) {
            hasQueryData.value = true;
        }
        // å¦‚果返回了ID,保存起来
        if (rateRes && rateRes.data && rateRes.data.id) {
            rateId.value = rateRes.data.id;
        }
        // ä¿å­˜æˆåŠŸåŽé‡æ–°è°ƒç”¨æŸ¥è¯¢é¡µé¢
        getList();
    }).catch(err => {
        proxy.$message.error('保存失败');
        console.error('保存失败:', err);
    });
}
// èŽ·å–ç‚’æœºæŸ¥è¯¢æ•°æ®
const machineQueryData = ref([]);
const getMachineQueryData = (machineId) => {
    return machineQueryData.value.find(item => item.id === machineId);
};
const getMachineIndex = (item) => {
    // å…¼å®¹å¤šç§å­—段命名,返回 1-4 ä¹‹ä¸€ï¼Œå¦åˆ™è¿”回 0(未知)
    const candidates = [item.machineId, item.machineNo, item.machine, item.deviceNo, item.deviceId]
    for (const v of candidates) {
        if (v === undefined || v === null) continue
        const n = Number(String(v).replace(/[^\d]/g, "")) // æŠ½å–æ•°å­—
        if ([1,2,3,4].includes(n)) return n
    }
    return 0
}
const computeTodaySummary = () => {
    const todayStr = dayjs().format("YYYY-MM-DD")
    // é‡ç½®æ‰€æœ‰ç‚’机数据
    machines.forEach(machine => {
        machineData[machine.name] = { workLoad: 0, currentWorkLoad: 0, vacant: 0 }
    })
    tableData.value.forEach(item => {
        // ä»…统计当天
        const isToday = dayjs(item.entryDate).format("YYYY-MM-DD") === todayStr
        if (!isToday) return
        // ä½¿ç”¨æ­£ç¡®çš„字段名:workLoad(炒机工作量), currentWorkLoad(炒机正在工作量)
        const workLoad = Number(item.workLoad) || 0
        const currentWorkLoad = Number(item.currentWorkLoad) || 0
        const machineName = item.speculativeTradingName || '炒机1'
        if (machineData[machineName]) {
            machineData[machineName].workLoad += workLoad
            machineData[machineName].currentWorkLoad += currentWorkLoad
            machineData[machineName].vacant = machineData[machineName].workLoad - machineData[machineName].currentWorkLoad
        }
    })
}
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
@@ -137,6 +339,56 @@
    page.current = 1;
    getList();
};
// æ˜¯å¦æœ‰æŸ¥è¯¢æ•°æ®
const hasQueryData = ref(false)
// æŸè€—率
const rate = ref(6)
// æŸè€—率ID
const rateId = ref(null)
// èŽ·å–ç‚’æœºæ­£åœ¨å·¥ä½œé‡æ•°æ®
const getMachineProductionData = () => {
    schedulingList().then((res) => {
        // å¤„理炒机正在工作量数据
        if (res.data && Array.isArray(res.data)) {
            // è®¾ç½®æ˜¯å¦æœ‰æŸ¥è¯¢æ•°æ®
            hasQueryData.value = res.data.length > 0
            // ä¿å­˜æŸ¥è¯¢æ•°æ®åˆ°machineQueryData
            machineQueryData.value = res.data;
            // é‡ç½®æ‰€æœ‰ç‚’机数据
            machines.forEach(machine => {
                machineData[machine.name] = { workLoad: 0, currentWorkLoad: 0, vacant: 0 }
            });
            // éåŽ†æ•°æ®ï¼Œæ ¹æ®æŸ¥è¯¢è¿”å›žçš„æ•°æ®ç»“æž„å¤„ç†
            res.data.forEach(item => {
                // æ ¹æ®name字段确定炒机
                const machineName = item.name || '炒机1';
                if (machineData[machineName]) {
                    // å¦‚果查询数据中有workLoad,则初始化炒机总量
                    if (item.workLoad !== null && item.workLoad !== undefined) {
                        machineData[machineName].workLoad = Number(item.workLoad) || 0;
                    }
                    // å¦‚果查询数据中有currentWorkLoad,则设置正在工作量
                    if (item.currentWorkLoad !== null && item.currentWorkLoad !== undefined) {
                        machineData[machineName].currentWorkLoad = Number(item.currentWorkLoad) || 0;
                    }
                    // è®¡ç®—空余工作量
                    machineData[machineName].vacant = machineData[machineName].workLoad - machineData[machineName].currentWorkLoad;
                }
            });
        }
    }).catch(err => {
        console.error('获取炒机正在工作量数据失败:', err);
    });
};
const changeDaterange = (value) => {
    if (value) {
        searchForm.value.entryDateStart = value[0];
@@ -165,9 +417,33 @@
            pendingQuantity: (Number(item.quantity) || 0) - (Number(item.schedulingNum) || 0)
        }));
        page.total = res.data.total;
        computeTodaySummary()
        // åŒæ—¶èŽ·å–ç‚’æœºæ­£åœ¨å·¥ä½œé‡æ•°æ®
        getMachineProductionData();
        // èŽ·å–æŸè€—çŽ‡æ•°æ®
        getLossRateData();
    }).catch(() => {
        tableLoading.value = false;
    })
};
// èŽ·å–æŸè€—çŽ‡æ•°æ®
const getLossRateData = () => {
    getLossRate().then((res) => {
        const data = res.data || res;
        if (data && data.rate !== undefined && data.rate !== null) {
            rate.value = Number(data.rate); // ç¡®ä¿è½¬æ¢ä¸ºæ•°å­—
            rateId.value = data.id || null;
        } else {
            rate.value = 6;
            rateId.value = null;
        }
    }).catch(err => {
        console.error('获取损耗率数据失败:', err);
        rate.value = 6;
        rateId.value = null;
    });
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
@@ -189,6 +465,26 @@
    })
};
// æ‰“开自动派工弹框
const openAutoDispatch = () => {
    if (selectedRows.value.length === 0) {
        proxy.$message.error("请选择至少一条数据");
        return;
    }
    // è¿‡æ»¤æŽ‰å¾…排产数量为0的数据
    const validRows = selectedRows.value.filter(row => row.pendingQuantity > 0);
    if (validRows.length === 0) {
        proxy.$message.warning("选中的数据无需派工");
        return;
    }
    nextTick(() => {
        autoDispatchDia.value?.openDialog('auto', validRows)
    })
};
// å¯¼å‡º
const handleOut = () => {
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
@@ -206,7 +502,129 @@
onMounted(() => {
    getList();
    getLossRateData();
});
</script>
<style scoped></style>
<style scoped>
.summary-bar{
    display: flex;
    gap: 16px;
    margin: 10px 0 16px 0;
}
.summary-item{
    background: #f5f7fa;
    border: 1px solid #ebeef5;
    border-radius: 6px;
    padding: 10px 16px;
    min-width: 160px;
}
.summary-label{
    color: #909399;
    font-size: 12px;
    margin-bottom: 6px;
}
.summary-value{
    color: #303133;
    font-size: 20px;
    font-weight: 600;
}
.summary-control{
    display: flex;
    align-items: center;
    height: 28px;
}
.machines-grid{
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 20px;
    padding: 16px;
    background: #f8f9fa;
    border-radius: 8px;
    border: 1px solid #e9ecef;
}
.machine-card{
    border: 1px solid #dee2e6;
    border-radius: 8px;
    padding: 16px;
    background: #fff;
    box-shadow: 0 2px 4px rgba(0,0,0,0.05);
    transition: all 0.3s ease;
}
.machine-card:hover{
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.machine-title{
    font-weight: 600;
    font-size: 16px;
    margin-bottom: 12px;
    color: #2c3e50;
    text-align: center;
    padding-bottom: 8px;
    border-bottom: 2px solid #3498db;
}
.machine-metrics{
    display: flex;
    flex-direction: column;
    gap: 10px;
    color: #495057;
}
.machine-control{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 0;
    border-bottom: 1px solid #f1f3f4;
}
.machine-control span{
    font-size: 14px;
    white-space: nowrap;
    color: #6c757d;
    font-weight: 500;
}
.machine-metrics > div:not(.machine-control) {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0;
    font-size: 14px;
}
.machine-metrics > div:not(.machine-control) span:first-child {
    color: #6c757d;
}
.machine-metrics > div:not(.machine-control) span:last-child {
    font-weight: 600;
    color: #2c3e50;
}
.save-button-container{
    grid-column: 1 / -1;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 16px;
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid #e9ecef;
}
.loss-rate-container{
    display: flex;
    align-items: center;
    gap: 8px;
}
.loss-rate-label{
    font-size: 14px;
    color: #6c757d;
    font-weight: 500;
    white-space: nowrap;
}
</style>
src/views/productionManagement/productionOrder/index.vue
@@ -11,15 +11,24 @@
                    clearable
                    prefix-icon="Search"
                />
                <span class="search_title ml10">项目名称:</span>
                <span class="search_title ml10">合同号:</span>
                <el-input
                    v-model="searchForm.projectName"
                    v-model="searchForm.salesContractNo"
                    style="width: 240px"
                    placeholder="请输入"
                    @change="handleQuery"
                    clearable
                    prefix-icon="Search"
                />
<!--                <span class="search_title ml10">项目名称:</span>-->
<!--                <el-input-->
<!--                    v-model="searchForm.projectName"-->
<!--                    style="width: 240px"-->
<!--                    placeholder="请输入"-->
<!--                    @change="handleQuery"-->
<!--                    clearable-->
<!--                    prefix-icon="Search"-->
<!--                />-->
                <span class="search_title ml10">录入日期:</span>
                <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                                                placeholder="请选择" clearable @change="changeDaterange" />
@@ -58,25 +67,25 @@
        width: 120,
    },
    {
        label: "合同号",
        label: "销售合同号",
        prop: "salesContractNo",
        width: 220,
    },
    {
        label: "客户合同号",
        prop: "customerContractNo",
        width: 250,
    },
    // {
    //     label: "客户合同号",
    //     prop: "customerContractNo",
    //     width: 250,
    // },
    {
        label: "客户名称",
        prop: "customerName",
        width: 250,
    },
    {
        label: "项目名称",
        prop: "projectName",
        width:300
    },
    // {
    //     label: "项目名称",
    //     prop: "projectName",
    //     width:300
    // },
    {
        label: "付款状态",
        prop: "status",
@@ -132,10 +141,12 @@
const data = reactive({
    searchForm: {
        customerName: "",
        salesContractNo: "",
        projectName: "",
        entryDate: null, // å½•入日期
        entryDateStart: undefined,
        entryDateEnd: undefined,
        status: "",
        entryDate: [dayjs().format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD")], // å½•入日期,默认当天
        entryDateStart: dayjs().format("YYYY-MM-DD"),
        entryDateEnd: dayjs().format("YYYY-MM-DD"),
    },
});
const { searchForm } = toRefs(data);
src/views/productionManagement/productionReporting/components/formDia.vue
@@ -13,8 +13,15 @@
              <el-input v-model="form.schedulingNum" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="本次生产数量:" prop="finishedNum">
                    <el-col :span="12">
                        <el-form-item label="待生产数量:" prop="pendingNum">
                            <el-input v-model="form.pendingNum" placeholder="请输入" clearable disabled/>
                        </el-form-item>
                    </el-col>
        </el-row>
        <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="本次生产数量:" prop="finishedNum">
                            <el-input-number
                                v-model="form.finishedNum"
                                placeholder="请输入"
@@ -25,13 +32,18 @@
                                style="width: 100%"
                                @change="changeNum"
                            />
                        </el-form-item>
                    </el-col>
          <el-col :span="12">
            <el-form-item label="单价(元):" prop="unitPrice">
              <el-input v-model="form.unitPrice" placeholder="请输入" clearable @input="calculateTotalPrice"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="待生产数量:" prop="pendingNum">
              <el-input v-model="form.pendingNum" placeholder="请输入" clearable disabled/>
            <el-form-item label="总价(元):" prop="totalPrice">
              <el-input v-model="form.totalPrice" placeholder="请输入" clearable disabled/>
            </el-form-item>
          </el-col>
        </el-row>
@@ -42,6 +54,9 @@
                                v-model="form.schedulingUserId"
                                placeholder="选择人员"
                                style="width: 100%;"
                filterable
                default-first-option
                :reserve-keyword="false"
                            >
                                <el-option
                                    v-for="user in userList"
@@ -95,6 +110,8 @@
        finishedNum: "",
        schedulingUserId: "",
        schedulingDate: "",
        unitPrice: "",
        totalPrice: "",
  },
  rules: {
        schedulingNum: [{ required: true, message: "请输入", trigger: "blur" },],
@@ -118,6 +135,19 @@
        proxy.$modal.msgWarning('本次生产数量不可大于排产数量')
    }
    form.value.pendingNum = form.value.schedulingNum - form.value.finishedNum;
    calculateTotalPrice();
}
// è®¡ç®—总价
const calculateTotalPrice = () => {
    const quantity = Number(form.value.finishedNum ?? 0);
    const unitPrice = Number(form.value.unitPrice ?? 0);
    if (quantity > 0 && unitPrice > 0) {
        form.value.totalPrice = (quantity * unitPrice).toFixed(2);
    } else {
        form.value.totalPrice = '0.00';
    }
}
// æäº¤äº§å“è¡¨å•
const submitForm = () => {
src/views/productionManagement/productionReporting/index.vue
@@ -7,11 +7,16 @@
                                        style="width: 200px;"
                                        @change="handleQuery" />
                </el-form-item>
                <el-form-item label="项目名称:">
                    <el-input v-model="searchForm.projectName" placeholder="请输入" clearable prefix-icon="Search"
                <el-form-item label="合同号:">
                    <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search"
                                        style="width: 200px;"
                                        @change="handleQuery" />
                </el-form-item>
<!--                <el-form-item label="项目名称:">-->
<!--                    <el-input v-model="searchForm.projectName" placeholder="请输入" clearable prefix-icon="Search"-->
<!--                                        style="width: 200px;"-->
<!--                                        @change="handleQuery" />-->
<!--                </el-form-item>-->
                <el-form-item label="排产日期:">
                    <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
                                                    placeholder="请选择" clearable @change="changeDaterange" />
@@ -148,10 +153,13 @@
const data = reactive({
    searchForm: {
        staffName: "",
        entryDate: null, // å½•入日期
        entryDateStart: undefined,
        entryDateEnd: undefined,
        customerName: "",
        salesContractNo: "",
        projectName: "",
        status: "",
        entryDate: [dayjs().format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD")], // å½•入日期,默认当天
        entryDateStart: dayjs().format("YYYY-MM-DD"),
        entryDateEnd: dayjs().format("YYYY-MM-DD"),
    },
});
const { searchForm } = toRefs(data);
@@ -197,25 +205,29 @@
        prop: "schedulingUserName",
    },
    {
        label: "产线",
        prop: "productionLine",
    },
    {
        label: "合同号",
        prop: "salesContractNo",
        width: 200,
    },
    {
        label: "客户合同号",
        prop: "customerContractNo",
        width: 200,
    },
    // {
    //     label: "客户合同号",
    //     prop: "customerContractNo",
    //     width: 200,
    // },
    {
        label: "客户名称",
        prop: "customerName",
        width: 200,
    },
    {
        label: "项目名称",
        prop: "projectName",
        width:300
    },
    // {
    //     label: "项目名称",
    //     prop: "projectName",
    //     width:300
    // },
    {
        label: "产品大类",
        prop: "productCategory",
@@ -227,12 +239,27 @@
        width: 150,
    },
    {
        label: "绑定机器",
        prop: "speculativeTradingName",
        width: 220,
    },
    {
        label: "单位",
        prop: "unit",
    },
    {
        label: "工序",
        prop: "process",
    },
    // {
    //     label: "口味分类",
    //     prop: "type",
    //     width: 150,
    // },
    {
        label: "损耗",
        prop: "loss",
        width: 150,
    },
    {
        label: "排产数量",
@@ -249,6 +276,11 @@
        prop: "pendingFinishNum",
        width: 100,
    },
    {
        label: "备注",
        prop: "remark",
        width: 200,
    },
]);
const tableData = ref([]);
const selectedRows = ref([]);
src/views/qualityManagement/finalInspection/components/filesDia.vue
@@ -30,16 +30,10 @@
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="500"
                    :page="page"
                    @pagination="pagination"
      >
      </PIMTable>
            <pagination
                style="margin: 10px 0"
                v-show="total > 0"
                @pagination="paginationSearch"
                :total="total"
                :page="page.current"
                :limit="page.size"
            />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
@@ -95,6 +89,7 @@
const page = reactive({
    current: 1,
    size: 100,
    total: 0
});
const total = ref(0);
const tableData = ref([]);
@@ -111,7 +106,7 @@
  currentId.value = row.id;
  getList()
}
const paginationSearch = (obj) => {
const pagination = (obj) => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
@@ -119,7 +114,7 @@
const getList = () => {
  qualityInspectFileListPage({inspectId: currentId.value}).then(res => {
    tableData.value = res.data.records;
        total.value = res.data.total;
        page.total = res.data.total;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
src/views/qualityManagement/finalInspection/components/formDia.vue
@@ -58,7 +58,9 @@
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
                            <el-select v-model="form.checkName" placeholder="请选择" clearable>
                            <el-select v-model="form.checkName"               filterable
                         default-first-option
                         :reserve-keyword="false" placeholder="请选择" clearable>
                                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                                     :value="item.nickName"/>
                            </el-select>
src/views/qualityManagement/finalInspection/index.vue
@@ -150,7 +150,7 @@
    label: "操作",
    align: "center",
    fixed: "right",
    width: 280,
    width: 300,
    operation: [
      {
        name: "编辑",
src/views/qualityManagement/processInspection/components/filesDia.vue
@@ -30,16 +30,10 @@
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="500"
                    :page="page"
                    @pagination="pagination"
      >
      </PIMTable>
            <pagination
                style="margin: 10px 0"
                v-show="total > 0"
                @pagination="paginationSearch"
                :total="total"
                :page="page.current"
                :limit="page.size"
            />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
@@ -60,7 +54,6 @@
  qualityInspectFileDel,
  qualityInspectFileListPage
} from "@/api/qualityManagement/qualityInspectFile.js";
import Pagination from "@/components/PIMTable/Pagination.vue";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
@@ -98,6 +91,7 @@
const page = reactive({
    current: 1,
    size: 100,
    total: 0
});
const total = ref(0);
const tableData = ref([]);
@@ -114,17 +108,18 @@
  currentId.value = row.id;
  getList()
}
const paginationSearch = (obj) => {
const getList = () => {
  qualityInspectFileListPage({inspectId: currentId.value}).then(res => {
    tableData.value = res.data.records;
        page.total = res.data.total;
  })
}
const pagination = (obj) => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
};
const getList = () => {
  qualityInspectFileListPage({inspectId: currentId.value}).then(res => {
    tableData.value = res.data.records;
        total.value = res.data.total;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection;
src/views/qualityManagement/processInspection/components/formDia.vue
@@ -65,7 +65,9 @@
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
                            <el-select v-model="form.checkName" placeholder="请选择" clearable>
                            <el-select v-model="form.checkName"               filterable
                         default-first-option
                         :reserve-keyword="false" placeholder="请选择" clearable>
                                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                                     :value="item.nickName"/>
                            </el-select>
src/views/qualityManagement/processInspection/index.vue
@@ -155,7 +155,7 @@
    label: "操作",
    align: "center",
    fixed: "right",
    width: 280,
    width: 300,
    operation: [
      {
        name: "编辑",
src/views/qualityManagement/rawMaterialInspection/components/filesDia.vue
@@ -30,16 +30,10 @@
          :isSelection="true"
          @selection-change="handleSelectionChange"
          height="500"
                    :page="page"
                    @pagination="pagination"
      >
      </PIMTable>
            <pagination
                style="margin: 10px 0"
                v-show="total > 0"
                @pagination="paginationSearch"
                :total="total"
                :page="page.current"
                :limit="page.size"
            />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDia">取消</el-button>
@@ -60,7 +54,6 @@
  qualityInspectFileDel,
  qualityInspectFileListPage
} from "@/api/qualityManagement/qualityInspectFile.js";
import Pagination from "@/components/PIMTable/Pagination.vue";
const { proxy } = getCurrentInstance()
const emit = defineEmits(['close'])
@@ -97,6 +90,7 @@
const page = reactive({
    current: 1,
    size: 100,
    total: 0
});
const total = ref(0);
const tableData = ref([]);
@@ -114,15 +108,16 @@
  currentId.value = row.id;
  getList()
}
const paginationSearch = (obj) => {
const pagination = (obj) => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
};
const getList = () => {
  qualityInspectFileListPage({inspectId: currentId.value, ...page}).then(res => {
    tableData.value = res.data.records;
        total.value = res.data.total;
        page.total = res.data.total;
  })
}
// è¡¨æ ¼é€‰æ‹©æ•°æ®
src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -157,7 +157,7 @@
    label: "操作",
    align: "center",
    fixed: "right",
    width: 280,
    width: 300,
    operation: [
      {
        name: "编辑",
src/views/reportAnalysis/dataDashboard/index.vue
@@ -54,7 +54,7 @@
        <!-- è´¨é‡ç»Ÿè®¡ -->
                <div class="panel-header">
                    <span class="panel-title">质量统计</span>
                    <span class="panel-title">近4月质量统计</span>
                </div>
                <div class="main-panel">
                    <div class="panel-item-customers">
@@ -174,7 +174,7 @@
        </div>
                
                <div class="financial-header">
                    <span class="financial-title">财务分析</span>
                    <span class="financial-title">近4月财务分析</span>
                </div>
                <div class="main-panel">
                    <div class="panel-item-customers">
@@ -205,11 +205,11 @@
                <div class="panel-item-customers">
                    <div style="display: flex;justify-content: space-between;margin-bottom: 20px;">
                        <div class="section-title">应收应付统计</div>
                        <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group">
                            <el-radio-button label="按周" :value="1" />
                            <el-radio-button label="按月" :value="2" />
                            <el-radio-button label="按季度" :value="3" />
                        </el-radio-group>
<!--                        <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group">-->
<!--                            <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"
@@ -226,7 +226,7 @@
        <!-- å›žæ¬¾ä¸Žå¼€ç¥¨åˆ†æž -->
         <div class="panel-header">
                    <span class="panel-title">回款与开票分析</span>
                    <span class="panel-title">近一月回款与开票分析</span>
                </div>
        <div class="panel-item-customers" style="padding-top: 60px;">
                    <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries"
@@ -412,7 +412,7 @@
const barLegend = {
    show: true,
    textStyle: { color: '#B8C8E0' },
    data: ['原材料不合格数', '过程不合格数', '出厂不合格数']
    data: ['原材料合格数', '过程合格数', '出不合格数']
}
const barLegend1 = {
    show: true,
@@ -487,7 +487,7 @@
])
const barSeries1 = ref([
    {
        name: '原材料不合格数',
        name: '原材料合格数',
        type: 'bar',
        barGap: 0,
        emphasis: {
@@ -509,7 +509,7 @@
        data: []
    },
    {
        name: '过程不合格数',
        name: '过程合格数',
        type: 'bar',
        emphasis: {
            focus: 'series'
@@ -530,7 +530,7 @@
        data: []
    },
    {
        name: '出厂不合格数',
        name: '出厂合格数',
        type: 'bar',
        emphasis: {
            focus: 'series'
@@ -672,10 +672,10 @@
    getLedgerPage(params).then((res) => {
        equipmentNum.value = res.data.total
    });
    getRepairPage(params).then((res) => {
    getRepairPage({...params, status:0}).then((res) => {
        equipmentRepair.value = res.data.total
    });
    getUpkeepPage(params).then((res) => {
    getUpkeepPage({...params, status:0}).then((res) => {
        equipmentMaintain.value = res.data.total
    });
    measuringInstrumentListPage(params).then((res) => {
@@ -920,7 +920,7 @@
  // ä½¿ç”¨nextTick确保DOM完全渲染后再初始化图表
  nextTick(() => {
    // åˆå§‹åŒ–autofit自适应
    autofit.init({ dh: 1080, dw: 1920, el: '.data-dashboard', resize: true }, false)
    autofit.init({ dh: 800, dw: 1280, el: '.data-dashboard', resize: true }, false)
    
    // æ·»åŠ è‡ªåŠ¨æ»šåŠ¨åŠ¨ç”»æ•ˆæžœ - å®¢æˆ·ä¿¡æ¯åˆ—表
    const contractList = refContractList.value
src/views/reportAnalysis/projectProfit/index.vue
@@ -64,11 +64,11 @@
      align: "center",
      prop: "customerName",
    },
    {
      label: "项目名称",
      align: "center",
      prop: "projectName",
    },
    // {
    //   label: "项目名称",
    //   align: "center",
    //   prop: "projectName",
    // },
    {
      label: "合同金额",
      align: "center",
src/views/salesManagement/indicatorStats/index.vue
@@ -224,6 +224,10 @@
}
onMounted(() => {
  // è®¾ç½®æŒ‡æ ‡ç­›é€‰æ—¥æœŸèŒƒå›´é»˜è®¤å€¼ä¸ºå½“天
  const today = dayjs().format('YYYY-MM-DD')
  indicatorFilter.dateRange = [today, today]
  nextTick(() => initIndicatorChart())
})
</script>
src/views/salesManagement/invoiceLedger/fileList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
<template>
  <el-dialog v-model="dialogVisible" title="附件" width="40%" :before-close="handleClose">
    <el-table :data="tableData" border height="40vh">
      <el-table-column label="附件名称" prop="name" min-width="400" show-overflow-tooltip />
      <el-table-column fixed="right" label="操作" width="150" align="center">
        <template #default="scope">
          <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">下载</el-button>
          <el-button link type="primary" size="small" @click="lookFile(scope.row)">预览</el-button>
          <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-dialog>
  <filePreview ref="filePreviewRef" />
</template>
<script setup>
import { ref } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import filePreview from '@/components/filePreview/index.vue'
import { delCommonFileInvoiceLedger} from '@/api/publicApi/commonFile.js'
const dialogVisible = ref(false)
const tableData = ref([])
const { proxy } = getCurrentInstance();
const filePreviewRef = ref()
const handleClose = () => {
  dialogVisible.value = false
}
const open = (list) => {
  dialogVisible.value = true
  tableData.value = list
}
const downLoadFile = (row) => {
  proxy.$download.name(row.url);
}
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
}
// åˆ é™¤é™„ä»¶
const handleDelete = (row) => {
  ElMessageBox.confirm(`确认删除附件"${row.name}"吗?`, '删除确认', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
        delCommonFileInvoiceLedger([row.id]).then(() => {
      ElMessage.success('删除成功')
      // ä»Žåˆ—表中移除已删除的附件
      const index = tableData.value.findIndex(item => item.id === row.id)
      if (index !== -1) {
        tableData.value.splice(index, 1)
      }
    }).catch(() => {
      ElMessage.error('删除失败')
    })
  }).catch(() => {
    proxy.$modal.msg('已取消删除')
  })
}
defineExpose({
  open
})
</script>
<style></style>
src/views/salesManagement/invoiceLedger/index.vue
@@ -31,9 +31,8 @@
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="销售合同号" prop="salesContractNo" show-overflow-tooltip width="180" />
        <el-table-column label="客户合同号" prop="customerContractNo" show-overflow-tooltip width="180" />
        <el-table-column label="客户名称" prop="customerName" show-overflow-tooltip width="240" />
        <el-table-column label="项目" prop="projectName" width="320" />
<!--        <el-table-column label="项目" prop="projectName" width="320" />-->
        <el-table-column label="产品大类" prop="productCategory" width="200" />
        <el-table-column label="规格型号" prop="specificationModel" width="160" show-overflow-tooltip />
        <el-table-column label="发票号" prop="invoiceNo" width="200" show-overflow-tooltip />
@@ -43,21 +42,22 @@
        <el-table-column label="录入人" prop="invoicePerson" show-overflow-tooltip />
        <el-table-column label="录入日期" prop="createTime" show-overflow-tooltip :formatter="formatDate" width="180" />
        <el-table-column label="开票日期" prop="invoiceDate" show-overflow-tooltip width="120" />
        <el-table-column label="发票" prop="invoiceFileName" width="120" align="center" show-overflow-tooltip fixed="right">
        <!-- <el-table-column label="发票" prop="invoiceFileName" width="120" align="center" show-overflow-tooltip fixed="right">
          <template #default="scope">
            <el-button v-if="scope.row.invoiceFileName" text bg type="primary"
              @click="handleFile(scope.row.commonFiles)">
              æŸ¥çœ‹é™„ä»¶
            </el-button>
            <el-button v-else link type="primary" @click="handleDownload(scope.row)" :disabled="scope.row.invoicePerson !== userStore.nickName">
            <el-button v-else link type="primary" @click="handleDownload(scope.row)">
              ä¸Šä¼ 
            </el-button>
          </template>
        </el-table-column>
        </el-table-column> -->
        <el-table-column fixed="right" label="操作" width="150" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="openForm(scope.row)" :disabled="scope.row.invoicePerson !== userStore.nickName">编辑</el-button>
            <el-button link type="primary" size="small" @click="delInvoiceLedger(scope.row)" :disabled="scope.row.invoicePerson !== userStore.nickName">删除</el-button>
            <el-button link type="primary" size="small" @click="openForm(scope.row)">编辑</el-button>
            <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">附件</el-button>
            <el-button link type="primary" size="small" @click="delInvoiceLedger(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -108,7 +108,7 @@
            <el-form-item label="附件材料:" prop="remark">
              <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
                :headers="upload.headers" accept=".pdf" :limit="10" :before-upload="handleBeforeUpload"
                :on-error="handleUploadError" :on-success="handleUploadSuccess" :on-remove="handleRemove">
                :on-error="handleUploadError" :on-success="handleUploadSuccess">
                <el-button type="primary">上传</el-button>
                <template #tip>
                  <!--                  æ–‡ä»¶æ ¼å¼æ”¯æŒ doc,docx,xls,xlsx,ppt,pptx,pdf,txt,xml,jpg,jpeg,png,gif,bmp,rar,zip,7z-->
@@ -149,6 +149,7 @@
        </div>
      </template>
    </el-dialog>
    <FileList ref="fileListRef" />
  </div>
</template>
@@ -164,10 +165,11 @@
  commitFile,
  registrationProductPage,
  delInvoiceLedgerByRegProductId,
} from "../../../api/salesManagement/invoiceLedger.js";
} from "@/api/salesManagement/invoiceLedger.js";
import useUserStore from "@/store/modules/user.js";
import useFormData from "@/hooks/useFormData";
import dayjs from "dayjs";
import FileList from "./fileList.vue";
const { proxy } = getCurrentInstance();
const tableData = ref([]);
@@ -245,7 +247,11 @@
const getList = () => {
  tableLoading.value = true;
  const { invoiceDate, ...rest } = searchForm;
  registrationProductPage({ ...rest, ...page }).then((res) => {
  // å°†èŒƒå›´æ—¥æœŸå­—段传递给后端
  const params = { ...rest, ...page };
  // ç§»é™¤å¼€ç¥¨æ—¥æœŸçš„默认值设置,只保留范围日期字段
  delete params.invoiceDate;
  registrationProductPage(params).then((res) => {
    tableLoading.value = false;
    tableData.value = res.data.records;
    total.value = res.data.total;
@@ -272,13 +278,15 @@
  invoiceLedgerProductInfo({ id: row.id }).then((res) => {
    form.value = { ...res.data };
    fileList.value = res.data.fileList;
    // ä¿å­˜ticketRegistrationId到表单数据中
    if (row.ticketRegistrationId) {
      form.value.ticketRegistrationId = row.ticketRegistrationId;
    }
    if (!form.value.invoicePerson) {
      form.value.invoicePerson = userStore.nickName;
      form.value.entryDate = getCurrentDate();
      // ç§»é™¤å½•入日期默认值设置,只处理范围日期字段
    }
    if (!form.value.invoiceDate) {
      form.value.invoiceDate = getCurrentDate();
    }
    // ç§»é™¤å¼€ç¥¨æ—¥æœŸé»˜è®¤å€¼è®¾ç½®ï¼Œåªå¤„理范围日期字段
  });
  dialogFormVisible.value = true;
};
@@ -291,7 +299,6 @@
};
// ä¸Šä¼ å‰æ ¡æ£€
function handleBeforeUpload(file) {
  console.log("file", file);
  // æ ¡æ£€æ–‡ä»¶å¤§å°
  if (file.size > 1024 * 1024 * 10) {
    proxy.$modal.msgError("上传文件大小不能超过10MB!");
@@ -303,6 +310,7 @@
    proxy.$modal.msgError("文件格式不匹配");
    return false;
  }
  console.log('handleBeforeUpload');
  proxy.$modal.loading("正在上传文件,请稍候...");
  return true;
}
@@ -314,20 +322,27 @@
// ä¸Šä¼ æˆåŠŸå›žè°ƒ
function handleUploadSuccess(res, file, uploadFiles) {
  proxy.$modal.closeLoading();
  console.log('handleUploadSuccess');
  if (res.code === 200) {
    proxy.$refs["fileUpload"].handleRemove(file);
    fileList.value.push(res.data);
    proxy.$modal.msgSuccess("上传成功");
    // å°†ä¸Šä¼ æˆåŠŸçš„æ–‡ä»¶ä¿¡æ¯æ·»åŠ åˆ°fileList中
    const fileInfo = {
      name: file.name,
      url: res.data.url || file.response?.data?.url || file.url,
      response: file.response
    };
    // æ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨ç›¸åŒæ–‡ä»¶ï¼Œé¿å…é‡å¤æ·»åŠ 
    const existingFileIndex = fileList.value.findIndex(f => f.name === fileInfo.name);
    if (existingFileIndex === -1) {
      fileList.value.push(fileInfo);
    } else {
      fileList.value[existingFileIndex] = fileInfo;
    }
    // ç¡®ä¿è¡¨å•数据中的fileList也更新
    form.value.fileList = fileList.value;
  } else {
    proxy.$modal.msgError(res.msg);
    proxy.$refs.fileUpload.handleRemove(file);
  }
}
// ç§»é™¤æ–‡ä»¶
function handleRemove(file) {
  let index = fileList.value.findIndex((item) => item.url === file.url);
  if (index > -1) {
    fileList.value.splice(index, 1);
  }
}
// æäº¤è¡¨å•
@@ -361,13 +376,6 @@
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
// æ‰“开附件上传弹窗
const handleDownload = (val) => {
  fileList.value = [];
  uploadModal.value = true;
  currentId.value = val.id;
};
// ç¡®è®¤æ–‡ä»¶ä¸Šä¼ 
@@ -433,7 +441,22 @@
  getList();
};
//附件相关
const fileListRef = ref(null)
//查看附件
const downLoadFile = (row) => {
    invoiceLedgerProductInfo({ id: row.id }).then((res) => {
        fileListRef.value.open(res.data.fileList)
    });
}
onMounted(() => {
  // è®¾ç½®å¼€ç¥¨æ—¥æœŸèŒƒå›´é»˜è®¤å€¼ä¸ºå½“天
  const today = dayjs().format('YYYY-MM-DD');
  searchForm.invoiceDate = [today, today];
  // è®¾ç½®èŒƒå›´æ—¥æœŸå­—段的起始和结束时间
  searchForm.invoiceDateStart = today;
  searchForm.invoiceDateEnd = today;
  getList();
});
</script>
src/views/salesManagement/invoiceRegistration/index.vue
@@ -1,406 +1,378 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :inline="true" :model="searchForm">
        <el-form-item label="客户名称">
          <el-input
            v-model="searchForm.customerName"
            style="width: 240px"
            placeholder="请输入名称搜索"
            clearable
            :prefix-icon="Search"
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item label="客户合同号">
          <el-input
            v-model="searchForm.customerContractNo"
            placeholder="请输入客户合同号"
            clearable
          />
        </el-form-item>
        <el-form-item label="项目名称">
          <el-input
            v-model="searchForm.projectName"
            placeholder="请输入项目名称"
            clearable
          />
        </el-form-item>
        <el-form-item>
          <el-checkbox
            v-model="searchForm.status"
            label="不显示未开票金额为0"
            @change="handleQuery"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery"> æœç´¢ </el-button>
          <el-button @click="resetForm"> é‡ç½® </el-button>
          <el-button @click="handleExport" style="margin-right: 10px">导出</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="table_list">
      <div class="flex justify-between">
        <div></div>
        <div>
        <el-button type="primary" @click="openForm" style="margin-bottom: 8px">
          æ–°å¢žç™»è®°
        </el-button>
        </div>
      </div>
      <el-table
        :data="tableData"
        :border="true"
        height="calc(100vh - 21em)"
        v-loading="tableLoading"
        :expand-row-keys="expandedRowKeys"
        :row-key="(row) => row.id"
        show-summary
        :summary-method="summarizeMainTable"
        @expand-change="expandChange"
        @selection-change="handleSelectionChange"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column type="expand">
          <template #default="props">
            <el-table
              :data="props.row.children"
              border
              show-summary
              :summary-method="summarizeChildrenTable"
            >
              <el-table-column
                align="center"
                label="序号"
                type="index"
                width="60"
              />
              <el-table-column label="产品大类" prop="productCategory" />
              <el-table-column
                label="规格型号"
                prop="specificationModel"
                width="150"
              />
              <el-table-column label="单位" prop="unit" width="70" />
              <el-table-column label="数量" prop="quantity" width="70" />
              <el-table-column label="税率(%)" prop="taxRate" width="80" />
              <el-table-column
                label="含税单价(元)"
                prop="taxInclusiveUnitPrice"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="含税总价(元)"
                prop="taxInclusiveTotalPrice"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="不含税总价(元)"
                prop="taxExclusiveTotalPrice"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="开票数"
                prop="invoiceNum"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="开票金额(元)"
                prop="invoiceAmount"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="未开票数"
                prop="noInvoiceNum"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="未开票金额(元)"
                prop="noInvoiceAmount"
                :formatter="formattedNumber"
              />
            </el-table>
          </template>
        </el-table-column>
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column
          label="销售合同号"
          prop="salesContractNo"
          show-overflow-tooltip
          width="200"
        />
        <el-table-column
          label="客户合同号"
          prop="customerContractNo"
          width="200"
          show-overflow-tooltip
        />
        <el-table-column
          label="客户名称"
          prop="customerName"
          show-overflow-tooltip
          width="240"
        />
        <el-table-column label="业务员" prop="salesman" show-overflow-tooltip width="90"/>
        <el-table-column
          label="项目名称"
          prop="projectName"
          show-overflow-tooltip
          width="200"
        />
        <el-table-column
          label="合同金额(元)"
          prop="contractAmount"
          show-overflow-tooltip
          :formatter="formattedNumber"
                    width="220"
        />
        <el-table-column
          label="已开票金额(元)"
          prop="invoiceTotal"
          show-overflow-tooltip
          :formatter="formattedNumber"
          width="120"
        />
        <el-table-column
          label="未开票金额(元)"
          prop="noInvoiceAmountTotal"
          show-overflow-tooltip
          width="120"
        >
          <template #default="{ row, column }">
            <el-text type="danger">
              {{ formattedNumber(row, column, row.noInvoiceAmountTotal) }}
            </el-text>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
    <el-dialog
      v-model="dialogFormVisible"
      title="新增开票登记页面"
      width="85%"
      @close="closeDia"
    >
      <el-form
        :model="form"
        label-width="140px"
        label-position="top"
        :rules="rules"
        ref="formRef"
      >
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="销售合同号:" prop="salesContractNo">
              <el-input v-model="form.salesContractNo" disabled></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户名称:" prop="customerName">
              <el-input
                v-model="form.customerName"
                placeholder="自动填充"
                disabled
              ></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="业务员:" prop="salesman">
              <el-input
                v-model="form.salesman"
                placeholder="自动填充"
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="项目名称:" prop="projectName">
              <el-input
                v-model="form.projectName"
                placeholder="自动填充"
                disabled
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入人" prop="createUer">
              <el-input v-model="form.createUer" placeholder="请输入录入人" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="开票日期" prop="issueDate">
              <el-date-picker
                style="width: 100%"
                v-model="form.issueDate"
                type="date"
                placeholder="请选择"
                clearable
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入日期:" prop="createTime">
              <el-date-picker
                style="width: 100%"
                v-model="form.createTime"
                type="date"
                placeholder="请选择"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="发票号码:" prop="invoiceNo">
              <el-input
                v-model="form.invoiceNo"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-form-item label="产品信息:" prop="entryDate"> </el-form-item>
        </el-row>
        <el-table
          :data="productData"
          border
          show-summary
          :summary-method="summarizeChildrenTable"
        >
          <el-table-column
            align="center"
            label="序号"
            type="index"
            width="60"
          />
          <el-table-column label="产品大类" prop="productCategory" />
          <el-table-column
            label="规格型号"
            prop="specificationModel"
            width="150"
          />
          <el-table-column label="单位" prop="unit" />
          <el-table-column label="数量" prop="quantity" width="70" />
          <el-table-column label="税率(%)" prop="taxRate" width="80" />
          <el-table-column
            label="含税单价(元)"
            prop="taxInclusiveUnitPrice"
            :formatter="formattedNumber"
    <div class="app-container">
        <div class="search_form">
            <el-form :inline="true" :model="searchForm">
                <el-form-item label="客户名称">
                    <el-input
                        v-model="searchForm.customerName"
                        style="width: 240px"
                        placeholder="请输入名称搜索"
                        clearable
                        :prefix-icon="Search"
                        @change="handleQuery"
                    />
                </el-form-item>
                <el-form-item>
                    <el-checkbox
                        v-model="searchForm.status"
                        label="不显示未开票金额为0"
                        @change="handleQuery"
                    />
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="handleQuery"> æœç´¢ </el-button>
                    <el-button @click="resetForm"> é‡ç½® </el-button>
                    <el-button @click="handleExport" style="margin-right: 10px">导出</el-button>
                </el-form-item>
            </el-form>
        </div>
        <div class="table_list">
            <div class="flex justify-between">
                <div></div>
                <div>
                    <el-button type="primary" @click="openForm" style="margin-bottom: 8px">
                        æ–°å¢žç™»è®°
                    </el-button>
                </div>
            </div>
            <el-table
                :data="tableData"
                :border="true"
                height="calc(100vh - 21em)"
                v-loading="tableLoading"
                :expand-row-keys="expandedRowKeys"
                :row-key="(row) => row.id"
                show-summary
                :summary-method="summarizeMainTable"
                @expand-change="expandChange"
                @selection-change="handleSelectionChange"
            >
                <el-table-column align="center" type="selection" width="55" />
                <el-table-column type="expand">
                    <template #default="props">
                        <el-table
                            :data="props.row.children"
                            border
                            show-summary
                            :summary-method="summarizeChildrenTable"
                        >
                            <el-table-column
                                align="center"
                                label="序号"
                                type="index"
                                width="60"
                            />
                            <el-table-column label="产品大类" prop="productCategory" />
                            <el-table-column
                                label="规格型号"
                                prop="specificationModel"
                                width="150"
                            />
                            <el-table-column label="单位" prop="unit" width="70" />
                            <el-table-column label="数量" prop="quantity" width="70" />
                            <el-table-column label="税率(%)" prop="taxRate" width="80" />
                            <el-table-column
                                label="含税单价(元)"
                                prop="taxInclusiveUnitPrice"
                                :formatter="formattedNumber"
                            />
                            <el-table-column
                                label="含税总价(元)"
                                prop="taxInclusiveTotalPrice"
                                :formatter="formattedNumber"
                            />
                            <el-table-column
                                label="不含税总价(元)"
                                prop="taxExclusiveTotalPrice"
                                :formatter="formattedNumber"
                            />
                            <el-table-column
                                label="开票数"
                                prop="invoiceNum"
                                :formatter="formattedNumber"
                            />
                            <el-table-column
                                label="开票金额(元)"
                                prop="invoiceAmount"
                                :formatter="formattedNumber"
                            />
                            <el-table-column
                                label="未开票数"
                                prop="noInvoiceNum"
                                :formatter="formattedNumber"
                            />
                            <el-table-column
                                label="未开票金额(元)"
                                prop="noInvoiceAmount"
                                :formatter="formattedNumber"
                            />
                        </el-table>
                    </template>
                </el-table-column>
                <el-table-column align="center" label="序号" type="index" width="60" />
                <el-table-column
                    label="销售合同号"
                    prop="salesContractNo"
                    show-overflow-tooltip
                />
<!--                <el-table-column-->
<!--                    label="客户合同号"-->
<!--                    prop="customerContractNo"-->
<!--                    width="200"-->
<!--                    show-overflow-tooltip-->
<!--                />-->
                <el-table-column
                    label="客户名称"
                    prop="customerName"
                    show-overflow-tooltip
                />
                <el-table-column label="业务员" prop="salesman" show-overflow-tooltip/>
                <el-table-column
                    label="合同金额(元)"
                    prop="contractAmount"
                    show-overflow-tooltip
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="已开票金额(元)"
                    prop="invoiceTotal"
                    show-overflow-tooltip
                    :formatter="formattedNumber"
                />
                <el-table-column
                    label="未开票金额(元)"
                    prop="noInvoiceAmountTotal"
                    show-overflow-tooltip
                    width="120"
                >
                    <template #default="{ row, column }">
                        <el-text type="danger">
                            {{ formattedNumber(row, column, row.noInvoiceAmountTotal) }}
                        </el-text>
                    </template>
                </el-table-column>
            </el-table>
            <pagination
                v-show="total > 0"
                :total="total"
                layout="total, sizes, prev, pager, next, jumper"
                :page="page.current"
                :limit="page.size"
                @pagination="paginationChange"
            />
        </div>
        <el-dialog
            v-model="dialogFormVisible"
            title="新增开票登记页面"
            width="85%"
            @close="closeDia"
        >
            <el-form
                :model="form"
                label-width="140px"
                label-position="top"
                :rules="rules"
                ref="formRef"
            >
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="销售合同号:" prop="salesContractNo">
                            <el-input v-model="form.salesContractNo" disabled placeholder="多合同批量处理(具体合同号见产品列表)"></el-input>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="客户名称:" prop="customerName">
                            <el-input
                                v-model="form.customerName"
                                placeholder="自动填充"
                                disabled
                            ></el-input>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="业务员:" prop="salesman">
                            <el-input
                                v-model="form.salesman"
                                placeholder="自动填充"
                                disabled
                            />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="录入人" prop="createUer">
                            <el-input v-model="form.createUer" placeholder="请输入录入人" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="开票日期" prop="issueDate">
                            <el-date-picker
                                style="width: 100%"
                                v-model="form.issueDate"
                                type="date"
                                placeholder="请选择"
                                clearable
                                format="YYYY-MM-DD"
                                value-format="YYYY-MM-DD"
                            />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="录入日期:" prop="createTime">
                            <el-date-picker
                                style="width: 100%"
                                v-model="form.createTime"
                                type="date"
                                placeholder="请选择"
                                clearable
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="发票号码:" prop="invoiceNo">
                            <el-input
                                v-model="form.invoiceNo"
                                placeholder="请输入"
                                clearable
                            />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-form-item label="产品信息:" prop="entryDate"> </el-form-item>
                </el-row>
                <el-table
                    :data="productData"
                    border
                    show-summary
                    :summary-method="summarizeChildrenTable"
                >
                    <el-table-column
                        align="center"
                        label="序号"
                        type="index"
                        width="60"
                    />
                    <el-table-column label="所属合同" prop="salesContractNo" width="200">
                        <template #default="{ row }">
                            <el-tag type="primary">{{ row.salesContractNo }}</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="产品大类" prop="productCategory" />
                    <el-table-column
                        label="规格型号"
                        prop="specificationModel"
                        width="150"
                    />
                    <el-table-column label="单位" prop="unit" />
                    <el-table-column label="数量" prop="quantity" width="70" />
                    <el-table-column label="税率(%)" prop="taxRate" width="80" />
                    <el-table-column
                        label="含税单价(元)"
                        prop="taxInclusiveUnitPrice"
                        :formatter="formattedNumber"
                        width="200"
          />
          <el-table-column
            label="含税总价(元)"
            prop="taxInclusiveTotalPrice"
            :formatter="formattedNumber"
                    />
                    <el-table-column
                        label="含税总价(元)"
                        prop="taxInclusiveTotalPrice"
                        :formatter="formattedNumber"
                        width="200"
          />
          <el-table-column
            label="不含税总价(元)"
            prop="taxExclusiveTotalPrice"
            :formatter="formattedNumber"
            width="150"
          />
          <el-table-column label="本次开票数" prop="currentInvoiceNum" width="180">
            <template #default="scope">
              <el-input-number :step="0.1" :min="0" style="width: 100%"
                    />
                    <el-table-column
                        label="不含税总价(元)"
                        prop="taxExclusiveTotalPrice"
                        :formatter="formattedNumber"
                        width="150"
                    />
                    <el-table-column label="本次开票数" prop="currentInvoiceNum" width="180">
                        <template #default="scope">
                            <el-input-number :step="0.1" :min="0" style="width: 100%"
                                                             :precision="2"
                v-model="scope.row.currentInvoiceNum"
                @change="invoiceNumBlur(scope.row)"
              ></el-input-number>
            </template>
          </el-table-column>
          <el-table-column
            label="本次开票金额(元)"
            prop="currentInvoiceAmount"
            width="180"
          >
            <template #default="scope">
              <el-input-number :step="0.01" :min="0" style="width: 100%"
                                                             v-model="scope.row.currentInvoiceNum"
                                                             @change="invoiceNumBlur(scope.row)"
                            ></el-input-number>
                        </template>
                    </el-table-column>
                    <el-table-column
                        label="本次开票金额(元)"
                        prop="currentInvoiceAmount"
                        width="180"
                    >
                        <template #default="scope">
                            <el-input-number :step="0.01" :min="0" style="width: 100%"
                                                             :precision="2"
                v-model="scope.row.currentInvoiceAmount"
                @change="invoiceAmountBlur(scope.row)"
              ></el-input-number>
            </template>
          </el-table-column>
          <el-table-column label="未开票数" prop="noInvoiceNum" width="120">
            <template #default="scope">
              <el-input
                type="number"
                min="0"
                disabled
                v-model="scope.row.noInvoiceNum"
              ></el-input>
            </template>
          </el-table-column>
          <el-table-column
            label="未开票金额(元)"
            prop="noInvoiceAmount"
            width="200"
          >
            <template #default="scope">
              <el-input
                type="number"
                min="0"
                disabled
                v-model="scope.row.noInvoiceAmount"
                :formatter="formattedInputNumber"
                :precision="2"
                :step="0.01"
              ></el-input>
            </template>
          </el-table-column>
          <el-table-column label="登记人" prop="register" width="100">
            <!-- <template #default="{ row }">
              <el-input
                v-model="row.register"
                placeholder="请输入登记人"
                disabled
              />
            </template> -->
          </el-table-column>
          <el-table-column label="登记日期" prop="registerDate" width="150">
            <!-- <template #default="{ row }">
              <el-date-picker
                style="width: 100%"
                v-model="row.registerDate"
                value-format="YYYY-MM-DD"
                format="YYYY-MM-DD"
                type="date"
                placeholder="请选择"
                clearable
                disabled
              />
            </template> -->
          </el-table-column>
        </el-table>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
                                                             v-model="scope.row.currentInvoiceAmount"
                                                             @change="invoiceAmountBlur(scope.row)"
                            ></el-input-number>
                        </template>
                    </el-table-column>
                    <el-table-column label="未开票数" prop="noInvoiceNum" width="120">
                        <template #default="scope">
                            <el-input
                                type="number"
                                min="0"
                                disabled
                                v-model="scope.row.noInvoiceNum"
                            ></el-input>
                        </template>
                    </el-table-column>
                    <el-table-column
                        label="未开票金额(元)"
                        prop="noInvoiceAmount"
                        width="200"
                    >
                        <template #default="scope">
                            <el-input
                                type="number"
                                min="0"
                                disabled
                                v-model="scope.row.noInvoiceAmount"
                                :formatter="formattedInputNumber"
                                :precision="2"
                                :step="0.01"
                            ></el-input>
                        </template>
                    </el-table-column>
                    <el-table-column label="登记人" prop="register" width="100">
                        <!-- <template #default="{ row }">
                            <el-input
                                v-model="row.register"
                                placeholder="请输入登记人"
                                disabled
                            />
                        </template> -->
                    </el-table-column>
                    <el-table-column label="登记日期" prop="registerDate" width="150">
                        <!-- <template #default="{ row }">
                            <el-date-picker
                                style="width: 100%"
                                v-model="row.registerDate"
                                value-format="YYYY-MM-DD"
                                format="YYYY-MM-DD"
                                type="date"
                                placeholder="请选择"
                                clearable
                                disabled
                            />
                        </template> -->
                    </el-table-column>
                </el-table>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitForm">确认</el-button>
                    <el-button @click="closeDia">取消</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>
<script setup>
@@ -410,9 +382,9 @@
import { ElMessageBox } from "element-plus";
// import {userListNoPage} from "@/api/system/user.js";
import {
  getSalesLedgerWithProducts,
  ledgerListPage,
  productList,
    getSalesLedgerWithProducts,
    ledgerListPage,
    productList,
} from "@/api/salesManagement/salesLedger.js";
import { invoiceRegistrationSave } from "@/api/salesManagement/invoiceRegistration.js";
import useFormData from "@/hooks/useFormData";
@@ -426,261 +398,377 @@
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
    current: 1,
    size: 100,
});
const total = ref(0);
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
const data = reactive({
  searchForm: {
    customerName: "",
    status: false,
    customerContractNo: undefined, // å®¢æˆ·åˆåŒå·
    projectName: undefined, // é¡¹ç›®åç§°
    createUer: undefined, // ç™»è®°äºº
    issueDate: undefined, // å¼€ç¥¨æ—¥æœŸ
    createTime: undefined, // å½•入日期:
  },
  form: {
    salesLedgerId: "",
    customerName: "",
    salesman: "",
    projectName: "",
    productData: [],
    invoiceNo: "",
    createUer: userStore.nickName,
    issueDate: dayjs().format("YYYY-MM-DD"),
  },
  rules: {
    salesLedgerId: [{ required: true, message: "请选择", trigger: "change" }],
    createUer: [{ required: true, message: "请选择", trigger: "blur" }],
    issueDate: [{ required: true, message: "请选择", trigger: "change" }],
    invoiceNo: [{ required: true, message: "请输入", trigger: "change" }],
    createTime: [{ required: true, message: "请选择", trigger: "change" }],
  },
    searchForm: {
        customerName: "",
        status: false,
        customerContractNo: undefined, // å®¢æˆ·åˆåŒå·
        projectName: undefined, // é¡¹ç›®åç§°
        createUer: undefined, // ç™»è®°äºº
        issueDate: undefined, // å¼€ç¥¨æ—¥æœŸ
        createTime: undefined, // å½•入日期:
        productCategory: "",
        isInvoice: 1
    },
    form: {
        salesLedgerId: "",
        customerName: "",
        salesman: "",
        projectName: "",
        productData: [],
        invoiceNo: "",
        createUer: userStore.nickName,
        issueDate: dayjs().format("YYYY-MM-DD"),
        selectedContractIds: [], // æ–°å¢žï¼šå­˜å‚¨æ‰€æœ‰é€‰ä¸­çš„合同ID
        isBatch: false // æ–°å¢žï¼šæ ‡è¯†æ˜¯å¦ä¸ºæ‰¹é‡æ“ä½œ
    },
    rules: {
        createUer: [{ required: true, message: "请选择", trigger: "blur" }],
        issueDate: [{ required: true, message: "请选择", trigger: "change" }],
        invoiceNo: [{ required: true, message: "请输入", trigger: "change" }],
        createTime: [{ required: true, message: "请选择", trigger: "change" }],
    },
});
const { form, rules } = toRefs(data);
const { form: searchForm, resetForm } = useFormData(data.searchForm);
const formattedNumber = (row, column, cellValue) => {
  if (cellValue == 0) {
    return parseFloat(cellValue).toFixed(2);
  }
  if (cellValue) {
    return parseFloat(cellValue).toFixed(2);
  } else {
    return cellValue;
  }
    if (cellValue == 0) {
        return parseFloat(cellValue).toFixed(2);
    }
    if (cellValue) {
        return parseFloat(cellValue).toFixed(2);
    } else {
        return cellValue;
    }
};
const formattedInputNumber = (value) => {
  return value ? parseFloat(value).toFixed(2) : 0;
    return value ? parseFloat(value).toFixed(2) : 0;
};
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
    page.current = 1;
    getList();
};
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
    page.current = obj.page;
    page.size = obj.limit;
    getList();
};
const getList = () => {
  tableLoading.value = true;
  ledgerListPage({ ...searchForm, ...page }).then((res) => {
    tableLoading.value = false;
    tableData.value = res.records;
    total.value = res.total;
    expandedRowKeys.value = [];
  });
    tableLoading.value = true;
    ledgerListPage({ ...searchForm, ...page }).then((res) => {
        tableLoading.value = false;
        tableData.value = res.records;
        total.value = res.total;
        expandedRowKeys.value = [];
    });
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  console.log("selection", selection);
  selectedRows.value = selection.filter(
    (item) => item.salesContractNo !== undefined
  );
    console.log("selection", selection);
    selectedRows.value = selection.filter(
        (item) => item.salesContractNo !== undefined
    );
};
const expandedRowKeys = ref([]);
// å±•开行
const expandChange = (row, expandedRows) => {
  if (expandedRows.length > 0) {
    expandedRowKeys.value = [];
    try {
      productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
        const index = tableData.value.findIndex((item) => item.id === row.id);
        if (index > -1) {
          tableData.value[index].children = res.data;
        }
        expandedRowKeys.value.push(row.id);
      });
    } catch (error) {
      console.log(error);
    }
  } else {
    expandedRowKeys.value = [];
  }
    if (expandedRows.length > 0) {
        expandedRowKeys.value = [];
        try {
            productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
                const index = tableData.value.findIndex((item) => item.id === row.id);
                if (index > -1) {
                    tableData.value[index].children = res.data;
                }
                expandedRowKeys.value.push(row.id);
            });
        } catch (error) {
            console.log(error);
        }
    } else {
        expandedRowKeys.value = [];
    }
};
// ä¸»è¡¨åˆè®¡æ–¹æ³•
const summarizeMainTable = (param) => {
  return proxy.summarizeTable(param, [
    "contractAmount",
    "invoiceTotal",
    "noInvoiceAmountTotal",
  ]);
    return proxy.summarizeTable(param, [
        "contractAmount",
        "invoiceTotal",
        "noInvoiceAmountTotal",
    ]);
};
// å­è¡¨åˆè®¡æ–¹æ³•
const summarizeChildrenTable = (param) => {
  return proxy.summarizeTable(param, [
    "taxInclusiveUnitPrice",
    "taxInclusiveTotalPrice",
    "taxExclusiveTotalPrice",
    "invoiceNum",
    "invoiceAmount",
    "currentInvoiceAmount",
    "noInvoiceNum",
    "noInvoiceAmount",
    "currentInvoiceNum",
  ]);
    return proxy.summarizeTable(param, [
        "taxInclusiveUnitPrice",
        "taxInclusiveTotalPrice",
        "taxExclusiveTotalPrice",
        "invoiceNum",
        "invoiceAmount",
        "currentInvoiceAmount",
        "noInvoiceNum",
        "noInvoiceAmount",
        "currentInvoiceNum",
    ]);
};
// æ‰“开弹框
const openForm = () => {
  // åˆ¤æ–­æ˜¯å¦å¤šé€‰
  if (selectedRows.value.length != 1) {
    proxy.$modal.msgError("请选择一条合同");
    return;
  }
  form.value = {};
  productData.value = [];
  getSalesLedgerWithProducts({ id: selectedRows.value[0].id }).then((res) => {
    form.value = { ...res };
    form.value.createTime = dayjs().format("YYYY-MM-DD");
    form.value.issueDate = dayjs().format("YYYY-MM-DD");
    form.value.createUer = userStore.nickName;
    productData.value = form.value.productData.map((item) => {
      return item;
    });
    dialogFormVisible.value = true;
    console.log("productData.value ", productData.value);
  });
    // åˆ¤æ–­æ˜¯å¦é€‰æ‹©äº†åˆåŒ
    if (selectedRows.value.length === 0) {
        proxy.$modal.msgError("请至少选择一条合同");
        return;
    }
    // æ£€æŸ¥æ‰€æœ‰é€‰æ‹©çš„合同是否具有相同的客户名称
    const firstRow = selectedRows.value[0];
    const isSameCustomer = selectedRows.value.every(row =>
        row.customerName === firstRow.customerName
    );
    if (!isSameCustomer) {
        proxy.$modal.msgError("请选择相同客户名称的合同");
        return;
    }
    // å…è®¸ä¸åŒçš„销售合同号批量处理,无需检查重复
    form.value = {};
    productData.value = [];
    // åŠ è½½æ‰€æœ‰é€‰ä¸­åˆåŒçš„äº§å“æ•°æ®
    const promises = selectedRows.value.map(row =>
        getSalesLedgerWithProducts({ id: row.id })
    );
    Promise.all(promises).then(results => {
        // åˆå¹¶æ‰€æœ‰åˆåŒçš„产品数据,并为每个产品添加对应的合同信息
        const allProductData = [];
        results.forEach((result, index) => {
            const contract = selectedRows.value[index];
            const contractId = contract.id;
            if (result.productData) {
                result.productData.forEach(item => {
                    allProductData.push({
                        ...item,
                        id: contractId, // æ˜Žç¡®è®¾ç½®åˆåŒID
                        salesContractNo: contract.salesContractNo, // æ·»åŠ é”€å”®åˆåŒå·
                        customerName: contract.customerName, // æ·»åŠ å®¢æˆ·åç§°
                        customerContractNo: contract.customerContractNo // æ·»åŠ å®¢æˆ·åˆåŒå·
                    });
                });
            }
        });
        // è®¾ç½®è¡¨å•数据(使用第一个合同的基本信息,销售合同号留空)
        form.value = { ...results[0] };
        form.value.createTime = dayjs().format("YYYY-MM-DD");
        form.value.issueDate = dayjs().format("YYYY-MM-DD");
        form.value.createUer = userStore.nickName;
        form.value.selectedContractIds = selectedRows.value.map(row => row.id); // å­˜å‚¨æ‰€æœ‰é€‰ä¸­çš„合同ID
        form.value.salesContractNo = ""; // é”€å”®åˆåŒå·ç•™ç©ºï¼Œå› ä¸ºä¼šåœ¨äº§å“è¡¨æ ¼ä¸­åˆ†åˆ«æ˜¾ç¤º
        productData.value = allProductData;
        dialogFormVisible.value = true;
        console.log("productData.value ", productData.value);
    });
};
// æäº¤è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate((valid) => {
    if (valid) {
      form.value.productData = proxy.HaveJson(productData.value);
      invoiceRegistrationSave(form.value).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeDia();
        getList();
      });
    }
  });
    proxy.$refs["formRef"].validate((valid) => {
        if (valid) {
            // å¦‚果是批量操作,将所有合同的数据放在一个数组里,只调用一次接口
            if (selectedRows.value.length > 1) {
                // åˆ›å»ºåŒ…含所有合同数据的数组
                const batchData = selectedRows.value.map(contract => {
                    // ç­›é€‰å‡ºå±žäºŽå½“前合同的产品数据
                    const contractProductData = productData.value.filter(item =>
                        item.salesLedgerId === contract.id
                    );
                    // ä¸ºæ¯ä¸ªé”€å”®åˆåŒå·åˆ›å»ºç‹¬ç«‹çš„对象
                    return {
                        // åŸºç¡€è¡¨å•数据
                        issueDate: form.value.issueDate,
                        createTime: form.value.createTime,
                        createUer: form.value.createUer,
                        invoiceNo: form.value.invoiceNo,
                        // åˆåŒå®žé™…信息
                        id: contract.id, // ä½¿ç”¨id作为字段名,值为salesLedgerId
                        salesContractNo: contract.salesContractNo, // ä½¿ç”¨å®žé™…的销售合同号
                        customerName: contract.customerName, // ä½¿ç”¨å®žé™…的客户名称
                        customerId: contract.customerId, // æ·»åŠ å®¢æˆ·ID
                        customerContractNo: contract.customerContractNo, // ä½¿ç”¨å®žé™…的客户合同号
                        projectName: contract.projectName, // ä½¿ç”¨å®žé™…的项目名称
                        salesman: contract.salesman, // ä½¿ç”¨å®žé™…的业务员
                        // äº§å“æ•°æ®
                        productData: proxy.HaveJson(contractProductData),
                        // æ‰¹é‡æ ‡è¯†
                        isBatch: true
                    };
                });
                // åªè°ƒç”¨ä¸€æ¬¡æŽ¥å£ï¼Œä¼ é€’包含所有合同数据的数组
                invoiceRegistrationSave(batchData).then(() => {
                    proxy.$modal.msgSuccess("批量新增成功");
                    closeDia();
                    getList();
                });
            } else {
                // å•个合同提交逻辑 - ä¹Ÿä»¥æ•°ç»„形式传递
                const singleContract = selectedRows.value[0];
                const singleFormArray = [
                    {
                        // åŸºç¡€è¡¨å•数据
                        issueDate: form.value.issueDate,
                        createTime: form.value.createTime,
                        createUer: form.value.createUer,
                        invoiceNo: form.value.invoiceNo,
                        // åˆåŒå®žé™…信息
                        id: singleContract.id, // ä½¿ç”¨id作为字段名,值为salesLedgerId
                        salesContractNo: singleContract.salesContractNo, // ä½¿ç”¨å®žé™…的销售合同号
                        customerName: singleContract.customerName, // ä½¿ç”¨å®žé™…的客户名称
                        customerId: singleContract.customerId, // æ·»åŠ å®¢æˆ·ID
                        customerContractNo: singleContract.customerContractNo, // ä½¿ç”¨å®žé™…的客户合同号
                        projectName: singleContract.projectName, // ä½¿ç”¨å®žé™…的项目名称
                        salesman: singleContract.salesman, // ä½¿ç”¨å®žé™…的业务员
                        // äº§å“æ•°æ®
                        productData: proxy.HaveJson(productData.value),
                        // æ‰¹é‡æ ‡è¯†
                        isBatch: false
                    }
                ];
                invoiceRegistrationSave(singleFormArray).then((res) => {
                    proxy.$modal.msgSuccess("提交成功");
                    closeDia();
                    getList();
                });
            }
        }
    });
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
    proxy.resetForm("formRef");
    dialogFormVisible.value = false;
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      proxy.download("/invoiceRegistration/export", {}, "开票登记信息.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => {
            proxy.download("/invoiceRegistration/export", {}, "开票登记信息.xlsx");
        })
        .catch(() => {
            proxy.$modal.msg("已取消");
        });
};
// å¯¼å‡ºé”€å”®å°è´¦
const handleExport = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      proxy.download("/sales/ledger/exportOne", { ...searchForm, ...page }, "开票登记.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
    ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
        confirmButtonText: "确认",
        cancelButtonText: "取消",
        type: "warning",
    })
        .then(() => {
            proxy.download("/sales/ledger/exportOne", { ...searchForm, ...page }, "开票登记.xlsx");
        })
        .catch(() => {
            proxy.$modal.msg("已取消");
        });
};
//本次开票失焦操作
const invoiceNumBlur = (row) => {
  if (!row.currentInvoiceNum) {
    row.currentInvoiceNum = 0;
  }
  if (row.currentInvoiceNum > row.tempNoInvoiceNum) {
    proxy.$modal.msgWarning("本次开票数不得大于未开票数");
    row.currentInvoiceNum = 0;
  }
  // è®¡ç®—本次开票金额
  row.currentInvoiceAmount = (
    row.currentInvoiceNum * row.taxInclusiveUnitPrice
  ).toFixed(2);
  // è®¡ç®—未开票数
  row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
    2
  );
  // è®¡ç®—未开票金额
  row.noInvoiceAmount = (
    row.tempnoInvoiceAmount - row.currentInvoiceAmount
  ).toFixed(2);
    if (!row.currentInvoiceNum) {
        row.currentInvoiceNum = 0;
    }
    if (row.currentInvoiceNum > row.tempNoInvoiceNum) {
        proxy.$modal.msgWarning("本次开票数不得大于未开票数");
        row.currentInvoiceNum = 0;
    }
    // è®¡ç®—本次开票金额
    row.currentInvoiceAmount = (
        row.currentInvoiceNum * row.taxInclusiveUnitPrice
    ).toFixed(2);
    // è®¡ç®—未开票数
    row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
        2
    );
    // è®¡ç®—未开票金额
    row.noInvoiceAmount = (
        row.tempnoInvoiceAmount - row.currentInvoiceAmount
    ).toFixed(2);
};
// æœ¬æ¬¡å¼€ç¥¨é‡‘额失焦操作
const invoiceAmountBlur = (row) => {
  if (!row.currentInvoiceAmount) {
    row.currentInvoiceAmount = 0;
  }
  // è®¡ç®—是否超过开票总金额
  if (row.currentInvoiceAmount > row.tempnoInvoiceAmount) {
    proxy.$modal.msgWarning("本次开票金额不得大于未开票金额");
    row.currentInvoiceAmount = 0;
  }
  // è®¡ç®—本次开票数
  row.currentInvoiceNum = (
    row.currentInvoiceAmount / row.taxInclusiveUnitPrice
  ).toFixed(2);
  console.log("row.currentInvoiceNum ", row.currentInvoiceNum);
  console.log(" row.originalNoInvoiceNum  ", row.originalNoInvoiceNum);
  // è®¡ç®—未开票数
  row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
    2
  );
  // è®¡ç®—未开票金额
  row.noInvoiceAmount = (
    row.tempnoInvoiceAmount - row.currentInvoiceAmount
  ).toFixed(2);
    if (!row.currentInvoiceAmount) {
        row.currentInvoiceAmount = 0;
    }
    // è®¡ç®—是否超过开票总金额
    if (row.currentInvoiceAmount > row.tempnoInvoiceAmount) {
        proxy.$modal.msgWarning("本次开票金额不得大于未开票金额");
        row.currentInvoiceAmount = 0;
    }
    // è®¡ç®—本次开票数
    row.currentInvoiceNum = (
        row.currentInvoiceAmount / row.taxInclusiveUnitPrice
    ).toFixed(2);
    console.log("row.currentInvoiceNum ", row.currentInvoiceNum);
    console.log(" row.originalNoInvoiceNum  ", row.originalNoInvoiceNum);
    // è®¡ç®—未开票数
    row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed(
        2
    );
    // è®¡ç®—未开票金额
    row.noInvoiceAmount = (
        row.tempnoInvoiceAmount - row.currentInvoiceAmount
    ).toFixed(2);
};
onMounted(() => {
  getList();
    getList();
});
</script>
<style scoped lang="scss">
.table_list {
  margin-top: unset;
    margin-top: unset;
}
.flex {
  display: flex;
    display: flex;
}
.justify-between {
  justify-content: space-between;
    justify-content: space-between;
}
::v-deep(.el-checkbox__label) {
  font-weight: bold;
    font-weight: bold;
}
</style>
src/views/salesManagement/orderManagement/index.vue
@@ -59,7 +59,6 @@
            Â¥{{ scope.row.amount.toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column prop="paymentMethod" label="付款方式" width="120" />
        <el-table-column prop="status" label="订单状态" width="100">
          <template #default="scope">
            <el-tag :type="getStatusType(scope.row.status)">
@@ -131,15 +130,6 @@
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="付款方式" prop="paymentMethod">
              <el-select v-model="form.paymentMethod" placeholder="请选择付款方式" style="width: 100%">
                <el-option label="全款到付" value="全款到付"></el-option>
                <el-option label="分期付款" value="分期付款"></el-option>
                <el-option label="月结" value="月结"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="订单状态" prop="status">
              <el-select v-model="form.status" placeholder="请选择状态" style="width: 100%">
@@ -246,11 +236,10 @@
  {
    id: 1,
    orderNo: 'ORD202312001',
    customer: '上海科技有限公司',
    salesperson: '陈志强',
    customer: '广州科技公司',
    salesperson: '张三',
    orderDate: '2023-12-01',
    amount: 50000.00,
    paymentMethod: '全款到付',
    status: '待审核',
    remark: '重要客户订单'
  },
@@ -261,7 +250,6 @@
    salesperson: '刘雅婷',
    orderDate: '2023-12-02',
    amount: 35000.00,
    paymentMethod: '分期付款',
    status: '已审核',
    remark: '常规订单'
  },
@@ -272,7 +260,6 @@
    salesperson: '王建国',
    orderDate: '2023-12-03',
    amount: 28000.00,
    paymentMethod: '月结',
    status: '已发货',
    remark: '新客户订单'
  }
@@ -291,7 +278,6 @@
  salesperson: '',
  orderDate: '',
  amount: 0,
  paymentMethod: '',
  status: '待审核',
  remark: ''
})
@@ -301,7 +287,6 @@
  salesperson: [{ required: true, message: '请选择业务员', trigger: 'change' }],
  orderDate: [{ required: true, message: '请选择订单日期', trigger: 'change' }],
  amount: [{ required: true, message: '请输入订单金额', trigger: 'blur' }],
  paymentMethod: [{ required: true, message: '请选择付款方式', trigger: 'change' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
}
@@ -360,7 +345,6 @@
  form.salesperson = ''
  form.orderDate = ''
  form.amount = 0
  form.paymentMethod = ''
  form.status = '待审核'
  form.remark = ''
  dialogVisible.value = true
src/views/salesManagement/paymentShipping/index.vue
@@ -60,7 +60,6 @@
            Â¥{{ scope.row.paidAmount }}
          </template>
        </el-table-column>
        <el-table-column prop="paymentMethod" label="付款方式" width="120" />
        <el-table-column prop="paymentStatus" label="付款状态" width="100">
          <template #default="scope">
            <el-tag :type="getPaymentStatusType(scope.row.paymentStatus)">
@@ -120,15 +119,6 @@
          <el-col :span="12">
            <el-form-item label="订单金额" prop="orderAmount">
              <el-input-number v-model="form.orderAmount" :precision="2" :min="0" style="width: 100%"></el-input-number>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="付款方式" prop="paymentMethod">
              <el-select v-model="form.paymentMethod" placeholder="请选择付款方式" style="width: 100%">
                <el-option label="全款到付" value="全款到付"></el-option>
                <el-option label="分期付款" value="分期付款"></el-option>
                <el-option label="月结" value="月结"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
@@ -201,14 +191,6 @@
        </el-form-item>
        <el-form-item label="付款金额" prop="paymentAmount">
          <el-input-number v-model="paymentAmount" :precision="2" :min="0" :max="currentRecord.orderAmount" style="width: 100%"></el-input-number>
        </el-form-item>
        <el-form-item label="付款方式" prop="paymentMethod">
          <el-select v-model="paymentMethod" placeholder="请选择付款方式" style="width: 100%">
            <el-option label="现金" value="现金"></el-option>
            <el-option label="银行转账" value="银行转账"></el-option>
            <el-option label="支付宝" value="支付宝"></el-option>
            <el-option label="微信支付" value="微信支付"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="付款备注" prop="paymentRemark">
          <el-input type="textarea" v-model="paymentRemark" rows="3" placeholder="请输入付款备注"></el-input>
@@ -312,7 +294,6 @@
  orderNo: '',
  customer: '',
  orderAmount: 0,
  paymentMethod: '',
  paymentStatus: '未付款',
  shippingStatus: '待发货',
  shippingDate: '',
@@ -324,7 +305,6 @@
  // orderNo: [{ required: true, message: '请输入订单号', trigger: 'blur' }],
  customer: [{ required: true, message: '请选择客户', trigger: 'change' }],
  orderAmount: [{ required: true, message: '请输入订单金额', trigger: 'blur' }],
  paymentMethod: [{ required: true, message: '请选择付款方式', trigger: 'change' }],
  paymentStatus: [{ required: true, message: '请选择付款状态', trigger: 'change' }],
  shippingStatus: [{ required: true, message: '请选择发货状态', trigger: 'change' }]
}
@@ -335,7 +315,6 @@
const shippingDialogVisible = ref(false)
const currentRecord = ref({})
const paymentAmount = ref(0)
const paymentMethod = ref('')
const paymentRemark = ref('')
const shippingDate = ref('')
const logisticsCompany = ref('')
@@ -379,7 +358,6 @@
  form.orderNo = ''
  form.customer = ''
  form.orderAmount = 0
  form.paymentMethod = ''
  form.paymentStatus = '未付款'
  form.shippingStatus = '待发货'
  form.shippingDate = ''
@@ -404,7 +382,6 @@
const handlePayment = (row) => {
  currentRecord.value = row
  paymentAmount.value = row.orderAmount - row.paidAmount
  paymentMethod.value = ''
  paymentRemark.value = ''
  paymentDialogVisible.value = true
}
@@ -435,10 +412,6 @@
}
const savePayment = () => {
  if (!paymentMethod.value) {
    ElMessage.warning('请选择付款方式')
    return
  }
  currentRecord.value.paidAmount = Number(currentRecord.value.paidAmount) + paymentAmount.value
  if(currentRecord.value.paidAmount == currentRecord.value.orderAmount){
    currentRecord.value.paymentStatus = '已付款'
src/views/salesManagement/receiptPayment/index.vue
@@ -13,24 +13,6 @@
                prefix-icon="Search"
              />
            </el-form-item>
            <el-form-item label="客户合同号">
              <el-input
                v-model="searchForm.customerContractNo"
                placeholder="请输入"
                @change="handleQuery"
                clearable
                prefix-icon="Search"
              />
            </el-form-item>
            <el-form-item label="项目名称">
              <el-input
                v-model="searchForm.projectName"
                placeholder="请输入"
                @change="handleQuery"
                clearable
                prefix-icon="Search"
              />
            </el-form-item>
            <el-form-item>
              <el-checkbox
                v-model="searchForm.status"
@@ -122,7 +104,6 @@
                    size="small"
                    @click="changeEditType(scope.row)"
                    v-if="!scope.row.editType"
                                        :disabled="scope.row.registrant !== userStore.nickName"
                    >编辑</el-button
                  >
                  <el-button
@@ -131,7 +112,6 @@
                    size="small"
                    @click="saveReceiptPayment(scope.row)"
                    v-if="scope.row.editType"
                                        :disabled="scope.row.registrant !== userStore.nickName"
                    >保存</el-button
                  >
                  <el-button
@@ -139,7 +119,6 @@
                    type="primary"
                    size="small"
                    @click="delReceiptRecord(scope.row)"
                                        :disabled="scope.row.registrant !== userStore.nickName"
                    >删除</el-button
                  >
                </template>
@@ -155,23 +134,10 @@
          width="240"
        />
        <el-table-column
          label="客户合同号"
          prop="customerContractNo"
          show-overflow-tooltip
          width="240"
        />
        <el-table-column
          label="客户名称"
          prop="customerName"
          show-overflow-tooltip
          width="240"
        />
        <el-table-column
          label="项目名称"
          prop="projectName"
          show-overflow-tooltip
          width="340"
        />
        <el-table-column
          label="回款状态"
@@ -184,12 +150,12 @@
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="产品大类"
          prop="productCategory"
          show-overflow-tooltip
          width="100"
        />
<!--        <el-table-column-->
<!--          label="产品大类"-->
<!--          prop="productCategory"-->
<!--          show-overflow-tooltip-->
<!--          width="100"-->
<!--        />-->
        <el-table-column
          label="发票号"
          prop="invoiceNo"
@@ -349,7 +315,6 @@
                                v-model="form.registrant"
                                placeholder="请输入"
                                clearable
                                disabled
                            />
                        </el-form-item>
                    </el-col>
@@ -504,9 +469,7 @@
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  console.log("selection", selection);
  selectedRows.value = selection.filter(
    (item) => item.customerContractNo !== null
  );
  selectedRows.value = selection
};
// ä¸»è¡¨åˆè®¡æ–¹æ³•
const summarizeMainTable = (param) => {
src/views/salesManagement/receiptPaymentHistory/index.vue
@@ -10,24 +10,6 @@
          :prefix-icon="Search"
        />
      </el-form-item>
      <el-form-item label="客户合同号">
        <el-input
          v-model="searchForm.customerContractNo"
          placeholder="输入客户合同号"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
        />
      </el-form-item>
      <el-form-item label="项目名称">
        <el-input
          v-model="searchForm.projectName"
          placeholder="输入项目名称"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
        />
      </el-form-item>
      <el-form-item label="回款日期">
        <el-date-picker
          v-model="searchForm.receiptPaymentDate"
@@ -80,11 +62,6 @@
    width:240
  },
  {
    label: "客户合同号",
    prop: "customerContractNo",
    width:240
  },
  {
    label: "回款日期",
    prop: "receiptPaymentDate",
    width:100
@@ -93,11 +70,6 @@
    label: "客户名称",
    prop: "customerName",
    width:240
  },
  {
    label: "项目名称",
    prop: "projectName",
    width:200
  },
  {
    label: "回款金额(元)",
@@ -149,8 +121,6 @@
  receiptPaymentDate: [],
  receiptPaymentDateStart: undefined,
  receiptPaymentDateEnd: undefined,
  customerContractNo: undefined,
  projectName: undefined,
});
const { receipt_payment_type } = proxy.useDict("receipt_payment_type");
const isShowSummarySon = ref(true);
@@ -168,7 +138,11 @@
const getList = () => {
  tableLoading.value = true;
  const { receiptPaymentDate, ...rest } = searchForm;
  receiptPaymentHistoryListPage({ ...rest, ...page }).then((res) => {
  // å°†èŒƒå›´æ—¥æœŸå­—段传递给后端
  const params = { ...rest, ...page };
  // ç§»é™¤å›žæ¬¾æ—¥æœŸçš„默认值设置,只保留范围日期字段
  delete params.receiptPaymentDate;
  receiptPaymentHistoryListPage(params).then((res) => {
    tableLoading.value = false;
    tableData.value = res.records;
        page.total = res.total;
@@ -212,6 +186,12 @@
};
onMounted(() => {
  // è®¾ç½®å›žæ¬¾æ—¥æœŸèŒƒå›´é»˜è®¤å€¼ä¸ºå½“天
  const today = dayjs().format('YYYY-MM-DD');
  searchForm.receiptPaymentDate = [today, today];
  // è®¾ç½®èŒƒå›´æ—¥æœŸå­—段的起始和结束时间
  searchForm.receiptPaymentDateStart = dayjs(today).format('YYYY-MM-DD 00:00:00');
  searchForm.receiptPaymentDateEnd = dayjs(today).format('YYYY-MM-DD 23:59:59');
  getList();
});
</script>
src/views/salesManagement/salesLedger/fileList.vue
@@ -2,10 +2,11 @@
  <el-dialog v-model="dialogVisible" title="附件" width="40%" :before-close="handleClose">
    <el-table :data="tableData" border height="40vh">
      <el-table-column label="附件名称" prop="name" min-width="400" show-overflow-tooltip />
      <el-table-column fixed="right" label="操作" width="100" align="center">
      <el-table-column fixed="right" label="操作" width="150" align="center">
        <template #default="scope">
          <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">下载</el-button>
          <el-button link type="primary" size="small" @click="lookFile(scope.row)">预览</el-button>
          <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
@@ -15,7 +16,9 @@
<script setup>
import { ref } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import filePreview from '@/components/filePreview/index.vue'
import { delCommonFile } from '@/api/publicApi/commonFile.js'
const dialogVisible = ref(false)
const tableData = ref([])
@@ -35,6 +38,27 @@
const lookFile = (row) => {
  filePreviewRef.value.open(row.url)
}
// åˆ é™¤é™„ä»¶
const handleDelete = (row) => {
  ElMessageBox.confirm(`确认删除附件"${row.name}"吗?`, '删除确认', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    delCommonFile([row.id]).then(() => {
      ElMessage.success('删除成功')
      // ä»Žåˆ—表中移除已删除的附件
      const index = tableData.value.findIndex(item => item.id === row.id)
      if (index !== -1) {
        tableData.value.splice(index, 1)
      }
    }).catch(() => {
      ElMessage.error('删除失败')
    })
  }).catch(() => {
    proxy.$modal.msg('已取消删除')
  })
}
defineExpose({
  open
})
src/views/salesManagement/salesLedger/index.vue
@@ -6,16 +6,8 @@
          <el-input v-model="searchForm.customerName" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
        </el-form-item>
        <el-form-item label="客户合同号:">
          <el-input v-model="searchForm.customerContractNo" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
        </el-form-item>
        <el-form-item label="销售合同号:">
          <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
        </el-form-item>
        <el-form-item label="项目名称:">
          <el-input v-model="searchForm.projectName" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
        </el-form-item>
        <el-form-item label="录入日期:">
@@ -41,7 +33,7 @@
      </div>
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary style="width: 100%"
        :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)">
        :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 21em)">
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column type="expand">
          <template #default="props">
@@ -60,22 +52,28 @@
        </el-table-column>
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
        <el-table-column label="客户合同号" prop="customerContractNo" width="180" show-overflow-tooltip />
        <el-table-column label="客户名称" prop="customerName" width="300" show-overflow-tooltip />
        <el-table-column label="业务员" prop="salesman" width="100" show-overflow-tooltip />
        <el-table-column label="项目名称" prop="projectName" width="180" show-overflow-tooltip />
        <el-table-column label="付款方式" prop="paymentMethod" show-overflow-tooltip />
        <el-table-column label="合同金额(元)" prop="contractAmount" width="220" show-overflow-tooltip
          :formatter="formattedNumber" />
        <el-table-column label="录入人" prop="entryPersonName" width="100" show-overflow-tooltip />
        <el-table-column label="发货车牌" prop="shippingCarNumber" width="120" show-overflow-tooltip>
          <template #default="scope">
            <div>
              <div v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</div>
              <el-tag v-else type="warning">未发货</el-tag>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="发货日期" prop="shippingDate" width="120" show-overflow-tooltip />
        <el-table-column label="录入日期" prop="entryDate" width="120" show-overflow-tooltip />
        <el-table-column label="签订日期" prop="executionDate" width="120" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="200" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" :disabled="scope.row.invoiceTotal>0 || scope.row.entryPersonName !== userStore.nickName" @click="openForm('edit', scope.row)">编辑</el-button>
            <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">编辑</el-button>
<!--            <el-button link type="primary" size="small" @click="openForm('view', scope.row)">详情</el-button>-->
            <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">附件</el-button>
            <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">发货</el-button>
            <el-button v-if="!scope.row.shippingCarNumber" link type="primary" size="small" @click="openDeliveryForm(scope.row)">发货</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -93,7 +91,9 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="业务员:" prop="salesman">
              <el-select v-model="form.salesman" placeholder="请选择" clearable :disabled="operationType === 'view'">
              <el-select v-model="form.salesman"                 filterable
                         default-first-option
                         :reserve-keyword="false" placeholder="请选择" clearable :disabled="operationType === 'view'">
                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                  :value="item.nickName" />
              </el-select>
@@ -102,26 +102,14 @@
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="客户合同号:" prop="customerContractNo">
              <el-input v-model="form.customerContractNo" placeholder="请输入" clearable :disabled="operationType === 'view'"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="客户名称:" prop="customerId">
              <el-select v-model="form.customerId" placeholder="请选择" clearable :disabled="operationType === 'view'">
              <el-select v-model="form.customerId" placeholder="请选择" clearable :disabled="operationType === 'view'" filterable>
                <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
                  {{
                    item.customerName + "——" + item.taxpayerIdentificationNumber
                  }}
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="项目名称:" prop="projectName">
              <el-input v-model="form.projectName" placeholder="请输入" clearable :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
                    <el-col :span="12">
@@ -134,7 +122,9 @@
        <el-row :gutter="30">
                    <el-col :span="12">
                        <el-form-item label="录入人:" prop="entryPerson">
                            <el-select v-model="form.entryPerson" placeholder="请选择" clearable @change="changs" disabled>
                            <el-select v-model="form.entryPerson"                 filterable
                         default-first-option
                         :reserve-keyword="false" placeholder="请选择" clearable @change="changs">
                                <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
                            </el-select>
                        </el-form-item>
@@ -146,13 +136,7 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="付款方式">
              <el-input v-model="form.paymentMethod" placeholder="请输入" clearable :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-form-item label="产品信息:" prop="entryDate">
            <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">添加</el-button>
@@ -165,6 +149,7 @@
          <el-table-column align="center" label="序号" type="index" width="60" />
          <el-table-column label="产品大类" prop="productCategory" />
          <el-table-column label="规格型号" prop="specificationModel" />
          <el-table-column label="绑定机器" prop="speculativeTradingName" />
          <el-table-column label="单位" prop="unit" />
          <el-table-column label="数量" prop="quantity" />
          <el-table-column label="税率(%)" prop="taxRate" />
@@ -229,6 +214,13 @@
              <el-select v-model="productForm.productModelId" placeholder="请选择" clearable @change="getProductModel">
                <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="绑定机器:">
              <el-input v-model="productForm.speculativeTradingName" placeholder="请先选择规格型号" clearable disabled />
            </el-form-item>
          </el-col>
        </el-row>
@@ -317,7 +309,7 @@
                    <div v-for="(item, index) in printData" :key="index" class="print-page">
                        <div class="delivery-note">
                            <div class="header">
                                <div class="company-name">鼎诚瑞实业有限责任公司</div>
                                <div class="company-name">海川开心食品有限公司</div>
                                <div class="document-title">零售发货单</div>
                            </div>
                            
@@ -328,12 +320,15 @@
                                        <span class="value">{{ formatDate(item.createTime) }}</span>
                                    </div>
                                    <div>
                                        <span class="label">客户名称:</span>
                                        <span class="value">{{ item.customerName || '张爱有' }}</span>
                                        <span class="label">发货车牌号:</span>
                                        <span class="value">{{ item.shippingCarNumber }}</span>
                                    </div>
                                </div>
                                <div class="info-row">
                                    <div>
                                        <span class="label">客户名称:</span>
                                        <span class="value">{{ item.customerName || '张爱有' }}</span>
                                    </div>
                                    <span class="label">单号:</span>
                                    <span class="value">{{ item.salesContractNo }}</span>
                                </div>
@@ -434,11 +429,19 @@
                <el-row :gutter="30">
                    <el-col :span="24">
                        <el-form-item label="发货车牌号:" prop="shippingCarNumber">
                            <el-input
              <el-select v-model="deliveryForm.shippingCarNumber" filterable allow-create placeholder="请选择发货车牌号">
                <el-option key="1" label="新A H5153" value="新A H5153"/>
                <el-option key="2" label="新A H4232" value="新A H4232"/>
                <el-option key="3" label="新A H4001" value="新A H4001"/>
                <el-option key="4" label="新A H6409" value="新A H6409"/>
                <el-option key="5" label="新A G7446" value="新A G7446"/>
                <el-option key="6" label="新H 80369" value="新H 80369"/>
              </el-select>
                            <!-- <el-input
                                v-model="deliveryForm.shippingCarNumber"
                                placeholder="请输入发货车牌号"
                                clearable
                            />
                            /> -->
                        </el-form-item>
                    </el-col>
                </el-row>
@@ -502,9 +505,7 @@
const data = reactive({
  searchForm: {
    customerName: "", // å®¢æˆ·åç§°
    customerContractNo: "", // å®¢æˆ·åˆåŒç¼–号
    salesContractNo: "", // é”€å”®åˆåŒç¼–号
    projectName: "", // é¡¹ç›®åç§°
    entryDate: null, // å½•入日期
    entryDateStart: undefined,
    entryDateEnd: undefined,
@@ -512,23 +513,16 @@
  form: {
    salesContractNo: "",
    salesman: "",
    customerContractNo: "",
    customerId: "",
    projectName: "",
    entryPerson: "",
    entryDate: "",
    maintenanceTime: "",
    productData: [],
    executionDate: "",
    paymentMethod: "",
  },
  rules: {
    salesman: [{ required: true, message: "请选择", trigger: "change" }],
    customerContractNo: [
      { required: true, message: "请输入", trigger: "blur" },
    ],
    customerId: [{ required: true, message: "请选择", trigger: "change" }],
    projectName: [{ required: true, message: "请输入", trigger: "blur" }],
    entryPerson: [{ required: true, message: "请选择", trigger: "change" }],
    entryDate: [{ required: true, message: "请选择", trigger: "change" }],
    executionDate: [{ required: true, message: "请选择", trigger: "change" }],
@@ -551,6 +545,7 @@
    taxInclusiveTotalPrice: "",
    taxExclusiveTotalPrice: "",
    invoiceType: "",
    speculativeTradingName: "",
  },
  productRules: {
    productCategory: [{ required: true, message: "请选择", trigger: "change" }],
@@ -619,7 +614,11 @@
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  // åªæœ‰åœ¨ç‚¹å‡»æœç´¢æŒ‰é’®æ—¶æ‰é‡ç½®é¡µç åˆ°ç¬¬ä¸€é¡µ
  // é¿å…è¡¨å•字段change事件干扰分页
  if (arguments.length === 0) {
    page.current = 1;
  }
    expandedRowKeys.value = [];
  getList();
};
@@ -631,7 +630,11 @@
const getList = () => {
  tableLoading.value = true;
  const { entryDate, ...rest } = searchForm;
  ledgerListPage({ ...rest, ...page })
  // å°†èŒƒå›´æ—¥æœŸå­—段传递给后端
  const params = { ...rest, ...page };
  // ç§»é™¤å½•入日期的默认值设置,只保留范围日期字段
  delete params.entryDate;
  ledgerListPage(params)
    .then((res) => {
      tableLoading.value = false;
      tableData.value = res.records;
@@ -666,9 +669,11 @@
  if (index !== -1) {
    productForm.value.specificationModel = modelOptions.value[index].model;
    productForm.value.unit = modelOptions.value[index].unit;
    productForm.value.speculativeTradingName = modelOptions.value[index].speculativeTradingName || "";
  } else {
    productForm.value.specificationModel = null;
    productForm.value.unit = null;
    productForm.value.speculativeTradingName = "";
  }
};
const findNodeById = (nodes, productId) => {
@@ -770,7 +775,7 @@
  //     form.value.entryPerson = userAll.user.userId // è®¾ç½®é»˜è®¤ä¸šåŠ¡å‘˜ä¸ºå½“å‰ç”¨æˆ·
  //   }
  // });
  form.value.entryDate = getCurrentDate(); // è®¾ç½®é»˜è®¤å½•入日期为当前日期
  // ç§»é™¤å½•入日期默认值设置,只处理范围日期字段
  dialogFormVisible.value = true;
};
function changs(val) {
@@ -1166,7 +1171,7 @@
      <div class="print-page">
        <div class="delivery-note">
          <div class="header">
            <div class="company-name">鼎诚瑞实业有限责任公司</div>
            <div class="company-name">海川开心食品有限公司</div>
            <div class="document-title">零售发货单</div>
          </div>
          
@@ -1526,7 +1531,7 @@
const openDeliveryForm = (row) => {
  currentDeliveryRow.value = row;
  deliveryForm.value = {
    shippingDate: getCurrentDate(),
    shippingDate: "", // ç§»é™¤é»˜è®¤å€¼è®¾ç½®
    shippingCarNumber: "",
  };
  deliveryFormVisible.value = true;
@@ -1561,7 +1566,13 @@
};
onMounted(() => {
    getList();
  // è®¾ç½®å½•入日期范围默认值为当天
  const today = dayjs().format('YYYY-MM-DD');
  searchForm.entryDate = [today, today];
  // è®¾ç½®èŒƒå›´æ—¥æœŸå­—段的起始和结束时间
  searchForm.entryDateStart = today;
  searchForm.entryDateEnd = today;
  getList();
});
</script>
src/views/salesManagement/salesQuotation/index.vue
@@ -144,15 +144,6 @@
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="付款方式" prop="paymentMethod">
                <el-select v-model="form.paymentMethod" placeholder="请选择付款方式" style="width: 100%">
                  <el-option label="全款到付" value="全款到付"></el-option>
                  <el-option label="分期付款" value="分期付款"></el-option>
                  <el-option label="月结" value="月结"></el-option>
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="交货期" prop="deliveryPeriod">
                <el-date-picker
                  v-model="form.deliveryPeriod"
@@ -302,7 +293,6 @@
        <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="交货期">{{ currentQuotation.deliveryPeriod }}</el-descriptions-item>
<!--        <el-descriptions-item label="报价状态">-->
<!--          <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>-->
@@ -394,7 +384,6 @@
  salesperson: [{ required: true, message: '请选择业务员', trigger: 'change' }],
  quotationDate: [{ required: true, message: '请选择报价日期', trigger: 'change' }],
  validDate: [{ required: true, message: '请选择有效期', trigger: 'change' }],
  paymentMethod: [{ required: true, message: '请选择付款方式', trigger: 'change' }],
  deliveryPeriod: [{ required: true, message: '请选择交货期', trigger: 'change' }]
}
const userList = ref([]);
vite.config.js
@@ -8,7 +8,7 @@
  const { VITE_APP_ENV } = env;
  const baseUrl =
      env.VITE_APP_ENV === "development"
          ? "http://114.132.189.42:9036"
          ? "http://192.168.1.147:7003"
          : env.VITE_BASE_API;
  const javaUrl =
      env.VITE_APP_ENV === "development"