From 1ca5584d7e3200a9af65a099bd26d3593e2ba702 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期四, 07 五月 2026 14:36:08 +0800
Subject: [PATCH] 迁移pro

---
 src/main/java/com/ruoyi/production/bean/dto/ProductionPlanImportDto.java                                       |   81 
 src/main/java/com/ruoyi/warehouse/pojo/Warehouse.java                                                          |    7 
 src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java                                            |  296 
 src/main/java/com/ruoyi/measuringinstrumentledger/service/SparePartsRequisitionRecordService.java              |   19 
 src/main/java/com/ruoyi/common/utils/http/HttpUtils.java                                                       |   24 
 src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java                                                 |   20 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java                             |    1 
 src/main/java/com/ruoyi/common/utils/OrderUtils.java                                                           |  102 
 src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java                                      |   16 
 src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationParamController.java              |   62 
 src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceExeclDto.java                                   |   14 
 src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java                                                  |   22 
 src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java                                  |   75 
 src/main/java/com/ruoyi/production/service/ProductionOrderService.java                                         |   38 
 src/main/java/com/ruoyi/production/bean/dto/ProductionPlanSummaryDto.java                                      |   71 
 src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java                                     |   34 
 src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java                               |   59 
 src/main/java/com/ruoyi/ai/tools/ApproveTodoTools.java                                                         |  996 +
 src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java                                                   |   21 
 src/main/java/com/ruoyi/device/pojo/DeviceRepair.java                                                          |   49 
 src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java                                                   |    2 
 src/main/java/com/ruoyi/approve/utils/StartAndEndDateDto.java                                                  |   15 
 src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java                        |   31 
 src/main/java/com/ruoyi/account/controller/AccountExpenseController.java                                       |   33 
 src/main/java/com/ruoyi/project/system/domain/SysDictType.java                                                 |    6 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java                             |   20 
 src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java                                            |   19 
 src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java                                                 |    6 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java                             |   98 
 src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java                                            |   24 
 src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java                                     |    9 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java                            |   89 
 src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java                                           |   62 
 src/main/java/com/ruoyi/framework/config/ServerConfig.java                                                     |    2 
 src/main/java/com/ruoyi/ai/service/impl/AiChatSessionServiceImpl.java                                          |  191 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingRoom.java                                            |    3 
 src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceFileController.java                      |   15 
 src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java                                                       |   32 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationParamVo.java                              |   12 
 src/main/java/com/ruoyi/production/bean/dto/ProductionProductOutputDto.java                                    |   40 
 src/main/java/com/ruoyi/basic/dto/CustomerDto.java                                                             |   10 
 src/main/java/com/ruoyi/staff/pojo/SchemeApplicableStaff.java                                                  |   36 
 src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java                |    2 
 src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java |  115 
 src/main/java/com/ruoyi/basic/pojo/SupplierManageFile.java                                                     |   25 
 src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java                                     |   53 
 src/main/resources/mapper/system/SysUserMapper.xml                                                             |   22 
 src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java                                    |   22 
 src/main/java/com/ruoyi/project/tool/swagger/TestController.java                                               |   67 
 src/main/java/com/ruoyi/staff/dto/StaffOnJobExcelDto.java                                                      |   87 
 src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java                           |    2 
 src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java                                          |  104 
 src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java                                            |   62 
 src/main/java/com/ruoyi/approve/controller/KnowledgeBaseController.java                                        |   14 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java                                   |    6 
 src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java                        |  355 
 src/main/java/com/ruoyi/basic/dto/StorageBlobVO.java                                                           |   19 
 src/main/java/com/ruoyi/technology/pojo/TechnologyOperationParam.java                                          |   38 
 src/main/java/com/ruoyi/framework/config/ResourcesConfig.java                                                  |   13 
 src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java                                    |   23 
 src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementExceptionRecord.java                                 |    8 
 src/main/java/com/ruoyi/safe/pojo/SafeHazardRecord.java                                                        |   26 
 src/main/java/com/ruoyi/approve/vo/ApproveProcessVo.java                                                       |   12 
 src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationParamMapper.java                           |   18 
 src/main/java/com/ruoyi/basic/pojo/CustomerUser.java                                                           |   43 
 src/main/java/com/ruoyi/CodeGenerator.java                                                                     |   16 
 src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java                                                   |   29 
 src/main/java/com/ruoyi/common/enums/FileNameType.java                                                         |   10 
 src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java                                     |   22 
 src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java                                          |  114 
 src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java                                                       |   47 
 src/main/java/com/ruoyi/production/service/ProductionAccountService.java                                       |   23 
 src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java                                            |   37 
 src/main/java/com/ruoyi/safe/service/SafeTrainingService.java                                                  |    2 
 src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java                                           |   18 
 src/main/java/com/ruoyi/framework/security/service/SysLoginService.java                                        |   44 
 src/main/java/com/ruoyi/quality/pojo/QualityInspectParam.java                                                  |   17 
 src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java                                        |   21 
 src/main/java/com/ruoyi/safe/pojo/SafeTraining.java                                                            |   48 
 src/main/java/com/ruoyi/account/service/AccountIncomeService.java                                              |    2 
 src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationParamService.java                         |   27 
 src/main/java/com/ruoyi/sales/pojo/CommonFile.java                                                             |   11 
 src/main/java/com/ruoyi/basic/service/CustomerUserService.java                                                 |   13 
 src/main/java/com/ruoyi/framework/security/LoginUser.java                                                      |  116 
 src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml                                       |   60 
 src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java                   |   10 
 src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java                                          |   14 
 src/main/java/com/ruoyi/staff/pojo/StaffEmergencyContact.java                                                  |   28 
 src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java                                |   25 
 src/main/java/com/ruoyi/ai/store/MongoChatMemoryStore.java                                                     |   62 
 src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java                                |   29 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java                                              |    8 
 src/main/java/com/ruoyi/officesupplies/service/impl/OfficeSuppliesServiceImpl.java                             |    6 
 src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java                                              |    3 
 src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java                                  |    4 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java                                |  170 
 src/main/resources/mapper/production/ProductionOperationMainParamMapper.xml                                    |   30 
 src/main/java/com/ruoyi/account/service/impl/SalesRefundAmountOrderServiceImpl.java                            |   14 
 src/main/java/com/ruoyi/other/mapper/PdaVersionMapper.java                                                     |    9 
 src/main/java/com/ruoyi/approve/pojo/ApproveNode.java                                                          |   30 
 src/main/java/com/ruoyi/approve/pojo/ApproveProcessConfigNode.java                                             |  118 
 src/main/java/com/ruoyi/device/pojo/DeviceLedger.java                                                          |   36 
 src/main/java/com/ruoyi/framework/config/DruidConfig.java                                                      |   33 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java                                   |   29 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java                                          |   32 
 src/main/java/com/ruoyi/oA/controller/OaProjectPhaseController.java                                            |   20 
 src/main/java/com/ruoyi/sales/service/impl/SalespersonManagementServiceImpl.java                               |    6 
 src/main/java/com/ruoyi/common/utils/excel/ExcelUtils.java                                                     |    4 
 src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java                                                    |   23 
 src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java                                                  |    4 
 src/main/java/com/ruoyi/sales/service/ICommonFileService.java                                                  |    6 
 src/main/java/com/ruoyi/basic/pojo/SupplierManage.java                                                         |   39 
 src/main/java/com/ruoyi/project/system/domain/SysUser.java                                                     |   62 
 src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java                                                 |    7 
 src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java                                    |    2 
 src/main/java/com/ruoyi/purchase/controller/ProcurementBusinessSummaryController.java                          |   14 
 src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java                                         |   12 
 src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java                                              |    4 
 src/main/java/com/ruoyi/account/dto/AccountDto.java                                                            |    4 
 src/main/java/com/ruoyi/warehouse/service/DocumentationBorrowManagementService.java                            |    2 
 src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsRequisitionRecordController.java        |   36 
 src/main/java/com/ruoyi/sales/dto/ShippingProductDetailDto.java                                                |   16 
 src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java                                                     |   59 
 src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java                                           |   13 
 src/main/java/com/ruoyi/stock/pojo/StockInventory.java                                                         |   33 
 src/main/java/com/ruoyi/approve/mapper/ApproveProcessMapper.java                                               |    3 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductOutputServiceImpl.java                        |   10 
 src/main/java/com/ruoyi/approve/service/ApproveProcessConfigNodeService.java                                   |   22 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationServiceImpl.java                     |  142 
 src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordOut.java                                       |    3 
 src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java                                       |    5 
 src/main/java/com/ruoyi/procurementrecord/service/impl/InboundManagementServiceImpl.java                       |    6 
 src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java                                            |    3 
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                                                   |   44 
 doc/采购智能体多文件分析前端联调说明.md                                                                                        |  183 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/StaffContactsPersonal.java                                  |    9 
 src/main/java/com/ruoyi/oA/controller/OaProjectPhaseTaskController.java                                        |   20 
 src/main/java/com/ruoyi/technology/pojo/TechnologyRouting.java                                                 |   55 
 src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java                                          |    6 
 src/main/java/com/ruoyi/staff/dto/SaveStaffSchedulingDto.java                                                  |    2 
 src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java                                                        |    2 
 src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java                                          |   63 
 src/main/java/com/ruoyi/project/common/CommonController.java                                                   |  226 
 src/main/java/com/ruoyi/staff/service/StaffLeaveService.java                                                   |    2 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java                                    |   34 
 src/main/java/com/ruoyi/basic/controller/ProductController.java                                                |   16 
 src/main/java/com/ruoyi/ai/mongodbBean/ChatMessages.java                                                       |   30 
 src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java                                           |   32 
 src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerTemplate.java                                              |   49 
 src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java                                  |    3 
 src/main/java/com/ruoyi/safe/dto/SafeTrainingDto.java                                                          |   10 
 src/main/java/com/ruoyi/home/dto/CustomerContributionRankingDto.java                                           |    9 
 src/main/java/com/ruoyi/common/filter/RepeatableFilter.java                                                    |   14 
 src/main/java/com/ruoyi/project/system/controller/SysProfileController.java                                    |   19 
 src/main/java/com/ruoyi/projectManagement/pojo/Roles.java                                                      |   24 
 src/main/java/com/ruoyi/basic/controller/CustomerFollowUpController.java                                       |   38 
 src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java                                                        |   40 
 src/main/java/com/ruoyi/production/service/ProductionPlanService.java                                          |   56 
 src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java                                                  |   79 
 src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java                                             |    1 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetDraft.java                                              |    3 
 src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java                                   |    5 
 src/main/java/com/ruoyi/production/bean/dto/ProductionPlanDto.java                                             |   55 
 src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java                                            |   34 
 src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesServiceImpl.java                           |   30 
 src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java                                                    |   19 
 src/main/java/com/ruoyi/basic/controller/SupplierManageFileController.java                                     |    2 
 src/main/java/com/ruoyi/other/controller/PdaVersionController.java                                             |   31 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java                                              |   17 
 src/main/java/com/ruoyi/framework/manager/ShutdownManager.java                                                 |    2 
 src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementFileController.java         |    2 
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java                                             |   21 
 src/main/resources/mapper/quality/QualityTestStandardMapper.xml                                                |    4 
 src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java                                                     |   10 
 src/main/java/com/ruoyi/home/dto/ProductionTurnoverDto.java                                                    |   17 
 src/main/java/com/ruoyi/common/xss/Xss.java                                                                    |    4 
 src/main/java/com/ruoyi/safe/pojo/SafeHidden.java                                                              |   61 
 src/main/java/com/ruoyi/projectManagement/dto/RoleDto.java                                                     |    4 
 src/main/java/com/ruoyi/projectManagement/vo/PlanVo.java                                                       |    4 
 src/main/java/com/ruoyi/production/bean/dto/ProductionProductInputDto.java                                     |   44 
 src/main/resources/application-dev-pro.yml                                                                     |  266 
 src/main/resources/mapper/production/ProductionOrderBomMapper.xml                                              |   20 
 src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java                                     |   31 
 src/main/java/com/ruoyi/approve/service/impl/RpaProcessAutomationServiceImpl.java                              |    7 
 src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java              |   11 
 src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java                                                  |   30 
 src/main/java/com/ruoyi/basic/utils/FileUtil.java                                                              |  847 +
 src/main/java/com/ruoyi/warehouse/controller/DocumentationBorrowManagementController.java                      |   49 
 src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java                                   |   99 
 src/main/java/com/ruoyi/warehouse/dto/DocumentationBorrowManagementDto.java                                    |    2 
 src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpServiceImpl.java                                    |   12 
 src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java                                                         |   37 
 src/main/java/com/ruoyi/officesupplies/controller/OfficeSuppliesController.java                                |   21 
 src/main/java/com/ruoyi/procurementrecord/pojo/ReturnSaleProduct.java                                          |   35 
 src/main/java/com/ruoyi/ai/dto/AiChatSessionDto.java                                                           |   19 
 src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java                                    |    2 
 src/main/java/com/ruoyi/approve/pojo/OvertimeSetting.java                                                      |    3 
 src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java                                                    |    6 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java                |  176 
 src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java                                          |    2 
 src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java                                |   11 
 src/main/resources/approve-todo-agent-prompt.txt                                                               |   18 
 src/main/java/com/ruoyi/common/aop/DataScopeAop.java                                                           |  158 
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java                                      |  283 
 src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementController.java             |   28 
 src/main/java/com/ruoyi/warehouse/service/impl/DocumentClassificationServiceImpl.java                          |   21 
 src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordOutController.java                       |   17 
 src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java                                      |    8 
 src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java                                     |   10 
 src/main/java/com/ruoyi/production/service/ProductionProductOutputService.java                                 |    2 
 src/main/java/com/ruoyi/production/service/SalesLedgerProductionAccountingService.java                         |   27 
 src/main/java/com/ruoyi/projectManagement/vo/SavePlanNodeVo.java                                               |    4 
 src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java                                       |  180 
 src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java                                            |   64 
 src/main/resources/mapper/basic/StorageBlobMapper.xml                                                          |   61 
 src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceServiceImpl.java                       |   20 
 src/main/java/com/ruoyi/basic/mapper/CustomerUserMapper.java                                                   |   15 
 src/main/java/com/ruoyi/common/utils/ip/IpUtils.java                                                           |    2 
 src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java                                    |   47 
 src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java                                                   |    4 
 src/main/java/com/ruoyi/basic/pojo/CustomerReturnVisit.java                                                    |    7 
 src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java                                                 |   28 
 src/main/java/com/ruoyi/lavorissue/service/impl/LavorIssueServiceImpl.java                                     |   64 
 src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java                                                 |    4 
 src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java                                     |   39 
 src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamSyncDto.java                   |   14 
 src/main/resources/static/work-order-template.docx                                                             |    0 
 src/main/java/com/ruoyi/sales/service/impl/MetricStatisticsServiceImpl.java                                    |   14 
 src/main/java/com/ruoyi/ai/config/PurchaseAgentConfig.java                                                     |   32 
 src/main/java/com/ruoyi/home/controller/HomeController.java                                                    |   94 
 src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java                                           |   22 
 src/main/java/com/ruoyi/compensationperformance/service/impl/CompensationPerformanceServiceImpl.java           |    6 
 src/main/resources/mapper/technology/TechnologyRoutingMapper.xml                                               |   64 
 src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesController.java                              |   21 
 src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java                                       |   30 
 src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java                                     |    6 
 src/main/java/com/ruoyi/ai/config/ApproveTodoAgentConfig.java                                                  |   20 
 src/main/java/com/ruoyi/staff/controller/StaffLeaveController.java                                             |    8 
 src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java                              |   15 
 src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java                                         |   37 
 src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesRowcolController.java                        |   19 
 src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java                                  |   12 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java                                 |   15 
 src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java                                             |   24 
 src/main/java/com/ruoyi/technology/service/TechnologyBomService.java                                           |   32 
 src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java                                                       |    4 
 src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java                                                     |    8 
 src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java                                                       |   53 
 src/main/java/com/ruoyi/production/bean/dto/SalesLedgerProductionAccountingDto.java                            |   20 
 src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java                                       |   24 
 src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java                                 |   11 
 src/main/resources/mapper/production/ProductionOrderMapper.xml                                                 |  215 
 src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java                                                |    9 
 src/main/java/com/ruoyi/staff/controller/SchemeApplicableStaffController.java                                  |   20 
 src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java                                                 |   34 
 src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java                             |    3 
 src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EnergyPeriod.java                                      |   24 
 src/main/java/com/ruoyi/production/pojo/ProductionOrder.java                                                   |   83 
 src/main/java/com/ruoyi/production/service/ProductionOperationMainParamService.java                            |   16 
 src/main/java/com/ruoyi/safe/pojo/SafeAccident.java                                                            |   42 
 src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerImportDto.java                                              |    8 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java                         |   10 
 src/main/java/com/ruoyi/framework/security/service/TokenService.java                                           |  121 
 src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java                                          |   24 
 src/main/resources/mapper/basic/ProductModelMapper.xml                                                         |   38 
 src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java                                           |   79 
 src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/ElectricityConsumptionArea.java                        |   16 
 src/main/java/com/ruoyi/account/controller/AccountFileController.java                                          |   14 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagementFile.java                         |   26 
 src/main/java/com/ruoyi/sales/pojo/PurchaseLedgerFile.java                                                     |   23 
 src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java                                           |   33 
 src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java                                                      |   52 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java                                 |   18 
 src/main/java/com/ruoyi/home/dto/ProductionProgressOrderDto.java                                               |   57 
 src/main/java/com/ruoyi/warehouse/service/impl/WarehouseServiceImpl.java                                       |   27 
 src/main/java/com/ruoyi/basic/vo/CustomerVo.java                                                               |   28 
 src/main/java/com/ruoyi/device/mapper/DeviceRepairMapper.java                                                  |    5 
 src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrderProducts.java                                         |   22 
 src/main/java/com/ruoyi/approve/pojo/AnnualLeaveSetting.java                                                   |    3 
 src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java                                   |    4 
 src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java                                            |   21 
 src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java                                              |   14 
 src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java                                                        |   26 
 src/main/java/com/ruoyi/approve/service/impl/KnowledgeBaseServiceImpl.java                                     |    6 
 src/main/java/com/ruoyi/account/controller/BorrowInfoController.java                                           |   15 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java                            |  919 +
 src/main/java/com/ruoyi/account/pojo/BorrowInfo.java                                                           |   34 
 src/main/java/com/ruoyi/sales/service/impl/PaymentShippingServiceImpl.java                                     |    6 
 src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedgerRecord.java                    |   32 
 src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java                                               |    3 
 src/main/resources/mapper/production/ProductionProductInputMapper.xml                                          |  102 
 src/main/java/com/ruoyi/project/system/controller/SysIndexController.java                                      |    3 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerTemplateServiceImpl.java                           |   14 
 src/main/resources/mapper/sales/SalesQuotationMapper.xml                                                       |    1 
 src/main/java/com/ruoyi/staff/controller/PersonalShiftController.java                                          |   65 
 src/main/java/com/ruoyi/account/controller/AccountingController.java                                           |   16 
 src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java                                    |   18 
 src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java                                               |   17 
 src/main/java/com/ruoyi/technology/pojo/TechnologyOperation.java                                               |   68 
 src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java              |   21 
 src/main/java/com/ruoyi/staff/dto/PerformanceShiftAddDto.java                                                  |   12 
 src/main/java/com/ruoyi/procurementrecord/controller/GasTankWarningController.java                             |   18 
 src/main/java/com/ruoyi/technology/mapper/TechnologyParamMapper.java                                           |   18 
 src/main/java/com/ruoyi/project/system/controller/SysRoleController.java                                       |   13 
 src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java                                  |   17 
 src/main/java/com/ruoyi/warehouse/dto/ReturnExportDto.java                                                     |    2 
 src/main/java/com/ruoyi/collaborativeApproval/controller/StaffContactsPersonalController.java                  |   20 
 src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java                                    |    6 
 src/main/java/com/ruoyi/oA/pojo/OaProject.java                                                                 |    3 
 src/main/resources/mapper/approve/ApproveProcessMapper.xml                                                     |    2 
 src/main/java/com/ruoyi/other/pojo/PdaVersion.java                                                             |   54 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java                                      |    6 
 src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java                                                   |    6 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/SealApplicationManagement.java                              |   17 
 src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java                               |   48 
 src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java                                        |   18 
 src/main/java/com/ruoyi/common/utils/http/HttpHelper.java                                                      |    2 
 src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java                           |   24 
 src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java                                               |    2 
 src/main/java/com/ruoyi/warehouse/pojo/DocumentationReturnManagement.java                                      |   26 
 src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java                                          |   22 
 src/main/java/com/ruoyi/project/system/domain/SysDept.java                                                     |   16 
 src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java                                            |   50 
 src/main/java/com/ruoyi/production/service/ProductionProductMainService.java                                   |    8 
 src/main/java/com/ruoyi/sales/pojo/SalespersonManagement.java                                                  |   34 
 src/main/java/com/ruoyi/production/service/impl/ProductionOperationMainParamServiceImpl.java                   |   20 
 src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java                                        |    8 
 src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java                            |   56 
 src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java                            |    4 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java                                |  952 +
 src/main/resources/mapper/stock/StockUninventoryMapper.xml                                                     |   28 
 src/main/java/com/ruoyi/procurementrecord/controller/InboundManagementController.java                          |   18 
 src/main/java/com/ruoyi/stock/service/StockUninventoryService.java                                             |    6 
 src/main/java/com/ruoyi/quality/pojo/QualityTestStandardParam.java                                             |   30 
 src/main/resources/mapper/technology/TechnologyBomMapper.xml                                                   |   42 
 src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EnergyPeriodServiceImpl.java                   |    6 
 src/main/java/com/ruoyi/home/dto/QualityStatisticsItem.java                                                    |   11 
 src/main/java/com/ruoyi/basic/dto/SupplierManageDto.java                                                       |    4 
 src/main/java/com/ruoyi/projectManagement/dto/UpdateStateInfo.java                                             |    2 
 src/main/java/com/ruoyi/approve/pojo/ApproveLog.java                                                           |   10 
 src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java                                                   |   15 
 doc/20260506_add_ai_enabled_to_sys_user.sql                                                                    |    2 
 src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java                                  |    2 
 src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java                                           |   42 
 src/main/java/com/ruoyi/ai/pojo/AiChatSession.java                                                             |   34 
 src/main/java/com/ruoyi/purchase/service/impl/ProcurementBusinessSummaryServiceImpl.java                       |    8 
 src/main/java/com/ruoyi/project/system/domain/SysMenu.java                                                     |    6 
 src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java                               |   94 
 src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java                      |   15 
 src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationController.java                        |   67 
 src/main/java/com/ruoyi/basic/mapper/StorageBlobMapper.java                                                    |    6 
 src/main/java/com/ruoyi/basic/pojo/CustomerFollowUp.java                                                       |   16 
 src/main/java/com/ruoyi/safe/controller/SafeHazardController.java                                              |   20 
 src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java                                               |   85 
 src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java                                 |   33 
 .gitignore                                                                                                     |    3 
 src/main/java/com/ruoyi/approve/pojo/OnlineMeeting.java                                                        |    3 
 src/main/java/com/ruoyi/home/dto/CustomerRevenueAnalysisDto.java                                               |    7 
 src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml                                              |   19 
 src/main/java/com/ruoyi/device/vo/DeviceRepairVo.java                                                          |   20 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementServiceImpl.java          |    7 
 src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java                                       |    9 
 src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml                                          |   20 
 src/main/java/com/ruoyi/home/dto/ProductCategoryDistributionDto.java                                           |   23 
 src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesRowcolServiceImpl.java                     |   25 
 src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java                                    |   26 
 src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelvesRowcol.java                                        |    7 
 src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java                                                       |   13 
 src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceController.java                          |   36 
 src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java                                      |   53 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java                                                |   15 
 src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EquipmentEnergyConsumptionController.java        |   32 
 src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java                                    |   90 
 src/main/java/com/ruoyi/project/system/domain/vo/SysUserDeptVo.java                                            |    2 
 src/main/java/com/ruoyi/staff/service/impl/StaffSchedulingServiceImpl.java                                     |    2 
 src/main/java/com/ruoyi/production/mapper/ProductionOperationMainParamMapper.java                              |   18 
 src/main/java/com/ruoyi/quality/pojo/QualityInspectFile.java                                                   |   25 
 src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java                                                   |   58 
 src/main/java/com/ruoyi/common/enums/SparePartsRequisitionRecordSourceTypeEnum.java                            |   27 
 src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml                                                    |    6 
 src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java                                         |   26 
 src/main/java/com/ruoyi/framework/aspectj/LogAspect.java                                                       |    4 
 src/main/java/com/ruoyi/stock/service/StockInRecordService.java                                                |    6 
 src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java                                  |   12 
 src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java                                                 |  199 
 src/main/java/com/ruoyi/approve/pojo/FileSharing.java                                                          |    3 
 src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java                           |   88 
 src/main/java/com/ruoyi/safe/pojo/SafeHazard.java                                                              |   32 
 src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java                          |   44 
 src/main/java/com/ruoyi/collaborativeApproval/controller/MeetingController.java                                |   12 
 src/main/java/com/ruoyi/safe/controller/SafeHazardRecordController.java                                        |   20 
 src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java                                   |   23 
 src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java                              |   73 
 src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java                                    |   22 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/Notice.java                                                 |   20 
 src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java                                      |    6 
 src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java                                  |    4 
 src/main/resources/mapper/production/ProductionOrderRoutingOperationMapper.xml                                 |   44 
 src/main/java/com/ruoyi/sales/dto/StatisticsTableDto.java                                                      |    9 
 src/main/java/com/ruoyi/approve/service/impl/ApproveProcessConfigNodeServiceImpl.java                          |   48 
 src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java          |   34 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java           |  167 
 src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java                                                 |    2 
 src/main/java/com/ruoyi/staff/controller/BankController.java                                                   |   16 
 src/main/java/com/ruoyi/account/dto/SalesRefundAmountOrderDto.java                                             |   12 
 src/main/java/com/ruoyi/production/controller/ProductionPlanController.java                                    |  103 
 src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java                                             |   33 
 src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java                                        |   24 
 src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java                                                        |   25 
 doc/create_table_customer_user.sql                                                                             |   10 
 src/main/java/com/ruoyi/quality/pojo/QualityTestStandardBinding.java                                           |   22 
 src/main/java/com/ruoyi/common/vo/FileVo.java                                                                  |   16 
 src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java                                                    |   49 
 src/main/java/com/ruoyi/basic/service/impl/CustomerUserServiceImpl.java                                        |   19 
 src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java                                                  |   15 
 src/main/java/com/ruoyi/basic/dto/ProductModelDto.java                                                         |    2 
 src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordOutService.java                             |    2 
 src/main/java/com/ruoyi/procurementrecord/pojo/InboundManagement.java                                          |   32 
 src/main/java/com/ruoyi/account/dto/DeviceTypeDistributionVO.java                                              |    1 
 src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java                                                     |   20 
 src/main/java/com/ruoyi/approve/pojo/NotificationManagement.java                                               |    3 
 src/main/java/com/ruoyi/home/dto/WorkOrderEfficiencyDto.java                                                   |   13 
 src/main/java/com/ruoyi/staff/controller/HolidayApplicationController.java                                     |    5 
 src/main/java/com/ruoyi/technology/service/TechnologyRoutingService.java                                       |   40 
 src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java                         |   21 
 src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java                                    |    2 
 src/main/java/com/ruoyi/projectManagement/pojo/PlanNode.java                                                   |    3 
 src/main/resources/vm/java/controller.java.vm                                                                  |    2 
 src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java                                       |   21 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java                                    |   18 
 src/main/java/com/ruoyi/framework/config/SecurityConfig.java                                                   |   84 
 src/main/java/com/ruoyi/account/pojo/AccountFile.java                                                          |   27 
 src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java                                                |   57 
 src/main/java/com/ruoyi/projectManagement/pojo/Info.java                                                       |    3 
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java                                      |   13 
 src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java                                       |   23 
 src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java                                         |   32 
 src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java                              |   18 
 src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceNewDto.java                                     |    4 
 src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPriceManagementController.java                 |   20 
 src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java                                                       |    8 
 src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelves.java                                              |    7 
 src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java                                                        |   70 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingServiceImpl.java                         |   35 
 src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java                                                     |   28 
 src/main/java/com/ruoyi/basic/pojo/StorageBlob.java                                                            |   52 
 src/main/java/com/ruoyi/staff/controller/StaffContractController.java                                          |    6 
 src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationParamMapper.java                      |   18 
 src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java                                 |  350 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java                              |  224 
 src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java                                                    |    6 
 src/main/java/com/ruoyi/production/service/ProductionProductInputService.java                                  |    2 
 src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java                                         |   78 
 src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java                               |   47 
 src/main/java/com/ruoyi/oA/controller/OaProjectController.java                                                 |   31 
 src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java                                          |    9 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/NoticeType.java                                             |   14 
 src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java                                               |    6 
 src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceFileServiceImpl.java                   |    6 
 src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EquipmentEnergyConsumption.java                        |   30 
 src/main/java/com/ruoyi/dto/MapDto.java                                                                        |   11 
 src/main/java/com/ruoyi/basic/service/CustomerFollowUpFileService.java                                         |    6 
 src/main/java/com/ruoyi/production/pojo/ProductionOperationMainParam.java                                      |   95 
 src/main/resources/mapper/production/ProductionOperationTaskMapper.xml                                         |  213 
 src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java                                                      |    8 
 src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java                        |   17 
 src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java                                |   17 
 src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnSaleProductServiceImpl.java                       |   16 
 src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml                                               |   14 
 src/main/java/com/ruoyi/waterrecord/pojo/WaterRecord.java                                                      |   28 
 src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java                                         |   15 
 src/main/java/com/ruoyi/staff/pojo/StaffWorkExperience.java                                                    |   32 
 src/main/java/com/ruoyi/production/pojo/ProductionPlan.java                                                    |   85 
 src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java                                  |   23 
 src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java                                     |   22 
 src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java                                       |   49 
 src/main/java/com/ruoyi/lavorissue/service/LavorIssueService.java                                              |    2 
 src/main/java/com/ruoyi/procurementrecord/service/GasTankWarningService.java                                   |    2 
 src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java                                      |   51 
 src/main/java/com/ruoyi/staff/pojo/HolidayApplication.java                                                     |    8 
 src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java                                       |   32 
 src/main/java/com/ruoyi/production/bean/dto/UserAccountDto.java                                                |   14 
 src/main/java/com/ruoyi/equipmentenergyconsumption/dto/ElectricityConsumptionAreaTreeDto.java                  |    3 
 src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java                                 |   27 
 src/main/java/com/ruoyi/framework/security/service/SysPasswordService.java                                     |   15 
 src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java                      |   10 
 src/main/java/com/ruoyi/production/bean/dto/UserProductionAccountingDto.java                                   |   12 
 src/main/java/com/ruoyi/customervisits/pojo/CustomerVisits.java                                                |   26 
 src/main/java/com/ruoyi/production/controller/ProductionProductOutputController.java                           |   12 
 src/main/java/com/ruoyi/safe/controller/SafeTrainingDetailsController.java                                     |   21 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationParamServiceImpl.java                |  228 
 src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java                                 |    2 
 src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java                                               |    2 
 src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingMapper.java                                    |   18 
 src/main/java/com/ruoyi/sales/service/ShippingInfoService.java                                                 |   10 
 src/main/java/com/ruoyi/approve/controller/ApproveProcessConfigNodeController.java                             |   49 
 src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java                                   |   21 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java                                         |   18 
 src/main/java/com/ruoyi/sales/controller/SalespersonManagementController.java                                  |   20 
 src/main/java/com/ruoyi/common/utils/ServletUtils.java                                                         |    8 
 src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java                                       |  129 
 src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java                            |   40 
 src/main/java/com/ruoyi/approve/service/impl/NotificationManagementServiceImpl.java                            |    7 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java                                       |   27 
 src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java                                       |  108 
 src/main/java/com/ruoyi/staff/pojo/StaffScheduling.java                                                        |    3 
 src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java                                |   24 
 src/main/resources/mapper/sales/InvoiceLedgerMapper.xml                                                        |    2 
 src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java                                    |   20 
 src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java                                                 |   11 
 src/main/resources/application-dev.yml                                                                         |   59 
 src/main/java/com/ruoyi/safe/controller/SafeCertificationFileController.java                                   |   17 
 src/main/java/com/ruoyi/production/bean/vo/ProductionPlanVo.java                                               |   33 
 src/main/java/com/ruoyi/project/common/CaptchaController.java                                                  |   30 
 src/main/java/com/ruoyi/production/controller/ProductionOrderController.java                                   |   98 
 src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationParamService.java                    |   33 
 src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java                                |   11 
 src/main/java/com/ruoyi/sales/controller/SalesQuotationController.java                                         |   11 
 src/main/java/com/ruoyi/collaborativeApproval/service/DutyPlanService.java                                     |    2 
 src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsRequisitionRecordServiceImpl.java     |   38 
 src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java                                                         |   13 
 src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java                                |   28 
 src/main/java/com/ruoyi/stock/service/StockOutRecordService.java                                               |    6 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java                               |   74 
 src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java                                                |   53 
 src/main/java/com/ruoyi/device/pojo/DeviceDefectRecord.java                                                    |   25 
 src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java                                |   47 
 src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java                            |   20 
 src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java                                        |   21 
 src/main/java/com/ruoyi/project/system/controller/SysConfigController.java                                     |   22 
 src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java                             |   99 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/SealApplicationManagementServiceImpl.java           |    6 
 src/main/java/com/ruoyi/staff/pojo/StaffContract.java                                                          |   25 
 src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java                                |   18 
 src/main/java/com/ruoyi/ai/assistant/FileAnalyzeAgent.java                                                     |   24 
 src/main/java/com/ruoyi/other/pojo/TempFile.java                                                               |   14 
 src/main/java/com/ruoyi/warehouse/pojo/DocumentationBorrowManagement.java                                      |   26 
 pom.xml                                                                                                        |  193 
 src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java                          |   50 
 src/main/java/com/ruoyi/project/monitor/controller/CacheController.java                                        |   26 
 src/main/java/com/ruoyi/projectManagement/controller/PlanController.java                                       |   14 
 src/main/java/com/ruoyi/sales/controller/PaymentShippingController.java                                        |   22 
 src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java                                      |   38 
 src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java                                                      |   25 
 src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java                                    |  204 
 src/main/java/com/ruoyi/common/filter/XssFilter.java                                                           |   16 
 src/main/java/com/ruoyi/warehouse/controller/WarehouseController.java                                          |   31 
 src/main/java/com/ruoyi/production/mapper/ProductionProductOutputMapper.java                                   |    2 
 src/main/java/com/ruoyi/staff/pojo/PersonalShift.java                                                          |   22 
 src/main/java/com/ruoyi/account/pojo/SalesRefundAmountOrder.java                                               |   30 
 src/main/java/com/ruoyi/equipmentenergyconsumption/controller/ElectricityConsumptionAreaController.java        |   23 
 src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java                                               |   11 
 src/main/resources/mapper/sales/ShippingInfoMapper.xml                                                         |    9 
 src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java                                                           |   37 
 src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java                                  |   24 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java                                  |  485 
 src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java                                                        |    9 
 doc/20260506_用户AI功能字段前端联调说明.md                                                                                 |   53 
 src/main/java/com/ruoyi/ai/controller/XiaozhiController.java                                                   |  162 
 src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java                                  |   15 
 src/main/java/com/ruoyi/safe/pojo/SafeCertificationFile.java                                                   |   12 
 src/main/resources/mapper/production/ProductionProductMainMapper.xml                                           |  239 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java                                            |   10 
 src/main/java/com/ruoyi/project/system/domain/SysPost.java                                                     |    6 
 src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java                                      |   29 
 src/main/java/com/ruoyi/sales/pojo/ShipmentApproval.java                                                       |   73 
 src/main/resources/application.yml                                                                             |   38 
 src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java                                                        |  231 
 src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerTemplateController.java                              |   21 
 src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java                                       |   37 
 src/main/java/com/ruoyi/framework/config/ScheduleConfig.java                                                   |    2 
 src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java                                            |   32 
 src/main/java/com/ruoyi/warehouse/service/impl/DocumentationServiceImpl.java                                   |   41 
 src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeTypeController.java                             |    3 
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java                                        |   78 
 src/main/java/com/ruoyi/ScheduleTask.java                                                                      |    9 
 src/main/resources/mapper/staff/StaffOnJobMapper.xml                                                           |    4 
 src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java                                  |   19 
 src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java                                   |    7 
 src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessConfigNodeVo.java                                        |    9 
 src/main/java/com/ruoyi/staff/task/PersonalAttendanceRecordsTask.java                                          |   27 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java                                     |   31 
 src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java                                             |    3 
 src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java                                 |    7 
 src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java                                                        |   21 
 src/main/java/com/ruoyi/basic/service/StorageBlobService.java                                                  |   21 
 src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java                                            |   13 
 src/main/resources/mapper/stock/StockOutRecordMapper.xml                                                       |   14 
 src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java       |  125 
 src/main/resources/mybatis/mybatis-config.xml                                                                  |    3 
 src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java                                                   |    3 
 src/main/java/com/ruoyi/technology/controller/TechnologyRoutingController.java                                 |   70 
 src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java                                            |    4 
 src/main/java/com/ruoyi/project/monitor/domain/SysJob.java                                                     |    4 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementFileServiceImpl.java      |   14 
 src/main/java/com/ruoyi/other/dto/PdaVersionDTO.java                                                           |   15 
 src/main/java/com/ruoyi/projectManagement/controller/RolesController.java                                      |   16 
 src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java                                               |  161 
 src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java                             |   11 
 src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java                                                        |   10 
 src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesNearExpiryController.java                       |   18 
 src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java                                 |   10 
 src/main/java/com/ruoyi/project/system/service/impl/UnipushService.java                                        |   18 
 src/main/resources/mapper/production/ProductionPlanMapper.xml                                                  |  106 
 src/main/java/com/ruoyi/ai/config/EmbeddingStoreConfig.java                                                    |   36 
 src/main/java/com/ruoyi/production/bean/dto/ProductionOrderDto.java                                            |   17 
 src/main/java/com/ruoyi/ai/controller/PurchaseAiController.java                                                |  903 +
 src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java                                   |   52 
 src/main/java/com/ruoyi/framework/config/SwaggerConfig.java                                                    |  177 
 src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java                                                 |    8 
 src/main/resources/application-new-pro.yml                                                                     |  268 
 src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java    |   19 
 src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java                             |   58 
 src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java                                        |   19 
 src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationMapper.java                           |   24 
 src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java                              |   37 
 src/main/java/com/ruoyi/home/dto/ProductionProgressDto.java                                                    |   20 
 src/main/resources/mapper/production/ProductionProductOutputMapper.xml                                         |   92 
 src/main/java/com/ruoyi/account/pojo/SalesReceiptReturn.java                                                   |   32 
 src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java                                                  |   38 
 src/main/java/com/ruoyi/basic/vo/ProductModelVo.java                                                           |   14 
 src/main/java/com/ruoyi/device/dto/DeviceDefectRecordDto.java                                                  |    6 
 src/main/resources/mapper/stock/StockInventoryMapper.xml                                                       |  254 
 src/main/java/com/ruoyi/lavorissue/pojo/LaborIssue.java                                                        |   36 
 src/main/java/com/ruoyi/account/controller/AccountIncomeController.java                                        |   22 
 src/main/java/com/ruoyi/project/system/service/impl/SysUserDeptServiceImpl.java                                |    6 
 src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java                                               |    3 
 src/main/java/com/ruoyi/basic/pojo/StorageAttachment.java                                                      |   35 
 src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java                                 |    6 
 src/main/java/com/ruoyi/basic/service/ICustomerService.java                                                    |   25 
 src/main/java/com/ruoyi/other/service/impl/PdaVersionServiceImpl.java                                          |   60 
 src/main/java/com/ruoyi/oA/pojo/OaProjectPhase.java                                                            |    3 
 src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java                         |   14 
 src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java                                       |   22 
 src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java                                                          |   15 
 src/main/java/com/ruoyi/common/interceptor/DataScopeSqlInterceptor.java                                        |  257 
 src/main/java/com/ruoyi/warehouse/service/impl/DocumentationBorrowManagementServiceImpl.java                   |   38 
 src/main/java/com/ruoyi/production/mapper/ProductionProductInputMapper.java                                    |    2 
 src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrderProductsController.java                         |    4 
 src/main/java/com/ruoyi/framework/security/service/SysRegisterService.java                                     |   16 
 src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java                                         |   34 
 src/main/java/com/ruoyi/procurementrecord/controller/ProcurementExceptionRecordController.java                 |   12 
 src/main/java/com/ruoyi/ai/assistant/SeparateChatAssistant.java                                                |   35 
 src/main/java/com/ruoyi/approve/pojo/RpaProcessAutomation.java                                                 |    3 
 src/main/resources/mapper/measuringinstrumentledger/SparePartsRequisitionRecordMapper.xml                      |   36 
 src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java                                              |   14 
 src/main/java/com/ruoyi/compensationperformance/pojo/CompensationPerformance.java                              |   44 
 src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java                                |   17 
 src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java                               |   21 
 src/main/java/com/ruoyi/purchase/pojo/SalesLedgerProductTemplate.java                                          |   46 
 src/main/java/com/ruoyi/staff/pojo/Bank.java                                                                   |   16 
 src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EnergyPeriodController.java                      |   34 
 src/main/java/com/ruoyi/sales/vo/SalesLedgerVo.java                                                            |   13 
 src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java                              |   96 
 src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java                                 |   17 
 src/main/resources/mapper/approve/ApproveProcessConfigNodeMapper.xml                                           |   21 
 src/main/java/com/ruoyi/device/controller/DeviceRepairController.java                                          |   45 
 src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java                                    |   15 
 src/main/resources/mapper/account/AccountIncomeMapper.xml                                                      |   30 
 src/main/java/com/ruoyi/projectManagement/pojo/Plan.java                                                       |   26 
 src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java                                                    |   25 
 src/main/java/com/ruoyi/project/system/domain/SysUserDept.java                                                 |   10 
 src/main/java/com/ruoyi/projectManagement/service/InfoService.java                                             |    2 
 src/main/java/com/ruoyi/common/config/FileProperties.java                                                      |   28 
 src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java                                         |   18 
 src/main/java/com/ruoyi/home/dto/AnalysisCustomerContractAmountsDto.java                                       |   11 
 src/main/resources/mapper/sales/SalesLedgerMapper.xml                                                          |   53 
 src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml                                        |   33 
 src/main/java/com/ruoyi/common/constant/Constants.java                                                         |    2 
 src/main/java/com/ruoyi/basic/service/IProductService.java                                                     |    3 
 src/main/resources/my-prompt-template.txt                                                                      |    2 
 src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java                                               |   13 
 src/main/java/com/ruoyi/warehouse/pojo/Documentation.java                                                      |   42 
 src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java                                             |   47 
 src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationMapper.java                                |   31 
 src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java                                        |   16 
 src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java                                     |   56 
 src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java                                        |   48 
 src/main/java/com/ruoyi/device/vo/DeviceMaintenanceVo.java                                                     |   51 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java                                          |   12 
 src/main/java/com/ruoyi/procurementrecord/dto/ReturnManagementDto.java                                         |   17 
 src/main/java/com/ruoyi/safe/controller/SafeHiddenFileController.java                                          |   14 
 src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java                                        |   16 
 src/main/resources/purchase-agent-prompt.txt                                                                   |   14 
 src/main/resources/mapper/quality/QualityInspectMapper.xml                                                     |   17 
 src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java                                                         |   29 
 src/main/java/com/ruoyi/officesupplies/pojo/OfficeSupplies.java                                                |   38 
 src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java                                                     |   42 
 src/main/java/com/ruoyi/basic/pojo/Product.java                                                                |   14 
 src/main/java/com/ruoyi/basic/service/ISupplierService.java                                                    |    2 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java                       |   75 
 src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java                                                 |   26 
 src/main/java/com/ruoyi/ai/service/AiFileTextExtractor.java                                                    |  131 
 src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java                                                       |    9 
 src/main/java/com/ruoyi/account/pojo/AccountIncome.java                                                        |   42 
 src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java                                     |    4 
 src/main/resources/mapper/basic/CustomerMapper.xml                                                             |  110 
 src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java                           |   85 
 src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java                                           |    4 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java                                   |  277 
 src/main/java/com/ruoyi/project/system/controller/SysLoginController.java                                      |   77 
 src/main/java/com/ruoyi/project/system/controller/SysDeptController.java                                       |    4 
 src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java                                                  |    4 
 src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java                                          |   45 
 src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationService.java                              |   26 
 src/main/resources/mapper/basic/StorageAttachmentMapper.xml                                                    |    8 
 src/main/java/com/ruoyi/approve/bean/dto/ApproveProcessConfigNodeDto.java                                      |   12 
 src/main/java/com/ruoyi/project/system/controller/SysUserController.java                                       |   13 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java                         |  136 
 .editorconfig                                                                                                  |   13 
 src/main/java/com/ruoyi/warehouse/mapper/DocumentationBorrowManagementMapper.java                              |    2 
 src/main/resources/mapper/technology/TechnologyOperationMapper.xml                                             |   37 
 src/main/java/com/ruoyi/basic/pojo/CustomerFollowUpFile.java                                                   |    5 
 src/main/java/com/ruoyi/basic/controller/SupplierManageController.java                                         |    7 
 src/main/java/com/ruoyi/approve/mapper/ApproveProcessConfigNodeMapper.java                                     |   18 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/DutyPlanServiceImpl.java                            |    8 
 src/main/java/com/ruoyi/account/controller/SalesReceiptReturnController.java                                   |    7 
 src/main/java/com/ruoyi/production/enums/ProductOrderStatusEnum.java                                           |   65 
 src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java                                   |    5 
 src/main/resources/mapper/production/ProductionOrderRoutingOperationParamMapper.xml                            |   29 
 src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java                                  |   52 
 src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java                                             |   57 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/DutyPlan.java                                               |   23 
 src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java                             |    6 
 src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java                                                   |    7 
 src/main/java/com/ruoyi/collaborativeApproval/controller/DutyPlanController.java                               |   17 
 src/main/java/com/ruoyi/quality/pojo/QualityInspect.java                                                       |   22 
 src/main/java/com/ruoyi/warehouse/controller/DocumentClassificationController.java                             |   28 
 src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java                                                   |    7 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationVo.java                              |   26 
 src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java                                                        |   22 
 src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java                           |   14 
 AGENTS.md                                                                                                      |   15 
 src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java                    |    2 
 src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java                                |   11 
 src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardServiceImpl.java                               |   30 
 src/main/java/com/ruoyi/staff/dto/PersonalAttendanceRecordsDto.java                                            |    2 
 src/main/java/com/ruoyi/staff/service/impl/HolidayApplicationServiceImpl.java                                  |    6 
 src/main/java/com/ruoyi/warehouse/pojo/DocumentationFile.java                                                  |   25 
 src/main/java/com/ruoyi/account/service/AccountExpenseService.java                                             |    2 
 src/main/java/com/ruoyi/sales/pojo/SalesQuotation.java                                                         |    6 
 src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java                                               |    2 
 src/main/java/com/ruoyi/warehouse/service/DocumentationService.java                                            |    2 
 doc/encoding-rules.md                                                                                          |   24 
 src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java                                            |   10 
 src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java                                            |   57 
 src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java                                |   40 
 src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java                                                   |   11 
 src/main/java/com/ruoyi/approve/controller/HolidaySettingsController.java                                      |    4 
 src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java                                    |   13 
 src/main/java/com/ruoyi/basic/controller/EnumController.java                                                   |    4 
 src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationController.java                   |   18 
 src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java                                          |   10 
 src/main/java/com/ruoyi/project/system/controller/SysPostController.java                                       |    5 
 src/main/java/com/ruoyi/warehouse/controller/DocumentationController.java                                      |   46 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java                                   |   27 
 src/main/resources/mapper/staff/PersonalShiftMapper.xml                                                        |   14 
 src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java                            |   33 
 src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EquipmentEnergyConsumptionServiceImpl.java     |   11 
 src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java                                           |    2 
 src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java                                                  |   12 
 src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java                                                |    2 
 src/main/java/com/ruoyi/sales/pojo/PaymentShipping.java                                                        |   38 
 src/main/resources/mapper/device/DeviceRepairMapper.xml                                                        |    8 
 src/main/resources/mapper/system/SysRoleMapper.xml                                                             |    1 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java                                            |   21 
 src/main/java/com/ruoyi/stock/service/StockInventoryService.java                                               |   11 
 src/main/resources/application-hbtmblc.yml                                                                     |  256 
 src/main/resources/mapper/account/AccountExpenseMapper.xml                                                     |    8 
 src/main/java/com/ruoyi/project/system/controller/SysMenuController.java                                       |   20 
 src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java                                                    |   20 
 src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java                                                |   47 
 src/main/java/com/ruoyi/safe/pojo/SafeHiddenFile.java                                                          |   10 
 src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperationParam.java                                   |   80 
 src/main/java/com/ruoyi/basic/service/impl/ReturnVisitReminderService.java                                     |   13 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagement.java                             |   23 
 src/main/java/com/ruoyi/ai/dto/AiChatMessageDto.java                                                           |   15 
 src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java                                      |    1 
 src/main/java/com/ruoyi/quality/controller/QualityReportController.java                                        |   23 
 src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java                                                |   69 
 src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java                                  |   18 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/ReadingStatus.java                                          |    3 
 src/main/java/com/ruoyi/project/system/domain/SysConfig.java                                                   |    4 
 src/main/java/com/ruoyi/staff/controller/PersonalAttendanceLocationConfigController.java                       |   24 
 src/main/java/com/ruoyi/other/service/PdaVersionService.java                                                   |   13 
 src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java                                |  223 
 src/main/java/com/ruoyi/approve/controller/NotificationManagementController.java                               |    3 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingMinutes.java                                         |    3 
 src/main/java/com/ruoyi/ai/bean/PurchaseAiConfirmRequest.java                                                  |   26 
 src/main/java/com/ruoyi/oA/service/OaProjectService.java                                                       |    4 
 src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesServiceFile.java                                      |   34 
 src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java                                            |    5 
 src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java                                 |   34 
 src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java                                                       |  643 
 src/main/java/com/ruoyi/common/xss/XssValidator.java                                                           |    4 
 src/main/java/com/ruoyi/basic/service/impl/CustomerReturnVisitServiceImpl.java                                 |    6 
 src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java                                             |    7 
 src/main/java/com/ruoyi/lavorissue/dto/StatisticsLaborIssue.java                                               |    4 
 src/main/java/com/ruoyi/safe/dto/SafeHiddenDto.java                                                            |    9 
 src/main/java/com/ruoyi/common/vo/SimpleFileVo.java                                                            |    2 
 src/main/java/com/ruoyi/production/controller/ProductionOperationMainParamController.java                      |   18 
 src/main/java/com/ruoyi/equipmentenergyconsumption/dto/EquipmentEnergyConsumptionDto.java                      |   24 
 src/main/resources/mapper/procurementrecord/ReturnSaleProductMapper.xml                                        |    8 
 src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperation.java                                   |   70 
 src/main/java/com/ruoyi/projectManagement/controller/InfoController.java                                       |   24 
 src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java                                               |   38 
 src/main/java/com/ruoyi/technology/pojo/TechnologyBom.java                                                     |   60 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java                          |  743 
 src/main/java/com/ruoyi/account/controller/SalesRefundAmountOrderController.java                               |    7 
 src/main/java/com/ruoyi/home/dto/DeptStaffDistributionDto.java                                                 |    9 
 src/main/java/com/ruoyi/lavorissue/controller/LavorIssueController.java                                        |   31 
 src/main/java/com/ruoyi/home/dto/SupplierPurchaseRankingDto.java                                               |    9 
 src/main/java/com/ruoyi/sales/service/impl/ShipmentApprovalServiceImpl.java                                    |    9 
 src/main/java/com/ruoyi/production/controller/ProductionAccountController.java                                 |   41 
 src/main/java/com/ruoyi/dto/DateQueryDto.java                                                                  |    9 
 src/main/java/com/ruoyi/procurementrecord/pojo/GasTankWarning.java                                             |    3 
 src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java                                |    6 
 src/main/java/com/ruoyi/quality/controller/QualityInspectFileController.java                                   |    4 
 src/main/java/com/ruoyi/quality/controller/QualityInspectController.java                                       |   45 
 src/main/java/com/ruoyi/safe/service/impl/SafeCertificationServiceImpl.java                                    |   12 
 src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java                         |  142 
 src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java                                    |   21 
 src/main/java/com/ruoyi/ai/assistant/Assistant.java                                                            |   16 
 src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java                                          |   15 
 src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java                                                          |   17 
 src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceRecords.java                                              |   32 
 src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrdersMapper.java                                        |    3 
 src/main/java/com/ruoyi/approve/service/IApproveProcessService.java                                            |    9 
 src/main/java/com/ruoyi/approve/service/impl/HolidaySettingsServiceImpl.java                                   |    6 
 src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java                            |   14 
 src/main/java/com/ruoyi/measuringinstrumentledger/mapper/SparePartsRequisitionRecordMapper.java                |   23 
 src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java                                   |    3 
 src/main/java/com/ruoyi/project/system/domain/SysRole.java                                                     |    6 
 src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java                |   88 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamDto.java                            |   12 
 src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java                                            |   59 
 src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseServiceImpl.java                                         |   15 
 src/main/java/com/ruoyi/staff/controller/StaffSchedulingController.java                                        |    2 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java                                            |    9 
 src/main/java/com/ruoyi/home/dto/HomeSummaryDto.java                                                           |   17 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java                                     |   29 
 src/main/java/com/ruoyi/basic/pojo/ProductModel.java                                                           |   22 
 src/main/java/com/ruoyi/technology/service/TechnologyParamService.java                                         |   27 
 src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java                                     |   31 
 src/main/java/com/ruoyi/quality/service/IQualityInspectService.java                                            |    4 
 src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetApplication.java                                        |    6 
 src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationParamController.java                   |   68 
 src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java                                       |   27 
 src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java                                      |  124 
 src/main/java/com/ruoyi/common/config/MybatisHandler.java                                                      |    4 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationParamVo.java                         |    8 
 src/main/java/com/ruoyi/production/pojo/ProductionAccount.java                                                 |   76 
 src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java                                            |    2 
 src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java                                     |   97 
 src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java                                     |   13 
 src/main/java/com/ruoyi/procurementrecord/service/impl/GasTankWarningServiceImpl.java                          |   17 
 src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java                                           |   11 
 src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java                                |    2 
 src/main/java/com/ruoyi/compensationperformance/controller/CompensationPerformanceController.java              |   26 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java                                      |   49 
 src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java                         |   37 
 src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesService.java                                          |   42 
 src/main/java/com/ruoyi/framework/config/FilterConfig.java                                                     |   15 
 src/main/java/com/ruoyi/project/system/domain/SysNotice.java                                                   |    4 
 src/main/resources/mapper/device/DeviceMaintenanceMapper.xml                                                   |    4 
 src/main/java/com/ruoyi/account/pojo/AccountExpense.java                                                       |   17 
 src/main/java/com/ruoyi/sales/pojo/SalesLedger.java                                                            |   33 
 src/main/java/com/ruoyi/technology/pojo/TechnologyBomStructure.java                                            |   57 
 src/main/resources/mapper/technology/TechnologyRoutingOperationMapper.xml                                      |  106 
 src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java          |    6 
 src/main/java/com/ruoyi/stock/controller/StockInRecordController.java                                          |   40 
 src/main/java/com/ruoyi/oA/pojo/OaProjectPhaseTask.java                                                        |    3 
 src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java                                 |   52 
 src/main/java/com/ruoyi/home/dto/QualityStatisticsDto.java                                                     |   11 
 src/main/java/com/ruoyi/device/service/IDeviceRepairService.java                                               |   11 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java                                         |  204 
 src/main/resources/mapper/sales/ShippingProductDetailMapper.xml                                                |   22 
 src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java                                      |   16 
 src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java                                                   |    9 
 src/main/java/com/ruoyi/RuoYiServletInitializer.java                                                           |    8 
 src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java                               |   20 
 src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamDto.java                       |   10 
 src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsRequisitionRecordDto.java                      |   15 
 src/main/java/com/ruoyi/basic/task/StorageBlobCleanupTask.java                                                 |  184 
 src/main/java/com/ruoyi/basic/task/ReturnVisitReminderTask.java                                                |   16 
 src/main/java/com/ruoyi/stock/controller/StockInventoryController.java                                         |   60 
 src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java                                 |    5 
 src/main/java/com/ruoyi/safe/controller/SafeTrainingFileController.java                                        |   14 
 src/main/java/com/ruoyi/staff/pojo/StaffOnJob.java                                                             |   35 
 src/main/java/com/ruoyi/safe/pojo/SafeCertification.java                                                       |   20 
 src/main/java/com/ruoyi/approve/pojo/WorkingHoursSetting.java                                                  |    3 
 src/main/java/com/ruoyi/technology/bean/dto/BomImportDto.java                                                  |   37 
 src/main/java/com/ruoyi/basic/controller/CustomerController.java                                               |   86 
 src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java                                  |    2 
 src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java                                   |   46 
 src/main/resources/mapper/production/ProductionBomStructureMapper.xml                                          |   53 
 src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java                |    4 
 src/main/java/com/ruoyi/basic/dto/StorageAttachmentDTO.java                                                    |   14 
 src/main/java/com/ruoyi/basic/pojo/Customer.java                                                               |   26 
 src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java                                                        |    8 
 src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java                                       |   27 
 src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java                                       |   17 
 src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java                                            |  267 
 src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java                                        |    2 
 src/main/java/com/ruoyi/safe/service/impl/SafeHazardServiceImpl.java                                           |   13 
 src/main/java/com/ruoyi/approve/pojo/HolidaySettings.java                                                      |    3 
 src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardBindingServiceImpl.java                        |   14 
 src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/ElectricityConsumptionAreaServiceImpl.java     |    9 
 src/main/java/com/ruoyi/sales/pojo/SalesQuotationProduct.java                                                  |   31 
 src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java                                                |    2 
 src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java                                         |  267 
 src/main/java/com/ruoyi/collaborativeApproval/service/impl/StaffContactsPersonalServiceImpl.java               |    8 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamSyncDto.java                        |   15 
 src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java                                                  |    2 
 src/main/java/com/ruoyi/staff/pojo/StaffLeave.java                                                             |   25 
 src/main/java/com/ruoyi/ai/bean/ChatForm.java                                                                  |   15 
 src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java                                  |   35 
 src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceLocationConfig.java                                       |   30 
 src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml                                       |   11 
 src/main/java/com/ruoyi/production/service/ProductionOrderRoutingService.java                                  |   14 
 src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java                                    |   30 
 src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java                                         |   13 
 src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java                                 |   16 
 src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java                                       |   14 
 src/main/java/com/ruoyi/staff/pojo/StaffEducation.java                                                         |   32 
 src/main/java/com/ruoyi/safe/controller/SafeHiddenController.java                                              |   20 
 src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java                                                  |    6 
 src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesNearExpiry.java                                       |   46 
 src/main/java/com/ruoyi/ai/config/SeparateChatAssistantConfig.java                                             |   29 
 src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java                                                     |   69 
 src/main/resources/my-prompt-template3.txt                                                                     |    3 
 src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java                                              |   42 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java                                        |   12 
 src/main/java/com/ruoyi/project/system/controller/SysUserClientController.java                                 |   11 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java                                  |  332 
 src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java                      |   32 
 src/main/resources/mapper/technology/TechnologyRoutingOperationParamMapper.xml                                 |   26 
 src/main/java/com/ruoyi/projectManagement/vo/SearchPlanVo.java                                                 |    3 
 src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java                                              |   28 
 src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java                                       |   18 
 src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java                                                      |   91 
 src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java                                                |   40 
 src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java                                                  |    2 
 src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java                       |    4 
 src/main/java/com/ruoyi/approve/controller/RpaProcessAutomationController.java                                 |   17 
 src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java                                                  |   65 
 src/main/java/com/ruoyi/basic/excel/SupplierManageExcelDto.java                                                |    2 
 src/main/java/com/ruoyi/procurementrecord/pojo/ReturnManagement.java                                           |   38 
 src/main/java/com/ruoyi/safe/dto/SafeHazardRecordDto.java                                                      |   17 
 src/main/java/com/ruoyi/production/mapper/ProductionPlanMapper.java                                            |   32 
 src/main/java/com/ruoyi/sales/pojo/Loss.java                                                                   |   11 
 src/main/java/com/ruoyi/technology/pojo/TechnologyParam.java                                                   |   69 
 src/main/java/com/ruoyi/stock/pojo/StockUninventory.java                                                       |   29 
 src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java                                    |   17 
 src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java                                    |   65 
 src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java                       |    2 
 src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java                         |    9 
 src/main/java/com/ruoyi/projectManagement/service/PlanService.java                                             |    6 
 src/main/java/com/ruoyi/common/utils/file/FileUtils.java                                                       |    4 
 src/main/resources/application-demo.yml                                                                        |  115 
 src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java                            |   40 
 src/main/resources/mapper/production/ProductionAccountMapper.xml                                               |  131 
 src/main/java/com/ruoyi/ai/mapper/AiChatSessionMapper.java                                                     |    7 
 src/main/java/com/ruoyi/ai/service/AiChatSessionService.java                                                   |   22 
 src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperation.java                                        |   61 
 src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java                                    |   27 
 src/main/resources/mapper/account/SalesRefundAmountOrderMapper.xml                                             |    2 
 src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java                                        |    5 
 src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java                                             |   23 
 src/main/resources/mapper/stock/StockInRecordMapper.xml                                                        |   16 
 src/main/java/com/ruoyi/basic/dto/StorageAttachmentVO.java                                                     |   14 
 src/main/resources/mapper/production/ProductionOrderPickMapper.xml                                             |   42 
 src/main/java/com/ruoyi/ai/context/AiSessionUserContext.java                                                   |   35 
 src/main/java/com/ruoyi/project/system/domain/SysDictData.java                                                 |    4 
 src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java                                                 |    7 
 FILE_UPLOAD_README.md                                                                                          |  734 +
 src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml                                          |   32 
 src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java                                    |    5 
 src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java                                                          |   13 
 src/main/java/com/ruoyi/warehouse/pojo/DocumentClassification.java                                             |    7 
 src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java                                        |    2 
 src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java                           |   34 
 src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java                                      |   74 
 src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java                                               |    2 
 src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java                                |   25 
 doc/20260428_create_table_ai_chat_session.sql                                                                  |   16 
 src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java                                     |   25 
 src/main/java/com/ruoyi/staff/pojo/SchemeInsuranceDetail.java                                                  |   30 
 src/main/java/com/ruoyi/waterrecord/controller/WaterRecordController.java                                      |   15 
 src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java                                                      |   23 
 src/main/resources/mapper/technology/TechnologyParamMapper.xml                                                 |   22 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java                                          |   21 
 src/main/java/com/ruoyi/oA/service/impl/OaProjectServiceImpl.java                                              |   14 
 src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java                                                       |   37 
 src/main/java/com/ruoyi/stock/pojo/StockInRecord.java                                                          |   37 
 src/main/java/com/ruoyi/staff/controller/AnalyticsController.java                                              |    2 
 src/main/java/com/ruoyi/waterrecord/service/impl/WaterRecordServiceImpl.java                                   |    7 
 src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java                                      |    4 
 src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java                                              |   50 
 src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java                          |   36 
 /dev/null                                                                                                      |   59 
 src/main/java/com/ruoyi/collaborativeApproval/dto/MeetSummaryDto.java                                          |    1 
 src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java                                                          |   25 
 src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java                                     |   11 
 src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SparePartsRequisitionRecord.java                        |   69 
 src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java                                    |   35 
 1,006 files changed, 30,852 insertions(+), 8,711 deletions(-)

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..4261f1a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.{java,xml,yml,yaml,md,properties,sql,js,ts,vue,html,css,scss,json}]
+charset = utf-8
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
index b60b03f..d135432 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
 !gradle/wrapper/gradle-wrapper.jar
 
 target/
+/${project.build.directory}/
 !.mvn/wrapper/maven-wrapper.jar
 
 ######################################################################
@@ -43,4 +44,4 @@
 
 !*/build/*.java
 !*/build/*.html
-!*/build/*.xml
\ No newline at end of file
+!*/build/*.xml
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..edf1666
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,15 @@
+# 缂栫爜涓庝腑鏂囧鐞嗚鍒�
+
+鏈」鐩悗缁墍鏈変唬鐮佷慨鏀瑰繀椤婚伒瀹堜互涓嬭鍒欙細
+
+1. 鏂板缓鏂囦欢缁熶竴浣跨敤 `UTF-8` 缂栫爜锛屼笖涓嶅甫 `BOM`銆�
+2. 淇敼宸叉湁鏂囦欢鍓嶏紝鍏堟鏌ュ師鏂囦欢缂栫爜锛涘鏋滀笉鏄� `UTF-8`锛岄粯璁ゅ厛淇濇寔鍘熺紪鐮侊紝閬垮厤鎶婁腑鏂囧啓鍧忋��
+3. 涓枃鍐呭蹇呴』鐩存帴淇濈暀锛屼笉鍏佽杞箟鎴� `\\uXXXX`銆�
+4. 杈撳嚭銆佹彁浜ゃ�佺敓鎴愪唬鐮佹椂涓嶅緱鍑虹幇涔辩爜锛涘鏋滅粓绔樉绀哄紓甯革紝蹇呴』鍏堟牎楠屾枃浠剁湡瀹炲瓧鑺傜紪鐮侊紝鍐嶇户缁慨鏀广��
+5. 娑夊強鎵归噺鏇挎崲鏃讹紝鍙兘鍦ㄧ‘璁ょ紪鐮佸畨鍏ㄥ悗鎵ц锛涗笉鑳戒负浜嗘壒閲忚縼绉绘妸涓枃鍐呭鏀瑰潖銆�
+
+鎺ㄨ崘鍋氭硶锛�
+
+- 浼樺厛渚濊禆椤圭洰鏍圭洰褰� `.editorconfig`銆�
+- 淇敼鍓嶅厛纭鏂囦欢缂栫爜锛屽啀閫夋嫨瀵瑰簲鐨勫啓鍥炴柟寮忋��
+- 瀵瑰寘鍚ぇ閲忎腑鏂囨敞閲娿�佸瓧绗︿覆鐨勬枃浠讹紝浼樺厛灏忚寖鍥翠慨鏀瑰苟鍙婃椂缂栬瘧楠岃瘉銆�
diff --git a/FILE_UPLOAD_README.md b/FILE_UPLOAD_README.md
new file mode 100644
index 0000000..558dc85
--- /dev/null
+++ b/FILE_UPLOAD_README.md
@@ -0,0 +1,734 @@
+# 鏂囦欢涓婁紶鍔熻兘璇存槑
+
+鏈枃妗e熀浜庝互涓嬩唬鐮佹暣鐞嗭細
+
+- `src/main/java/com/ruoyi/basic/utils/FileUtil.java`
+- `src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java`
+- `src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java`
+- `src/main/java/com/ruoyi/project/common/CommonController.java`
+- `src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java`
+
+鐢ㄤ簬璇存槑鏈」鐩腑鏂囦欢涓婁紶銆侀檮浠剁粦瀹氥�佹枃浠堕瑙�/涓嬭浇鐨勬暣浣撹璁★紝浠ュ強 `FileUtil` 涓瘡涓柟娉曠殑浣滅敤銆�
+
+## 1. 鏁翠綋璁捐
+
+鏈」鐩殑鏂囦欢浣撶郴鍒嗘垚涓ゅ眰锛�
+
+- `storage_blob`锛氬瓨鏂囦欢瀹炰綋淇℃伅
+  - 鍘熷鏂囦欢鍚�
+  - 鍞竴鏂囦欢鍚� `uidFilename`
+  - 鏂囦欢璺緞 `path`
+  - 鏂囦欢澶у皬 `byteSize`
+  - 鏂囦欢绫诲瀷 `contentType`
+  - 鍏叡璁块棶鏍囪瘑 `resourceKey`
+- `storage_attachment`锛氬瓨鏂囦欢鍜屼笟鍔¤褰曠殑鍏宠仈鍏崇郴
+  - `application`锛氭枃浠剁敤閫�
+  - `recordType`锛氫笟鍔¤褰曠被鍨�
+  - `recordId`锛氫笟鍔¤褰曚富閿�
+  - `storageBlobId`锛氬叧鑱旂殑鏂囦欢涓昏〃 id
+
+鍙互鐞嗚В涓猴細
+
+- `storage_blob` 璐熻矗鈥滄枃浠舵湰韬��
+- `storage_attachment` 璐熻矗鈥滄枃浠舵寕鍦ㄥ摢鏉′笟鍔℃暟鎹笂鈥�
+
+## 2. 涓婁紶娴佺▼
+
+### 2.1 鏅�氫笂浼�
+
+鎺ュ彛锛�
+
+- `POST /common/upload`
+
+鎺у埗鍣ㄤ綅缃細
+
+- `src/main/java/com/ruoyi/project/common/CommonController.java`
+
+鍏ュ弬锛�
+
+- 琛ㄥ崟瀛楁鍚嶏細`files`
+- 绫诲瀷锛歚List<MultipartFile>`
+
+浠g爜閫昏緫锛�
+
+1. 鍓嶇鍏堣皟鐢� `/common/upload`
+2. `CommonController.upload()` 璋冪敤 `storageBlobService.upload(files, false)`
+3. 鏈嶅姟灞備繚瀛樻枃浠跺厓鏁版嵁鍒� `storage_blob`
+4. 杩斿洖 `StorageBlobVO` 鍒楄〃锛岄噷闈㈤�氬父浼氬甫锛�
+   - 鏂囦欢 id
+   - 鍘熷鏂囦欢鍚�
+   - 鍞竴鏂囦欢鍚�
+   - 棰勮鍦板潃 `previewURL`
+   - 涓嬭浇鍦板潃 `downloadURL`
+
+璇存槑锛�
+
+- 姝ゆ椂鍙槸鈥滀笂浼犱簡鏂囦欢鈥�
+- 杩樻病鏈夊拰鍏蜂綋涓氬姟鍗曟嵁寤虹珛鍏崇郴
+
+### 2.2 鍏叡涓婁紶
+
+鎺ュ彛锛�
+
+- `POST /common/public/upload`
+
+浠g爜閫昏緫锛�
+
+- `CommonController.publicUpload()` 璋冪敤 `storageBlobService.upload(files, true)`
+
+璇存槑锛�
+
+- 璇ユ帴鍙d笂浼犵殑鏂囦欢璧扳�滃叕鍏辨枃浠垛�濇ā寮�
+- 鎺у埗鍣ㄦ敞閲婂凡鏄庣‘璇存槑锛氭案涔呮湁鏁堬紝鎱庣敤
+- 瀵瑰簲 URL 鏋勫缓鏃讹紝鍙兘璧� `publicKey` 鍙傛暟锛岃�屼笉鏄复鏃� `token`
+
+## 3. 闄勪欢缁戝畾娴佺▼
+
+涓婁紶瀹屾垚鍚庯紝濡傛灉闇�瑕佹妸鏂囦欢缁戝畾鍒版煇鏉′笟鍔¤褰曪紝闇�瑕佸啀璋冪敤闄勪欢鎺ュ彛銆�
+
+鎺ュ彛锛�
+
+- `POST /storageAttachment/add`
+
+鎺у埗鍣ㄤ綅缃細
+
+- `src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java`
+
+鏍稿績璇锋眰瀵硅薄锛�
+
+- `StorageAttachmentDTO`
+
+鍏朵腑缁ф壙浜� `StorageAttachment`锛屽苟棰濆鍖呭惈锛�
+
+- `storageBlobDTOs`锛氬緟缁戝畾鐨勬枃浠跺垪琛�
+
+甯哥敤瀛楁鍚箟锛�
+
+- `application`锛氭枃浠剁敤閫�
+- `recordType`锛氫笟鍔$被鍨�
+- `recordId`锛氫笟鍔′富閿�
+- `storageBlobDTOs[].id`锛氫笂浼犳垚鍔熷悗杩斿洖鐨勬枃浠� id
+
+绀轰緥璇锋眰浣擄細
+
+```json
+{
+  "application": "file",
+  "recordType": "common_file",
+  "recordId": 1001,
+  "storageBlobDTOs": [
+    {
+      "id": 12,
+      "application": "file"
+    },
+    {
+      "id": 13,
+      "application": "file"
+    }
+  ]
+}
+```
+
+缁戝畾閫昏緫璇存槑锛�
+
+1. 鍏堜笂浼犳枃浠讹紝鎷垮埌 `storage_blob.id`
+2. 鍐嶈皟鐢� `/storageAttachment/add`
+3. 鏈嶅姟灞傛渶缁堜細閫氳繃 `FileUtil` 淇濆瓨 `storage_attachment`
+4. 鍚庣画鍗冲彲鎸変笟鍔¤褰曟煡璇㈠嚭璇ヨ褰曚笅鐨勯檮浠�
+
+## 4. 鏌ヨ涓庡垹闄ら檮浠�
+
+### 4.1 鏌ヨ闄勪欢鍒楄〃
+
+鎺ュ彛锛�
+
+- `GET /storageAttachment/list`
+
+璇存槑锛�
+
+- 鎸� `StorageAttachmentDTO` 涓殑鏉′欢鏌ヨ
+- 甯歌鏉′欢鏄� `application`銆乣recordType`銆乣recordId`
+- 杩斿洖缁撴灉鏈川涓婃槸鍜屼笟鍔¤褰曞叧鑱斿悗鐨勬枃浠跺垪琛�
+
+### 4.2 鍒犻櫎闄勪欢
+
+鎺ュ彛锛�
+
+- `DELETE /storageAttachment/delete`
+
+璇锋眰浣擄細
+
+- `List<Long> ids`
+
+璇存槑锛�
+
+- 杩欓噷鐨� `ids` 鏄檮浠跺叧鑱旇〃 id锛屼竴鑸槸 `storage_attachment.id`
+- 鍒犻櫎鏃堕�氬父涓嶄粎浼氬垹鍏宠仈鍏崇郴锛屼篃浼氳繘涓�姝ュ垹闄ゅ搴旀枃浠惰褰�
+
+## 5. 棰勮涓庝笅杞芥祦绋�
+
+### 5.1 涓嬭浇鎺ュ彛
+
+鎺ュ彛锛�
+
+- `GET /common/download/{fileName}`
+
+鏀寔涓ょ璁块棶鏂瑰紡锛�
+
+- 涓存椂閾炬帴锛歚token`
+- 鍏叡閾炬帴锛歚publicKey`
+
+浠g爜閫昏緫锛�
+
+1. 濡傛灉璇锋眰閲屾湁 `publicKey`锛岃蛋 `storageBlobService.getPublicFile(fileName, publicKey)`
+2. 鍚﹀垯璧� `storageBlobService.getFileByToken(fileName, token)`
+3. 鍙栧埌瀹為檯鏂囦欢鍚庯紝璋冪敤 `fileUtil.compressFile(file)` 鍋氬浘鐗囧帇缂╁鐞�
+4. 璁剧疆涓嬭浇鍝嶅簲澶达紝杈撳嚭鏂囦欢娴�
+
+### 5.2 棰勮鎺ュ彛
+
+鎺ュ彛锛�
+
+- `GET /common/preview/{fileName}`
+
+鏀寔涓ょ璁块棶鏂瑰紡锛�
+
+- 涓存椂閾炬帴锛歚token`
+- 鍏叡閾炬帴锛歚publicKey`
+
+浠g爜閫昏緫锛�
+
+1. 鏍¢獙 `token` 鎴� `publicKey`
+2. 鑾峰彇鏂囦欢
+3. 璋冪敤 `fileUtil.compressFile(file)`
+4. 鏍规嵁鏂囦欢鍐呭绫诲瀷杩斿洖 inline 棰勮
+
+## 6. 鏋氫妇鍚箟
+
+### 6.1 `ApplicationTypeEnum`
+
+浣嶇疆锛�
+
+- `src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java`
+
+褰撳墠瀹氫箟鍊硷細
+
+| 鏋氫妇 | type | 璇存槑 |
+|---|---|---|
+| `IMAGE` | `image` | 鍥剧墖绫绘枃浠� |
+| `FILE` | `file` | 鏅�氭枃浠� |
+| `AFTER_FILE` | `after_file` | 鍞悗鐩稿叧鏂囦欢 |
+| `BEFORE_FILE` | `before_file` | 鍞墠/鍓嶇疆鐩稿叧鏂囦欢 |
+| `APK` | `apk` | 瀹夎鍖呮枃浠� |
+
+浣滅敤锛�
+
+- 鐢ㄤ簬鍖哄垎鍚屼竴鏉′笟鍔¤褰曚笅锛屼笉鍚岀敤閫旂殑鏂囦欢
+- `FileUtil` 鐨勫緢澶氭煡璇€�佸垹闄ゃ�佷繚瀛樻柟娉曢兘浼氱敤鍒拌瀛楁
+
+### 6.2 `RecordTypeEnum`
+
+浣嶇疆锛�
+
+- `src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java`
+
+浣滅敤锛�
+
+- 鐢ㄤ簬鏍囪鏂囦欢灞炰簬鍝被涓氬姟璁板綍
+- 渚嬪璐ㄦ銆侀噰璐�佸鎴枫�佸敭鍚庛�佸彴璐︺�侀�氱煡銆佽澶囩瓑妯″潡
+- 涓婁紶瀹屾垚鍚庯紝闄勪欢鏈�缁堥�氳繃 `recordType + recordId` 鍜屼笟鍔℃暟鎹叧鑱�
+
+璇存槑锛�
+
+- 璇ユ灇涓惧�煎緢澶氾紝鏂囨。涓嶉�愪釜灞曞紑
+- 瀹為檯浣跨敤鏃跺繀椤讳紶浠g爜涓凡瀹氫箟鐨� `type` 鍊�
+- 濡傦細
+  - `common_file`
+  - `after_sales_service`
+  - `quality_inspect`
+  - `product`
+  - `notice`
+
+## 7. `FileUtil` 鏂规硶璇存槑
+
+`FileUtil` 鏄湰濂楁枃浠朵笂浼犱綋绯荤殑鏍稿績宸ュ叿绫伙紝涓昏璐熻矗锛�
+
+- 鏂囦欢涓庝笟鍔¤褰曠粦瀹�
+- 鏂囦欢涓庨檮浠跺垹闄�
+- 闄勪欢鏌ヨ
+- 棰勮/涓嬭浇鍦板潃鐢熸垚
+- token 浣跨敤娆℃暟鎺у埗
+- 鍥剧墖鍘嬬缉
+
+涓嬮潰鎸夊姛鑳藉垎缁勮鏄庢瘡涓柟娉曘��
+
+### 7.1 淇濆瓨闄勪欢鍏崇郴
+
+#### 1. `saveStorageAttachment(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, List<StorageBlobDTO> storageBlobDTOS)`
+
+浣滅敤锛�
+
+- 鎸夆�滄枃浠剁敤閫� + 璁板綍绫诲瀷 + 璁板綍 id鈥濅繚瀛橀檮浠跺叧绯�
+
+閫昏緫锛�
+
+1. 鏍¢獙 `application`銆乣recordType`銆乣recordId`
+2. 鍏堝垹闄よ繖缁勪笟鍔¤褰曚笅鐨勬棫闄勪欢
+3. 鎶婃柊鐨� `storageBlobDTOS` 杞垚 `storage_attachment` 璁板綍鍚庢壒閲忔彃鍏�
+
+閫傜敤鍦烘櫙锛�
+
+- 鏌愭潯涓氬姟鏁版嵁閲嶆柊淇濆瓨闄勪欢锛屾棫闄勪欢鏁翠綋鏇挎崲鎴愭柊闄勪欢
+
+#### 2. `saveStorageAttachmentByRecordTypeAndRecordId(String application, RecordTypeEnum recordType, Long recordId, List<StorageBlobDTO> storageBlobDTOS)`
+
+浣滅敤锛�
+
+- 鎸� `recordType + recordId` 淇濆瓨闄勪欢鍏崇郴锛宍application` 鍙寚瀹氾紝涔熷彲浠庢瘡涓枃浠跺璞¢噷璇诲彇
+
+閫昏緫鐗圭偣锛�
+
+- 濡傛灉 `application == null`锛屼細鏍规嵁 `storageBlobDTO.application` 鍒嗗埆鍒犻櫎鏃у叧绯�
+- 濡傛灉闄勪欢鍒楄〃涓虹┖锛屼細鐩存帴鍒犻櫎璇ヤ笟鍔¤褰曠殑闄勪欢鍏崇郴
+- 鎻掑叆鏃朵細鑷姩鍥炲~ `application`
+
+閫傜敤鍦烘櫙锛�
+
+- 涓�娆℃彁浜ら噷鍙兘鍖呭惈澶氱鐢ㄩ�旂殑闄勪欢
+- 鎴栬�呰皟鐢ㄦ柟涓嶆柟渚跨洿鎺ヤ紶鏋氫妇绫诲瀷
+
+### 7.2 鍒犻櫎鏂囦欢涓昏〃 `storage_blob`
+
+#### 3. `deleteStorageBlobs(List<Long> storageBlobIds)`
+
+浣滅敤锛�
+
+- 鎸夋枃浠朵富琛� id 鎵归噺鍒犻櫎鏂囦欢璁板綍
+
+#### 4. `deleteStorageBlobsByStorageAttachmentIds(List<Long> storageAttachmentIds)`
+
+浣滅敤锛�
+
+- 鍏堟牴鎹檮浠跺叧鑱� id 鏌ュ埌 `storageBlobId`
+- 鍐嶅垹闄ゅ搴旂殑鏂囦欢涓昏〃璁板綍
+
+#### 5. `deleteStorageBlobsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum application, RecordTypeEnum recordType, List<Long> recordIds)`
+
+浣滅敤锛�
+
+- 鏍规嵁鐢ㄩ�斻�佽褰曠被鍨嬨�佸涓笟鍔� id锛屾壒閲忓垹闄ゅ搴旂殑鏂囦欢涓昏〃璁板綍
+
+閫傜敤鍦烘櫙锛�
+
+- 鎵归噺鍒犻櫎鏌愮被涓氬姟鏁版嵁鏃讹紝鍚屾椂娓呯悊闄勪欢
+
+#### 6. `deleteStorageBlobsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鏍规嵁 `recordType + recordId` 鍒犻櫎璇ヤ笟鍔¤褰曚笅鎵�鏈夋枃浠朵富琛ㄨ褰�
+
+### 7.3 鍒犻櫎闄勪欢鍏崇郴 `storage_attachment`
+
+#### 7. `deleteStorageAttachmentsByStorageAttachmentIds(List<Long> storageAttachmentIds)`
+
+浣滅敤锛�
+
+- 鍏堝垹闄ら檮浠跺搴旂殑鏂囦欢涓昏〃璁板綍
+- 鍐嶅垹闄ら檮浠跺叧绯昏〃璁板綍
+
+#### 8. `deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鍒犻櫎鎸囧畾鐢ㄩ�斻�佹寚瀹氫笟鍔¤褰曚笅鐨勯檮浠跺叧绯�
+
+鐗圭偣锛�
+
+- 浼氬厛鍒� blob锛屽啀鍒� attachment
+
+#### 9. `deleteStorageAttachmentsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鍒犻櫎鎸囧畾涓氬姟璁板綍涓嬪叏閮ㄩ檮浠跺叧绯伙紝涓嶅尯鍒嗙敤閫�
+
+#### 10. `deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum application, RecordTypeEnum recordType, List<Long> recordIds)`
+
+浣滅敤锛�
+
+- 鎸夊涓笟鍔� id 鎵归噺鍒犻櫎闄勪欢鍏崇郴
+
+### 7.4 鏌ヨ闄勪欢鍏崇郴
+
+#### 11. `getStorageAttachmentsByStorageAttachmentIds(List<Long> storageAttachmentIds)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鏌ヨ `storage_attachment` 璁板綍
+
+#### 12. `getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鎸夌敤閫斻�佷笟鍔$被鍨嬨�佷笟鍔� id 鏌ヨ闄勪欢鍏崇郴
+
+#### 13. `getStorageAttachmentsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$被鍨嬨�佷笟鍔� id 鏌ヨ闄勪欢鍏崇郴
+
+### 7.5 鏌ヨ鏂囦欢淇℃伅 `StorageBlobVO`
+
+#### 14. `getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(StorageAttachmentDTO storageAttachmentDTO)`
+
+浣滅敤锛�
+
+- 閫氳繃 `StorageAttachmentDTO` 鏉′欢鏌ヨ鏂囦欢鍒楄〃
+
+鐗圭偣锛�
+
+- `application` 鍙��
+- 鏈�缁堣繑鍥炵殑鏄甫棰勮/涓嬭浇鍦板潃鐨� `StorageBlobVO`
+
+#### 15. `getStorageBlobVOsByStorageAttachmentIds(List<Long> storageAttachmentIds)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鏌ヨ鏂囦欢鍒楄〃
+
+鐗圭偣锛�
+
+- 浼氳嚜鍔ㄦ瀯寤猴細
+  - `previewURL`
+  - `downloadURL`
+  - `storageAttachmentId`
+
+#### 16. `getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鎸夌敤閫斻�佷笟鍔$被鍨嬨�佷笟鍔� id 鏌ヨ鏂囦欢鍒楄〃
+
+#### 17. `getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$被鍨嬨�佷笟鍔� id 鏌ヨ鏂囦欢鍒楄〃
+
+#### 18. `getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鍜岀 16 涓柟娉曠被浼硷紝浣嗗彲浠ヨ嚜瀹氫箟閾炬帴杩囨湡鏃堕棿
+
+璇存槑锛�
+
+- `expired` 鍗曚綅鏄垎閽�
+- 杩斿洖鐨勯瑙�/涓嬭浇鍦板潃浼氭寜杩欎釜鏃堕棿鐢熸垚绛惧悕
+
+#### 19. `getStorageBlobVOsByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鏌ヨ鏂囦欢鍒楄〃锛屽苟鑷畾涔夐摼鎺ヨ繃鏈熸椂闂�
+
+### 7.6 鏌ヨ闄勪欢瑙嗗浘 `StorageAttachmentVO`
+
+#### 20. `getStorageAttachmentVOSByStorageAttachmentIds(List<Long> storageAttachmentIds)`
+
+浣滅敤锛�
+
+- 鏌ヨ闄勪欢瑙嗗浘瀵硅薄
+
+鐗圭偣锛�
+
+- 姣忔潯闄勪欢璁板綍閲屼細宓屽鑷繁鐨� `storageBlobVOS`
+
+#### 21. `getStorageAttachmentVOSByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鏌ヨ闄勪欢瑙嗗浘锛屽苟鑷畾涔夐摼鎺ヨ繃鏈熸椂闂�
+
+#### 22. `getStorageAttachmentVOSByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$淮搴︽煡璇㈤檮浠惰鍥�
+
+#### 23. `getStorageAttachmentVOSByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$淮搴︽煡璇㈤檮浠惰鍥撅紝骞惰嚜瀹氫箟閾炬帴杩囨湡鏃堕棿
+
+### 7.7 浠呰幏鍙栭瑙堝湴鍧�
+
+#### 24. `getFilePreviewURLByStorageAttachmentIds(List<Long> storageAttachmentIds)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鍒楄〃锛岃繑鍥為瑙堝湴鍧�鍒楄〃
+
+#### 25. `getFilePreviewURLByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鍒楄〃锛岃繑鍥炲甫鑷畾涔夎繃鏈熸椂闂寸殑棰勮鍦板潃鍒楄〃
+
+#### 26. `getFilePreviewURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$淮搴﹁繑鍥為瑙堝湴鍧�鍒楄〃
+
+#### 27. `getFilePreviewURLByApplicationAndRecordTypeAndRecordIdAndExpired(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$淮搴﹁繑鍥炲甫鑷畾涔夎繃鏈熸椂闂寸殑棰勮鍦板潃鍒楄〃
+
+### 7.8 浠呰幏鍙栦笅杞藉湴鍧�
+
+#### 28. `getFileDownloadURLByStorageAttachmentIds(List<Long> storageAttachmentIds)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鍒楄〃锛岃繑鍥炰笅杞藉湴鍧�鍒楄〃
+
+#### 29. `getFileDownloadURLByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鏍规嵁闄勪欢鍏崇郴 id 鍒楄〃锛岃繑鍥炲甫鑷畾涔夎繃鏈熸椂闂寸殑涓嬭浇鍦板潃鍒楄〃
+
+#### 30. `getFileDownloadURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$淮搴﹁繑鍥炰笅杞藉湴鍧�鍒楄〃
+
+#### 31. `getFileDownloadURLByApplicationAndRecordTypeAndRecordIdAndExpired(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鎸変笟鍔$淮搴﹁繑鍥炲甫鑷畾涔夎繃鏈熸椂闂寸殑涓嬭浇鍦板潃鍒楄〃
+
+### 7.9 鏋勫缓绛惧悕 URL
+
+#### 32. `buildSignedPreviewUrl(StorageBlobVO storageBlob)`
+
+浣滅敤锛�
+
+- 浣跨敤绯荤粺榛樿杩囨湡鏃堕棿锛岀敓鎴愰瑙堥摼鎺�
+
+瀹為檯璋冪敤锛�
+
+- 鍐呴儴绛変环浜庤皟鐢� `buildSignedUrl(storageBlob, "/preview/", properties.getExpired())`
+
+#### 33. `buildSignedDownloadUrl(StorageBlobVO storageBlob)`
+
+浣滅敤锛�
+
+- 浣跨敤绯荤粺榛樿杩囨湡鏃堕棿锛岀敓鎴愪笅杞介摼鎺�
+
+瀹為檯璋冪敤锛�
+
+- 鍐呴儴绛変环浜庤皟鐢� `buildSignedUrl(storageBlob, "/download/", properties.getExpired())`
+
+#### 34. `buildSignedUrl(StorageBlobVO storageBlob, String actionPath, BigDecimal expired)`
+
+浣滅敤锛�
+
+- 鏋勫缓缁熶竴鐨勫甫绛惧悕棰勮/涓嬭浇鍦板潃
+
+鏀寔锛�
+
+- `actionPath = "/preview/"`
+- `actionPath = "/download/"`
+
+鏍稿績閫昏緫锛�
+
+1. 鏍¢獙璺緞鍙傛暟鍜屾枃浠朵俊鎭�
+2. 鎷兼帴鍩虹璁块棶鍦板潃
+3. 濡傛灉 `expired == -1`锛屼笉鐢熸垚 token锛岀洿鎺ヨ蛋 `publicKey`
+4. 鍚﹀垯鐢熸垚甯﹁繃鏈熸椂闂寸殑 JWT token
+5. 鎶� token 鐨勪娇鐢ㄦ鏁颁俊鎭啓鍏� Redis
+6. 杩斿洖鏈�缁� URL
+
+閲嶈璇存槑锛�
+
+- `expired` 鍗曚綅涓哄垎閽�
+- 榛樿杩囨湡鏃堕棿涓� 120 鍒嗛挓
+- 闈炴案涔呴摼鎺ヤ細鍙椻�滆繃鏈熸椂闂� + 浣跨敤娆℃暟闄愬埗鈥濆弻閲嶆帶鍒�
+
+### 7.10 token 浣跨敤鎺у埗
+
+#### 35. `cacheTokenUsage(String token, long expiredMillis)`
+
+浣滅敤锛�
+
+- 鎶� token 浣跨敤娆℃暟鍒濆鍖栧埌 Redis
+
+鐗圭偣锛�
+
+- 鍒濆鍊煎啓鍏ヤ负 `0`
+- TTL 涓� token 杩囨湡鏃堕棿淇濇寔涓�鑷�
+
+璇存槑锛�
+
+- 杩欐槸绉佹湁鏂规硶锛屼緵 `buildSignedUrl()` 鍐呴儴璋冪敤
+
+#### 36. `buildTokenUsageKey(String token)`
+
+浣滅敤锛�
+
+- 缁熶竴鐢熸垚 Redis key
+
+鏍煎紡锛�
+
+- `file:token:usage:{token}`
+
+璇存槑锛�
+
+- 杩欐槸绉佹湁鏂规硶
+
+#### 37. `validateTokenUsage(String token)`
+
+浣滅敤锛�
+
+- 鏍¢獙 token 鏄惁杩樿兘缁х画浣跨敤
+
+鏍稿績閫昏緫锛�
+
+1. 浠� Redis 璇诲彇褰撳墠浣跨敤娆℃暟
+2. 濡傛灉娌℃湁鍊硷紝璁や负閾炬帴宸茶繃鏈熸垨宸插け鏁�
+3. 濡傛灉杈惧埌涓婇檺锛岀珛鍗冲垹闄� Redis 璁板綍骞舵姤閿�
+4. 鍚﹀垯鑷涓�娆′娇鐢ㄦ鏁�
+5. 濡傛灉鑷鍚庤揪鍒颁笂闄愶紝鍐嶅垹闄� Redis 璁板綍
+
+璇存槑锛�
+
+- 璇ユ柟娉曢�氬父浼氬湪瀹為檯璁块棶鏂囦欢鏃剁敱鏈嶅姟灞傝皟鐢�
+
+#### 38. `resolveLimit()`
+
+浣滅敤锛�
+
+- 瑙f瀽 token 鍙娇鐢ㄦ鏁颁笂闄�
+
+瑙勫垯锛�
+
+- `properties.getUseLimit() <= 0` 鏃讹紝榛樿杩斿洖 `10`
+
+璇存槑锛�
+
+- 杩欐槸绉佹湁鏂规硶
+
+### 7.11 璺緞涓庡帇缂�
+
+#### 39. `buildRelativePath()`
+
+浣滅敤锛�
+
+- 鐢熸垚鏂囦欢瀛樺偍鐩稿璺緞
+
+鏍煎紡锛�
+
+- `yyyy/MMdd`
+
+渚嬪锛�
+
+- `2026/0430`
+
+鐢ㄩ�旓細
+
+- 涓�鑸敤浜庢寜鏃ユ湡鍒嗙洰褰曚繚瀛樹笂浼犳枃浠�
+
+#### 40. `compressFile(File file)`
+
+浣滅敤锛�
+
+- 瀵瑰浘鐗囪繘琛屽帇缂╋紝闈炲浘鐗囨垨涓嶆弧瓒虫潯浠舵椂杩斿洖鍘熸枃浠�
+
+鍘嬬缉鏉′欢锛�
+
+1. 寮�鍚簡 `properties.getCompress()`
+2. 鏂囦欢鏄浘鐗�
+3. 鏂囦欢澶у皬澶т簬 `properties.getNeedCompressSize()`
+
+澶勭悊閫昏緫锛�
+
+1. 鐩爣鏂囦欢鍚嶄负 `thumb_鍘熸枃浠跺悕`
+2. 濡傛灉鍘嬬缉鏂囦欢宸插瓨鍦紝鐩存帴澶嶇敤
+3. 浣跨敤 `Thumbnailator` 鎸夊師灏哄鍘嬬缉鐢昏川
+4. 濡傛灉鍘嬬缉澶辫触锛岄檷绾ц繑鍥炲師鏂囦欢
+
+璇存槑锛�
+
+- 褰撳墠涓嬭浇鍜岄瑙堟帴鍙i兘浼氳皟鐢ㄨ繖涓柟娉�
+
+#### 41. `isImage(String fileName)`
+
+浣滅敤锛�
+
+- 绠�鍗曞垽鏂枃浠舵槸鍚︽槸鍥剧墖
+
+鏀寔鍚庣紑锛�
+
+- `jpg`
+- `jpeg`
+- `png`
+
+璇存槑锛�
+
+- 杩欐槸绉佹湁鏂规硶锛屼緵 `compressFile()` 浣跨敤
+
+## 8. 鎺ㄨ崘浣跨敤椤哄簭
+
+涓氬姟涓婃渶甯歌鐨勬帴鍏ラ『搴忓涓嬶細
+
+1. 鍓嶇涓婁紶鏂囦欢鍒� `/common/upload`
+2. 鎷垮埌杩斿洖缁撴灉涓殑鏂囦欢 id
+3. 涓氬姟淇濆瓨鏃惰皟鐢� `/storageAttachment/add`
+4. 浼犲叆 `application + recordType + recordId + storageBlobDTOs`
+5. 鍚庣画椤甸潰鍥炴樉鏃舵寜涓氬姟鏉′欢璋冪敤闄勪欢鏌ヨ
+6. 鍓嶇浣跨敤杩斿洖鐨� `previewURL` 鎴� `downloadURL`
+
+## 9. 甯歌娉ㄦ剰鐐�
+
+### 9.1 鍏堜笂浼狅紝鍐嶇粦瀹�
+
+- `/common/upload` 鍙礋璐f枃浠跺叆搴�
+- `/storageAttachment/add` 鎵嶆槸鍜屼笟鍔℃暟鎹缓绔嬪叧绯�
+
+### 9.2 `application` 寰堥噸瑕�
+
+- 鍚屼竴鏉� `recordId` 涓嬪彲鑳芥湁澶氱粍涓嶅悓鐢ㄩ�旈檮浠�
+- 鍒犻櫎鍜屾煡璇㈡椂锛岀粡甯镐緷璧� `application`
+
+### 9.3 涓嬭浇閾炬帴涓嶆槸姘镐箙鏈夋晥
+
+- 鏅�氶摼鎺ヤ竴鑸�氳繃 JWT token 鎺у埗
+- 鍚屾椂鍙楄繃鏈熸椂闂村拰浣跨敤娆℃暟闄愬埗
+
+### 9.4 鍏叡鏂囦欢瑕佹厧鐢�
+
+- `public/upload` 涓婁紶鐨勬枃浠跺彲璧版案涔呭叕寮�璁块棶
+- 閫傚悎鍏紑璧勬簮锛屼笉閫傚悎鏁忔劅鏂囦欢
+
+### 9.5 鍥剧墖棰勮/涓嬭浇鍙兘杩斿洖鍘嬬缉鏂囦欢
+
+- 褰撳墠鎺у埗鍣ㄥ湪涓嬭浇鍜岄瑙堝墠閮戒細璋冪敤 `compressFile()`
+- 澶у浘鍦ㄨ闂椂鍙兘浣跨敤鍘嬬缉鍚庣殑鍓湰
+
+## 10. 涓�鍙ヨ瘽鎬荤粨
+
+鏈」鐩殑鏂囦欢涓婁紶鏂规鏄�滀袱闃舵妯″瀷鈥濓細
+
+- 绗竴闃舵涓婁紶鏂囦欢锛岀敓鎴� `storage_blob`
+- 绗簩闃舵缁戝畾涓氬姟锛岀敓鎴� `storage_attachment`
+
+鑰� `FileUtil` 鍒欒礋璐f妸鈥滀笂浼犲悗鐨勬枃浠垛�濆彉鎴愨�滃彲鏌ヨ銆佸彲棰勮銆佸彲涓嬭浇銆佸彲鍒犻櫎銆佸彲鎺ф椂鏁堚�濈殑瀹屾暣闄勪欢鑳藉姏銆�
diff --git a/doc/20260428_create_table_ai_chat_session.sql b/doc/20260428_create_table_ai_chat_session.sql
new file mode 100644
index 0000000..f490376
--- /dev/null
+++ b/doc/20260428_create_table_ai_chat_session.sql
@@ -0,0 +1,16 @@
+CREATE TABLE IF NOT EXISTS `ai_chat_session` (
+  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '涓婚敭',
+  `memory_id` varchar(64) NOT NULL COMMENT '浼氳瘽ID',
+  `user_id` bigint NOT NULL COMMENT '鐢ㄦ埛ID',
+  `tenant_id` bigint DEFAULT NULL COMMENT '绉熸埛ID',
+  `title` varchar(128) DEFAULT NULL COMMENT '浼氳瘽鏍囬',
+  `last_message` varchar(512) DEFAULT NULL COMMENT '鏈�鍚庝竴鏉℃秷鎭�',
+  `message_count` int NOT NULL DEFAULT 0 COMMENT '娑堟伅鏁伴噺',
+  `last_chat_time` datetime DEFAULT NULL COMMENT '鏈�鍚庤亰澶╂椂闂�',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_ai_chat_session_memory_id` (`memory_id`),
+  KEY `idx_ai_chat_session_user_tenant` (`user_id`, `tenant_id`),
+  KEY `idx_ai_chat_session_last_chat_time` (`last_chat_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='AI鍘嗗彶浼氳瘽鍏冩暟鎹〃';
diff --git a/doc/20260506_add_ai_enabled_to_sys_user.sql b/doc/20260506_add_ai_enabled_to_sys_user.sql
new file mode 100644
index 0000000..7e7ee9d
--- /dev/null
+++ b/doc/20260506_add_ai_enabled_to_sys_user.sql
@@ -0,0 +1,2 @@
+alter table sys_user
+    add ai_enabled tinyint(1) not null default 0 comment '鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級';
diff --git "a/doc/20260506_\347\224\250\346\210\267AI\345\212\237\350\203\275\345\255\227\346\256\265\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md" "b/doc/20260506_\347\224\250\346\210\267AI\345\212\237\350\203\275\345\255\227\346\256\265\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..bce48d5
--- /dev/null
+++ "b/doc/20260506_\347\224\250\346\210\267AI\345\212\237\350\203\275\345\255\227\346\256\265\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md"
@@ -0,0 +1,53 @@
+# 鐢ㄦ埛 AI 鍔熻兘瀛楁鍓嶇鑱旇皟璇存槑
+
+## 鑳屾櫙
+
+鍚庣宸插湪鐢ㄦ埛琛ㄥ鍔犻殣钘忓瓧娈� `ai_enabled`锛岀敤浜庢爣璇嗙敤鎴锋槸鍚﹀紑閫� AI 鍔熻兘銆�  
+璇ュ瓧娈典笉寮�鏀剧粰鐢ㄦ埛璧勬枡缁存姢鎺ュ彛锛堜笉閫氳繃鐢ㄦ埛缂栬緫椤甸潰涓嬪彂/鍥炲啓锛夈��
+
+## 瀛楁瀹氫箟
+
+| 瀛楁 | 绫诲瀷 | 榛樿鍊� | 璇存槑 |
+| --- | --- | --- | --- |
+| ai_enabled | tinyint(1) | 0 | 鏄惁寮�閫� AI 鍔熻兘锛歚0`=鏈紑閫氾紝`1`=宸插紑閫� |
+
+## 鑱旇皟鎺ュ彛
+
+鐧诲綍鍚庤皟鐢細
+
+```http
+GET /getInfo
+```
+
+杩斿洖涓柊澧為《灞傚瓧娈� `aiEnabled`锛�
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "user": {
+    "userId": 1,
+    "userName": "admin"
+  },
+  "aiEnabled": 1,
+  "roles": [
+    "admin"
+  ],
+  "permissions": [
+    "*:*:*"
+  ]
+}
+```
+
+## 鍓嶇浣跨敤寤鸿
+
+1. 鐧诲綍鎴愬姛鍚庢寜鐜版湁娴佺▼璋冪敤 `/getInfo`銆�
+2. 浠庡搷搴旈《灞傝鍙� `aiEnabled`銆�
+3. 鍒ゅ畾閫昏緫寤鸿锛�
+   - `aiEnabled === 1`锛氬睍绀�/鏀惧紑 AI 鐩稿叧鍏ュ彛銆�
+   - 鍏朵粬鍊硷紙`0`銆乣null`銆乣undefined`锛夛細鎸夋湭寮�閫氬鐞嗐��
+
+## 缂撳瓨璇存槑
+
+- `aiEnabled` 宸叉斁鍏ョ櫥褰曠紦瀛樺璞★紙`LoginUser`锛夊苟闅� token 鐢熷懡鍛ㄦ湡绠$悊銆�
+- 缂撳瓨 key 鍓嶇紑锛歚login_tokens:`銆�
diff --git a/doc/add.sql b/doc/add.sql
deleted file mode 100644
index 8902911..0000000
--- a/doc/add.sql
+++ /dev/null
@@ -1,132 +0,0 @@
-
-# 璁惧鍙拌处
-create table `product-inventory-management`.device_repair
-(
-    id                 bigint auto_increment
-        primary key,
-    device_ledger_id   varchar(255) not null comment '璁惧鍙拌处id',
-    repair_time        timestamp    null comment '鎶ヤ慨鏃ユ湡',
-    repair_name        varchar(255) not null comment '鎶ヤ慨浜�',
-    remark             varchar(255) not null comment '鏁呴殰鐜拌薄',
-    maintenance_name   varchar      not null comment '缁翠慨浜�',
-    maintenance_time   timestamp    null comment '缁翠慨鏃堕棿',
-    maintenance_result varchar(255) null comment '缁翠慨缁撴灉',
-    status             int default 0 comment '鐘舵��',
-    create_time        datetime     null comment '褰曞叆鏃堕棿',
-    update_time        datetime     null comment '鏇存柊鏃堕棿',
-    create_user        varchar(255) not null comment '褰曞叆浜�',
-    update_user        varchar(255) not null comment '鏇存柊浜�',
-    tenant_id          bigint       not null comment '绉熸埛id'
-);
-
-# 璁惧缁翠慨
-create table `product-inventory-management`.device_ledger
-(
-    id                           bigint auto_increment
-        primary key,
-    device_name                  varchar(255) not null comment '璁惧鍚嶇О',
-    device_model                 varchar(255) not null comment '瑙勬牸鍨嬪彿',
-    supplier_name                varchar(255) not null comment '渚涘簲鍟�',
-    unit                         varchar(255) not null comment '鍗曚綅',
-    number                       decimal      not null comment '鏁伴噺',
-    tax_including_price_unit     decimal      not null comment '鍚◣鍗曚环',
-    tax_including_price_total    decimal      not null comment '鍚◣鎬讳环',
-    tax_rate                     decimal      not null comment '绋庣巼',
-    un_tax_including_price_total decimal      not null comment '涓嶅惈绋庢�讳环',
-    create_time                  timestamp    null comment '褰曞叆鏃堕棿',
-    update_time                  timestamp    null comment '鏇存柊鏃堕棿',
-    create_user                  varchar(255) not null comment '褰曞叆浜�',
-    update_user                  varchar(255) not null comment '鏇存柊浜�',
-    tenant_id                    bigint       not null comment '绉熸埛id'
-);
-
-create table `product-inventory-management`.device_maintenance
-(
-    id                 bigint auto_increment
-        primary key,
-    device_ledger_id   varchar(255) not null comment '璁惧鍙拌处id',
-    maintenance__plan_time        timestamp    null comment '璁″垝淇濆吇鏃ユ湡',
-    maintenance_actually_name   varchar(255)      not null comment '瀹為檯淇濆吇浜�',
-    maintenance_actually_time   timestamp    null comment '瀹為檯淇濆吇鏃ユ湡',
-    maintenance_result int not null  default 0 comment '淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ',
-    status             int not null  default 0 comment '鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨',
-    create_time        datetime     null comment '褰曞叆鏃堕棿',
-    update_time        datetime     null comment '鏇存柊鏃堕棿',
-    create_user        varchar(255) not null comment '褰曞叆浜�',
-    update_user        varchar(255) not null comment '鏇存柊浜�',
-    tenant_id          bigint       not null comment '绉熸埛id'
-);
-
-
-alter table purchase_ledger
-    add payment_method varchar(255) null;
-alter table sales_ledger
-    add payment_method varchar(255) null;
-
-
-alter table payment_registration
-    modify sale_ledger_id bigint default 0 null comment '閿�鍞彴璐d';
-
-
-alter table ticket_registration
-    add enter_date timestamp null;
-
-alter table product_record
-    add 鍒梍name int null comment 'sale_ledger_projectI_id';
-
-# 娣诲姞璁惧鍚嶇О鍜岃鏍煎瀷鍙�
-ALTER TABLE `product-inventory-management`.`device_repair`
-    ADD COLUMN `device_name` varchar(255) NULL AFTER `tenant_id`,
-    ADD COLUMN `device_model` varchar(255) NULL AFTER `device_name`;
-
-ALTER TABLE `product-inventory-management`.`device_maintenance`
-    ADD COLUMN `device_name` varchar(255) NULL AFTER `tenant_id`,
-    ADD COLUMN `device_model` varchar(255) NULL AFTER `device_name`;
-
-
-
-DROP TABLE IF EXISTS storage_attachment;
-CREATE TABLE storage_attachment (
-                                    id BIGINT AUTO_INCREMENT PRIMARY KEY,
-                                    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
-                                    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
-                                    deleted BIGINT DEFAULT 0 NOT NULL,
-                                    record_type SMALLINT DEFAULT 0 NOT NULL,
-                                    record_id BIGINT DEFAULT 0 NOT NULL,
-                                    name VARCHAR(100) DEFAULT '' NOT NULL,
-                                    storage_blob_id BIGINT DEFAULT 0 NOT NULL
-) COMMENT='閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�';
-
-ALTER TABLE storage_attachment
-    COMMENT '閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�';
-
-ALTER TABLE storage_attachment MODIFY record_type SMALLINT COMMENT '鍏宠仈鐨勮褰曠被鍨�';
-ALTER TABLE storage_attachment MODIFY record_id BIGINT COMMENT '鍏宠仈鐨勮褰昳d';
-ALTER TABLE storage_attachment MODIFY name VARCHAR(100) COMMENT '鍚嶇О, 濡�: file, avatar (鍖哄垎鍚屼竴鏉¤褰曚笉鍚岀被鍨嬬殑闄勪欢)';
-ALTER TABLE storage_attachment MODIFY storage_blob_id BIGINT COMMENT '鍏宠仈storage_blob璁板綍id';
-
-CREATE INDEX idx_storage_attachment_on_record
-    ON storage_attachment (record_type, record_id);
-
-
-CREATE TABLE storage_blob (
-                              id BIGINT AUTO_INCREMENT PRIMARY KEY,
-                              create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
-                              key_name VARCHAR(150) DEFAULT '' NOT NULL,
-                              content_type VARCHAR(100) DEFAULT '' NOT NULL,
-                              original_filename VARCHAR(255) DEFAULT '' NOT NULL,
-                              bucket_filename VARCHAR(255) DEFAULT '' NOT NULL,
-                              bucket_name VARCHAR(255) DEFAULT '' NOT NULL,
-                              byte_size BIGINT DEFAULT 0 NOT NULL,
-                              UNIQUE (key_name)
-) COMMENT='閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�';
-
-ALTER TABLE storage_blob
-    COMMENT '閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�';
-
-ALTER TABLE storage_blob MODIFY key_name VARCHAR(150) COMMENT '璧勬簮id';
-ALTER TABLE storage_blob MODIFY content_type VARCHAR(100) COMMENT '璧勬簮绫诲瀷锛屼緥濡侸PG鍥剧墖鐨勮祫婧愮被鍨嬩负image/jpg';
-ALTER TABLE storage_blob MODIFY original_filename VARCHAR(255) COMMENT '鍘熸枃浠跺悕绉�';
-ALTER TABLE storage_blob MODIFY bucket_filename VARCHAR(255) COMMENT '瀛樺偍妗朵腑鏂囦欢鍚�';
-ALTER TABLE storage_blob MODIFY bucket_name VARCHAR(255) COMMENT '瀛樺偍妗跺悕';
-ALTER TABLE storage_blob MODIFY byte_size BIGINT COMMENT '璧勬簮灏哄(瀛楄妭)';
diff --git a/doc/create_table_customer_user.sql b/doc/create_table_customer_user.sql
new file mode 100644
index 0000000..dacbfb4
--- /dev/null
+++ b/doc/create_table_customer_user.sql
@@ -0,0 +1,10 @@
+drop table if exists customer_user;
+create table customer_user
+(
+    id          bigint auto_increment
+        primary key,
+    customer_id bigint not null default 0 comment '瀹㈡埛id',
+    user_id     bigint not null default 0 comment '鐢ㄦ埛id',
+    create_time datetime null comment '褰曞叆鏃堕棿',
+    tenant_id   bigint not null default 0 comment '绉熸埛id'
+);
diff --git a/doc/encoding-rules.md b/doc/encoding-rules.md
new file mode 100644
index 0000000..6aded9e
--- /dev/null
+++ b/doc/encoding-rules.md
@@ -0,0 +1,24 @@
+# 缂栫爜涓庨槻涔辩爜瑙勮寖
+
+鏈」鐩粺涓�閲囩敤浠ヤ笅瑙勫垯锛岄伩鍏嶄腑鏂囦贡鐮佸拰缂栫爜鍐茬獊锛�
+
+## 蹇呴』閬靛畧
+
+1. 鏂板缓鏂囦欢缁熶竴浣跨敤 `UTF-8` 缂栫爜锛屼笖涓嶅甫 `BOM`
+2. 淇敼宸叉湁鏂囦欢鍓嶅厛妫�鏌ュ師鏂囦欢缂栫爜
+3. 濡傛灉鏃ф枃浠朵笉鏄� `UTF-8`锛岄粯璁ゅ厛淇濇寔鍘熺紪鐮侊紝閬垮厤鎶婁腑鏂囧啓鍧�
+4. 涓枃鍐呭鐩存帴淇濈暀锛屼笉瑕佽浆涔夋垚 `\uXXXX`
+5. 杈撳嚭銆佺敓鎴愩�佹壒閲忔浛鎹㈡椂涓嶅緱鍑虹幇涔辩爜
+6. 濡傛灉缁堢鏄剧ず寮傚父锛屽厛鏍¢獙鏂囦欢鐪熷疄瀛楄妭鍜岀紪鐮侊紝鍐嶇户缁慨鏀�
+
+## 鎺ㄨ崘鍋氭硶
+
+- 浼樺厛閬靛惊椤圭洰鏍圭洰褰� `.editorconfig`
+- 瀵瑰寘鍚ぇ閲忎腑鏂囨敞閲娿�佸瓧绗︿覆鐨勬枃浠讹紝浼樺厛灏忚寖鍥翠慨鏀�
+- 鎵归噺鏇挎崲鍓嶅厛鍋氱紪鐮佹娊鏍锋鏌ワ紝鍐嶆墽琛屾壒閲忎慨鏀�
+- 姣忔娑夊強涓枃鍐呭鐨勬壒閲忔敼鍔ㄥ悗锛屽強鏃剁紪璇戞垨妫�鏌� diff
+
+## 椤圭洰鍐呭搴斾綅缃�
+
+- 缂栬緫鍣ㄩ粯璁よ鍒欙細`/.editorconfig`
+- AI 涓庡崗浣滅害鏉燂細`/AGENTS.md`
diff --git "a/doc/\351\207\207\350\264\255\346\231\272\350\203\275\344\275\223\345\244\232\346\226\207\344\273\266\345\210\206\346\236\220\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md" "b/doc/\351\207\207\350\264\255\346\231\272\350\203\275\344\275\223\345\244\232\346\226\207\344\273\266\345\210\206\346\236\220\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..cb9e3cf
--- /dev/null
+++ "b/doc/\351\207\207\350\264\255\346\231\272\350\203\275\344\275\223\345\244\232\346\226\207\344\273\266\345\210\206\346\236\220\345\211\215\347\253\257\350\201\224\350\260\203\350\257\264\346\230\216.md"
@@ -0,0 +1,183 @@
+# 閲囪喘鏅鸿兘浣撳鏂囦欢鍒嗘瀽鍓嶇鑱旇皟璇存槑
+
+## 娴佺▼璇存槑
+
+鍚庣宸叉柊澧為噰璐櫤鑳戒綋澶氭枃浠跺垎鏋愮‘璁ゆ祦绋嬶細
+
+1. 鍓嶇涓婁紶澶氫釜閲囪喘鐩稿叧鏂囦欢锛屽苟闄勫甫鐢ㄦ埛瑕佹眰銆�
+2. 鍚庣鎻愬彇鏂囦欢鍐呭锛屼氦缁欓噰璐櫤鑳戒綋鍒嗘瀽銆�
+3. 鏅鸿兘浣撹繑鍥炲緟瀹㈡埛纭鐨勭粨鏋勫寲 JSON銆�
+4. 鍓嶇灞曠ず鎽樿銆侀闄┿�佺己澶卞瓧娈靛拰寰呭鐞嗘暟鎹��
+5. 瀹㈡埛纭鎴栬ˉ鍏呮暟鎹悗锛屽墠绔皟鐢ㄧ‘璁ゆ帴鍙c��
+6. 鍚庣鏍规嵁纭鍚庣殑鏁版嵁鎵ц瀵瑰簲閲囪喘涓氬姟澶勭悊銆�
+
+鍒嗘瀽鎺ュ彛涓嶄細钀藉簱锛屽彧鏈夌‘璁ゆ帴鍙d細鎵ц涓氬姟澶勭悊銆�
+
+## 鎺ュ彛 1锛氶噰璐鏂囦欢鍒嗘瀽
+
+```http
+POST /purchase-ai/analyze-files
+Content-Type: multipart/form-data
+```
+
+璇锋眰鍙傛暟锛�
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| files | file[] | 鏄� | 澶氭枃浠朵笂浼犲瓧娈碉紝瀛楁鍚嶅繀椤绘槸 `files` |
+| message | string | 鍚� | 鐢ㄦ埛瑕佹眰锛屼緥濡傦細璇锋牴鎹繖浜涢噰璐悎鍚屽拰鏄庣粏鏁寸悊閲囪喘鍙拌处鏁版嵁 |
+| memoryId | string | 鍚� | 浼氳瘽 ID锛屼笉浼犳椂鍚庣浼氳嚜鍔ㄧ敓鎴愬唴閮ㄤ細璇� |
+
+杩斿洖锛�
+
+```http
+Content-Type: text/stream;charset=utf-8
+```
+
+鍓嶇闇�瑕佹嫾鎺ュ畬鏁存祦寮忔枃鏈悗鍐嶆墽琛� `JSON.parse`銆�
+
+杩斿洖 JSON 缁撴瀯绀轰緥锛�
+
+```json
+{
+  "success": true,
+  "businessType": "purchase_ledger",
+  "action": "confirm_required",
+  "description": "宸叉牴鎹枃浠舵暣鐞嗗嚭閲囪喘鍙拌处鑽夌锛岃纭銆�",
+  "confidence": 0.86,
+  "missingFields": [],
+  "warnings": [],
+  "payload": {},
+  "preview": []
+}
+```
+
+瀛楁璇存槑锛�
+
+| 瀛楁 | 璇存槑 |
+| --- | --- |
+| success | 鏄惁鍒嗘瀽鎴愬姛 |
+| businessType | 涓氬姟绫诲瀷锛歚purchase_ledger`銆乣payment_registration`銆乣purchase_return_order`銆乣unknown` |
+| action | 鍥哄畾涓� `confirm_required` |
+| description | 涓枃璇存槑 |
+| confidence | 缃俊搴︼紝0 鍒� 1 |
+| missingFields | 缂哄け瀛楁锛屽墠绔渶瑕佹彁绀虹敤鎴疯ˉ鍏� |
+| warnings | 椋庨櫓鎻愮ず |
+| payload | 寰呭鎴风‘璁ゅ苟鎻愪氦缁欑‘璁ゆ帴鍙g殑鏁版嵁 |
+| preview | 缁欏鎴风‘璁ょ敤鐨勪腑鏂囨憳瑕� |
+
+## 鎺ュ彛 2锛氱‘璁ゅ苟鎵ц涓氬姟澶勭悊
+
+```http
+POST /purchase-ai/analyze-files/confirm
+Content-Type: application/json
+```
+
+璇锋眰浣擄細
+
+```json
+{
+  "businessType": "purchase_ledger",
+  "payload": {
+  }
+}
+```
+
+褰撳墠鏀寔鐨� `businessType`锛�
+
+| businessType | 璇存槑 | 鍚庣澶勭悊 |
+| --- | --- | --- |
+| purchase_ledger | 閲囪喘鍙拌处 | 璋冪敤閲囪喘鍙拌处鏂板/缂栬緫 |
+| payment_registration | 浠樻鐧昏 | 璋冪敤浠樻鐧昏鏂板 |
+| purchase_return_order | 閲囪喘閫�璐у崟 | 璋冪敤閲囪喘閫�璐у崟鏂板 |
+
+纭鎺ュ彛杩斿洖鏅�� `AjaxResult`銆�
+
+## 閲囪喘鍙拌处 Payload 绾﹀畾
+
+閲囪喘鍙拌处纭鎺ㄨ崘浣跨敤涓や釜闆嗗悎锛�
+
+```json
+{
+ "businessType": "purchase_ledger",
+  "payload": {
+    "purchaseLedgers": []
+  }
+}
+```
+
+瀛楁绾﹀畾锛�
+
+- `purchaseLedgers` 鏀鹃噰璐鍗�/閲囪喘鍙拌处涓昏〃鏁版嵁锛屽瓧娈靛悕蹇呴』涓� `PurchaseLedgerDto` 淇濇寔涓�鑷淬��
+- 浜у搧鏄庣粏鏀惧湪姣忔潯 `purchaseLedgers[i].productData` 涓紝瀵瑰簲 `PurchaseLedgerDto` 鐨� `private List<SalesLedgerProduct> productData;`銆�
+- 椤跺眰 `payload.productData` 浠呬綔涓烘棫鏍煎紡鍏煎锛屼笉寤鸿鍓嶇缁х画浣跨敤銆�
+- 鏂囦欢涓殑鈥滈噰璐崟鍙封�濆氨鏄�滈噰璐悎鍚屽彿鈥濓紝鍓嶇鍙互缁熶竴鏄犲皠鎴� `purchaseContractNumber`銆�
+- 鏂囦欢涓殑鈥滈攢鍞崟鍙封�濆氨鏄�滈攢鍞悎鍚屽彿鈥濓紝鍓嶇鍙互缁熶竴鏄犲皠鎴� `salesContractNo`銆�
+- 鏃ユ湡瀛楁缁熶竴浣跨敤 `yyyy-MM-dd`锛屼緥濡� `2026-04-30`锛涗笉瑕佹彁浜� `4/30/26`銆乣2026/4/30`銆乣2026骞�4鏈�30鏃 鎴栧甫鏃跺垎绉掔殑鏍煎紡銆�
+- 閲囪喘鍙拌处涓嶉渶瑕佸墠绔紶瀹℃壒浜猴紝涓嶈鎻愪氦 `approveUserIds`銆乣approverId`銆�
+- `missingFields` 闈㈠悜瀹㈡埛灞曠ず锛屽彧鏀句腑鏂囩己澶遍」锛屼緥濡� `渚涘簲鍟嗗悕绉癭銆乣鍚◣鍗曚环`锛屼笉瑕佸睍绀鸿嫳鏂囧瓧娈靛悕銆�
+- 閲囪喘鍙拌处涓氬姟蹇呭~锛氶噰璐悎鍚屽彿銆佷緵搴斿晢鍚嶇О鎴栦緵搴斿晢ID銆�
+- 浜у搧鏄庣粏涓氬姟蹇呭~锛氫骇鍝佸悕绉般�佽鏍煎瀷鍙枫�佸崟浣嶃�佹暟閲忋�佸惈绋庡崟浠枫�佸惈绋庢�讳环锛涘鏋滃彧鏈夊惈绋庢�讳环鍜屾暟閲忥紝鍚庣浼氳嚜鍔ㄨ绠楀惈绋庡崟浠凤紱濡傛灉鍙湁鍚◣鍗曚环鍜屾暟閲忥紝鍚庣浼氳嚜鍔ㄨ绠楀惈绋庢�讳环銆�
+- 浜у搧鏄庣粏鍙�氳繃 `purchaseContractNumber`銆乣purchaseContractNo`銆乣閲囪喘鍚堝悓鍙穈銆乣閲囪喘鍗曞彿`銆乣閲囪喘璁㈠崟鍙穈 鍏宠仈瀵瑰簲閲囪喘璁㈠崟锛涗篃鍙�氳繃 `salesContractNo`銆乣salesContractNumber`銆乣閿�鍞悎鍚屽彿`銆乣閿�鍞崟鍙穈銆乣閿�鍞鍗曞彿` 杈呭姪鍖归厤銆�
+
+`purchaseLedgers` 鍗曟潯璁板綍鍏佽浣跨敤鐨� `PurchaseLedgerDto` 瀛楁锛�
+
+```text
+entryDateStart, entryDateEnd, id, purchaseContractNumber,
+supplierId, supplierName, isWhite, recorderId, recorderName, salesContractNo,
+salesContractNoId, projectName, entryDate, executionDate, remarks,
+attachmentMaterials, createdAt, updatedAt, salesLedgerId, hasChildren, Type,
+productData, tempFileIds, SalesLedgerFiles, phoneNumber, businessPersonId,
+productId, productModelId, invoiceNumber, invoiceAmount, ticketRegistrationId,
+contractAmount, receiptPaymentAmount, unReceiptPaymentAmount, type,
+paymentMethod, approvalStatus, templateName
+```
+
+绀轰緥锛�
+
+```json
+{
+  "purchaseLedgers": [
+    {
+      "purchaseContractNumber": "CG-2026-001",
+      "supplierName": "鍗楅�氱ず渚嬩緵搴斿晢",
+      "salesContractNo": "XS-2026-001",
+      "projectName": "绀轰緥椤圭洰",
+      "entryDate": "2026-04-30",
+      "executionDate": "2026-04-30",
+      "contractAmount": 120000,
+      "remarks": "鐢辨枃浠跺垎鏋愮敓鎴愶紝寰呯‘璁�",
+      "productData": [
+        {
+          "productCategory": "绀轰緥浜у搧",
+          "specificationModel": "鍨嬪彿A",
+          "unit": "浠�",
+          "quantity": 10,
+          "taxInclusiveUnitPrice": 12000,
+          "taxInclusiveTotalPrice": 120000,
+          "type": 2
+        }
+      ]
+    }
+  ]
+}
+```
+
+## 鍓嶇澶勭悊寤鸿
+
+1. 鐢ㄦ埛閫夋嫨澶氫釜鏂囦欢锛屽~鍐欏垎鏋愯姹傘��
+2. 浣跨敤 `multipart/form-data` 璋冪敤 `/purchase-ai/analyze-files`銆�
+3. 鎷兼帴娴佸紡杩斿洖鏂囨湰銆�
+4. 瀵瑰畬鏁存枃鏈墽琛� `JSON.parse`銆�
+5. 灞曠ず `preview`銆乣warnings`銆乣missingFields` 鍜� `payload`銆�
+6. 濡傛灉 `missingFields` 涓嶄负绌猴紝寮曞鐢ㄦ埛琛ュ厖鎴栫紪杈� `payload`銆�
+7. 鐢ㄦ埛纭鍚庯紝灏� `businessType` 鍜岀‘璁ゅ悗鐨� `payload` 鎻愪氦鍒� `/purchase-ai/analyze-files/confirm`銆�
+
+## 娉ㄦ剰浜嬮」
+
+- 鏂囦欢涓婁紶瀛楁鍚嶅繀椤绘槸 `files`銆�
+- 鍒嗘瀽鎺ュ彛鍙敓鎴愬緟纭鏁版嵁锛屼笉浼氭墽琛屼笟鍔¤惤搴撱��
+- 纭鎺ュ彛鎵嶄細鎵ц涓氬姟澶勭悊銆�
+- 濡傛灉 `payload` 缂哄皯蹇呰涓氬姟 ID锛岀‘璁ゆ帴鍙e彲鑳借繑鍥炰笟鍔℃牎楠岄敊璇��
+- 鍓嶇闇�瑕佹妸 `missingFields` 鏄庣‘灞曠ず缁欑敤鎴枫��
+- AI 杩斿洖鍐呭鎸夊悎娉� JSON 澶勭悊锛屼笉瑕佹寜鏅�氳嚜鐒惰瑷�灞曠ず銆�
diff --git a/pom.xml b/pom.xml
index 553dbf2..e840acd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,44 +15,78 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>2.5.15</version>
+        <version>3.5.13</version>
         <relativePath/>
     </parent>
 
     <properties>
+        <maven.compiler.source>25</maven.compiler.source>
+        <maven.compiler.target>25</maven.compiler.target>
+        <maven.compiler.release>25</maven.compiler.release>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-        <java.version>1.8</java.version>
+        <java.version>25</java.version>
+        <lombok.version>1.18.44</lombok.version>
         <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
-        <pagehelper.spring.boot.starter.version>1.4.7</pagehelper.spring.boot.starter.version>
+        <pagehelper.spring.boot.starter.version>2.1.1</pagehelper.spring.boot.starter.version>
         <fastjson.version>2.0.53</fastjson.version>
         <druid.version>1.2.23</druid.version>
         <commons.io.version>2.13.0</commons.io.version>
         <bitwalker.version>1.21</bitwalker.version>
-        <jwt.version>0.9.1</jwt.version>
+        <jwt.version>0.13.0</jwt.version>
         <kaptcha.version>2.3.3</kaptcha.version>
-        <swagger.version>3.0.0</swagger.version>
+        <knife4j.version>4.5.0</knife4j.version>
+        <springdoc.version>2.8.17</springdoc.version>
+        <swagger.annotations.version>1.6.15</swagger.annotations.version>
         <poi.version>5.2.3</poi.version>
         <oshi.version>6.6.5</oshi.version>
         <velocity.version>2.3</velocity.version>
         <!-- override dependency version -->
-        <tomcat.version>9.0.102</tomcat.version>
+        <!--        <tomcat.version>9.0.102</tomcat.version>-->
         <minio.version>8.4.3</minio.version>
         <okhttp.version>4.9.0</okhttp.version>
-        <hutool.version>5.8.18</hutool.version>
-        <logback.version>1.2.13</logback.version>
-        <spring-security.version>5.7.12</spring-security.version>
-        <spring-framework.version>5.3.39</spring-framework.version>
-        <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
+        <hutool.version>5.8.43</hutool.version>
+        <!--        <logback.version>1.2.13</logback.version>-->
+        <!--        <spring-security.version>5.7.12</spring-security.version>-->
+        <!--        <spring-framework.version>5.3.39</spring-framework.version>-->
+        <mybatis-plus.version>3.5.16</mybatis-plus.version>
         <getui-sdk.version>1.0.7.0</getui-sdk.version>
+        <jsqlparser.version>4.9</jsqlparser.version>
+        <thumbnailator.version>0.4.20</thumbnailator.version>
+        <langchain4j.version>1.0.0-beta3</langchain4j.version>
     </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>dev.langchain4j</groupId>
+                <artifactId>langchain4j-bom</artifactId>
+                <version>${langchain4j.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>dev.langchain4j</groupId>
+                <artifactId>langchain4j-community-bom</artifactId>
+                <version>${langchain4j.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
 
     <dependencies>
         <!-- ruoyi-springboot2 / swagger knife4j 閰嶇疆 -->
         <dependency>
             <groupId>com.github.xiaoymin</groupId>
-            <artifactId>knife4j-spring-boot-starter</artifactId>
-            <version>3.0.3</version>
+            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
+            <version>${knife4j.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+            <version>${springdoc.version}</version>
         </dependency>
 
         <!-- SpringBoot 鏍稿績鍖� -->
@@ -99,10 +133,48 @@
             <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-mongodb</artifactId>
+        </dependency>
+
         <!-- pool 瀵硅薄姹� -->
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-pool2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-pinecone</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-reactor</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>dev.langchain4j</groupId>
+            <artifactId>langchain4j-mcp</artifactId>
         </dependency>
 
         <!-- Mysql椹卞姩鍖� -->
@@ -110,13 +182,14 @@
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <scope>runtime</scope>
+            <version>8.0.33</version>
         </dependency>
 
         <!-- FreeMarker 妯℃澘寮曟搸锛氬鐞嗗彉閲忓崰浣嶇 -->
         <dependency>
             <groupId>org.freemarker</groupId>
             <artifactId>freemarker</artifactId>
-            <version>2.3.32</version>
+            <version>2.3.33</version>
         </dependency>
 
         <!-- pagehelper 鍒嗛〉鎻掍欢 -->
@@ -129,14 +202,26 @@
         <!-- 闃块噷鏁版嵁搴撹繛鎺ユ睜 -->
         <dependency>
             <groupId>com.alibaba</groupId>
-            <artifactId>druid-spring-boot-starter</artifactId>
+            <artifactId>druid-spring-boot-3-starter</artifactId>
             <version>${druid.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis</groupId>
+            <artifactId>mybatis</artifactId>
+            <version>${mybatis-plus.version}</version>
         </dependency>
 
         <!--mybatis-plus-->
         <dependency>
             <groupId>com.baomidou</groupId>
-            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
+            <version>${mybatis-plus.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-jsqlparser</artifactId>
             <version>${mybatis-plus.version}</version>
         </dependency>
 
@@ -145,6 +230,12 @@
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-generator</artifactId>
             <version>${mybatis-plus.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.jsqlparser</groupId>
+            <artifactId>jsqlparser</artifactId>
+            <version>${jsqlparser.version}</version>
         </dependency>
 
         <!-- 鑷畾涔夐獙璇佹敞瑙� -->
@@ -189,35 +280,37 @@
         <!-- Token鐢熸垚涓庤В鏋�-->
         <dependency>
             <groupId>io.jsonwebtoken</groupId>
-            <artifactId>jjwt</artifactId>
+            <artifactId>jjwt-api</artifactId>
             <version>${jwt.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-impl</artifactId>
+            <version>${jwt.version}</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-jackson</artifactId>
+            <version>${jwt.version}</version>
+            <scope>runtime</scope>
         </dependency>
 
         <!-- Jaxb -->
         <dependency>
-            <groupId>javax.xml.bind</groupId>
-            <artifactId>jaxb-api</artifactId>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
         </dependency>
 
         <!-- Swagger3渚濊禆 -->
         <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-boot-starter</artifactId>
-            <version>${swagger.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>io.swagger</groupId>
-                    <artifactId>swagger-models</artifactId>
-                </exclusion>
-            </exclusions>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>${swagger.annotations.version}</version>
         </dependency>
 
         <!-- 闃叉杩涘叆swagger椤甸潰鎶ョ被鍨嬭浆鎹㈤敊璇紝鎺掗櫎3.0.0涓殑寮曠敤锛屾墜鍔ㄥ鍔�1.6.2鐗堟湰 -->
-        <dependency>
-            <groupId>io.swagger</groupId>
-            <artifactId>swagger-models</artifactId>
-            <version>1.6.2</version>
-        </dependency>
 
         <!-- 鑾峰彇绯荤粺淇℃伅 -->
         <dependency>
@@ -268,6 +361,7 @@
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
         </dependency>
 
 
@@ -315,22 +409,22 @@
             <version>${getui-sdk.version}</version>
             <scope>compile</scope>
         </dependency>
-    
+
         <!--hutool宸ュ叿鍖�-->
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
             <version>${hutool.version}</version>
         </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
-            <version>5.8.43</version>
-        </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.datatype</groupId>
             <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>${thumbnailator.version}</version>
         </dependency>
 
     </dependencies>
@@ -339,11 +433,24 @@
         <finalName>${project.artifactId}</finalName>
         <plugins>
             <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.14.1</version>
+                <configuration>
+                    <release>${maven.compiler.release}</release>
+                    <proc>full</proc>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                            <version>${lombok.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+            <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
-                <configuration>
-                    <fork>true</fork> <!-- 濡傛灉娌℃湁璇ラ厤缃紝devtools涓嶄細鐢熸晥 -->
-                </configuration>
             </plugin>
         </plugins>
     </build>
diff --git a/src/main/java/com/ruoyi/CodeGenerator.java b/src/main/java/com/ruoyi/CodeGenerator.java
index 6356273..721245b 100644
--- a/src/main/java/com/ruoyi/CodeGenerator.java
+++ b/src/main/java/com/ruoyi/CodeGenerator.java
@@ -5,7 +5,8 @@
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.generator.FastAutoGenerator;
-import com.baomidou.mybatisplus.generator.config.*;
+import com.baomidou.mybatisplus.generator.config.GlobalConfig;
+import com.baomidou.mybatisplus.generator.config.OutputFile;
 import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
 import com.baomidou.mybatisplus.generator.config.po.TableField;
 import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
@@ -19,11 +20,11 @@
 // 婕旂ず渚嬪瓙锛屾墽琛� main 鏂规硶鎺у埗鍙拌緭鍏ユā鍧楄〃鍚嶅洖杞﹁嚜鍔ㄧ敓鎴愬搴旈」鐩洰褰曚腑
 public class CodeGenerator {
 
-    public static String database_url = "jdbc:mysql://1.15.17.182:9999/product-inventory-management-new";
+    public static String database_url = "jdbc:mysql://localhost:3300/product-inventory-management-new-pro";
     public static String database_username = "root";
-    public static String database_password= "xd@123456..";
+    public static String database_password= "root";
     public static String author = "鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃";
-    public static String model = "staff"; // 妯″潡
+    public static String model = "sales"; // 妯″潡
     public static String setParent = "com.ruoyi."+ model; // 鍖呰矾寰�
     public static String tablePrefix = ""; // 璁剧疆杩囨护琛ㄥ墠缂�
     public static void main(String[] args) {
@@ -81,7 +82,7 @@
                                     new Column("update_time", FieldFill.INSERT_UPDATE),
                                     new Column("create_user", FieldFill.INSERT),
                                     new Column("update_user", FieldFill.INSERT_UPDATE),
-                                    new Column("tenant_id", FieldFill.INSERT)
+                                    new Column("dept_id", FieldFill.INSERT)
                             )
                             .idType(IdType.AUTO) // 鑷涓婚敭
 
@@ -118,9 +119,8 @@
         StringBuilder help = new StringBuilder();
         help.append("璇疯緭鍏�" + tip + "锛�");
         System.out.println(help.toString());
-        if (scanner.hasNext()) {
-            String ipt = scanner.next();
-
+        if (scanner.hasNextLine()) {
+            String ipt = scanner.nextLine();
             if (StringUtils.isNotBlank(ipt)) {
                 return ipt;
             }
diff --git a/src/main/java/com/ruoyi/RuoYiServletInitializer.java b/src/main/java/com/ruoyi/RuoYiServletInitializer.java
index 9d82a23..709d23b 100644
--- a/src/main/java/com/ruoyi/RuoYiServletInitializer.java
+++ b/src/main/java/com/ruoyi/RuoYiServletInitializer.java
@@ -3,6 +3,9 @@
 import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+
 /**
  * web瀹瑰櫒涓繘琛岄儴缃�
  * 
@@ -15,4 +18,9 @@
     {
         return application.sources(RuoYiApplication.class);
     }
+
+    @Override
+    public void onStartup(ServletContext servletContext) throws ServletException {
+
+    }
 }
diff --git a/src/main/java/com/ruoyi/ScheduleTask.java b/src/main/java/com/ruoyi/ScheduleTask.java
index 2cb1ad7..adddc70 100644
--- a/src/main/java/com/ruoyi/ScheduleTask.java
+++ b/src/main/java/com/ruoyi/ScheduleTask.java
@@ -5,7 +5,7 @@
 import com.ruoyi.project.system.mapper.SysNoticeMapper;
 import com.ruoyi.safe.mapper.SafeTrainingMapper;
 import com.ruoyi.safe.pojo.SafeTraining;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
@@ -14,14 +14,13 @@
 import java.util.List;
 
 @Component
+@RequiredArgsConstructor
 //瀹氭椂浠诲姟姹囨��
 public class ScheduleTask {
 
-    @Autowired
-    private SafeTrainingMapper safeTrainingMapper;
+    private final SafeTrainingMapper safeTrainingMapper;
 
-    @Autowired
-    private SysNoticeMapper noticeMapper;
+    private final SysNoticeMapper noticeMapper;
 
     //瀹氭椂浠诲姟(15鍒嗛挓鎵ц涓�娆�--鍒ゆ柇鍩硅璁″垝鏁版嵁,鐘舵�佸仛鍙樻洿)
     @Scheduled(cron = "0 0/15 * * * ?")
diff --git a/src/main/java/com/ruoyi/account/controller/AccountExpenseController.java b/src/main/java/com/ruoyi/account/controller/AccountExpenseController.java
index 23e2508..4796d33 100644
--- a/src/main/java/com/ruoyi/account/controller/AccountExpenseController.java
+++ b/src/main/java/com/ruoyi/account/controller/AccountExpenseController.java
@@ -2,23 +2,20 @@
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.account.dto.ReportDateDto;
-import com.ruoyi.account.mapper.AccountIncomeMapper;
 import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.AccountIncome;
 import com.ruoyi.account.service.AccountExpenseService;
-import com.ruoyi.account.service.AccountFileService;
 import com.ruoyi.account.service.AccountIncomeService;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.annotation.Resource;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.Date;
 import java.util.List;
 
@@ -27,7 +24,7 @@
  */
 @RestController
 @RequestMapping("/account/accountExpense")
-@Api(tags = "璐㈠姟绠$悊--鏀嚭绠$悊")
+@Tag(name = "璐㈠姟绠$悊--鏀嚭绠$悊")
 public class AccountExpenseController {
 
     @Resource
@@ -43,7 +40,7 @@
      * @return
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody AccountExpense accountExpense) {
         accountExpense.setInputTime(new Date());
         LoginUser loginUser = SecurityUtils.getLoginUser();
@@ -57,7 +54,7 @@
      * @return
      */
     @DeleteMapping("/del")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delQualityInspect(@RequestBody List<Integer> ids) {
         if(CollectionUtils.isEmpty(ids)){
             return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -72,7 +69,7 @@
      * @return
      */
     @PostMapping("/update")
-    @ApiOperation("淇敼")
+    @Operation(summary = "淇敼")
     public AjaxResult update(@RequestBody AccountExpense accountExpense) {
         return AjaxResult.success(accountExpenseService.updateById(accountExpense));
     }
@@ -84,7 +81,7 @@
      * @return
      */
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult accountExpenseListPage(Page page, AccountExpense accountExpense) {
         return AjaxResult.success(accountExpenseService.accountExpenseListPage(page, accountExpense));
     }
@@ -95,7 +92,7 @@
      * @return
      */
     @GetMapping("/{id}")
-    @ApiOperation("璇︽儏")
+    @Operation(summary = "璇︽儏")
     public AjaxResult accountExpenseDetail(@PathVariable("id") Integer id) {
         return AjaxResult.success(accountExpenseService.getById(id));
     }
@@ -106,7 +103,7 @@
      * @param accountExpense
      */
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭")
+    @Operation(summary = "瀵煎嚭")
     public void accountExpenseExport(HttpServletResponse response,AccountExpense accountExpense) {
         accountExpenseService.accountExpenseExport(response, accountExpense);
     }
@@ -117,7 +114,7 @@
      * @return
      */
     @GetMapping("/report/forms")
-    @ApiOperation("璐㈠姟鎶ヨ〃鍥捐〃鏌ヨ")
+    @Operation(summary = "璐㈠姟鎶ヨ〃鍥捐〃鏌ヨ")
     public AjaxResult report(DateQueryDto dateQueryDto) {
         return AjaxResult.success(accountExpenseService.report(dateQueryDto));
     }
@@ -127,7 +124,7 @@
      * @return
      */
     @GetMapping("/report/analysis")
-    @ApiOperation("璐㈠姟鎶ヨ〃-璐㈠姟鍒嗘瀽")
+    @Operation(summary = "璐㈠姟鎶ヨ〃-璐㈠姟鍒嗘瀽")
     public AjaxResult analysis() {
         return AjaxResult.success(accountExpenseService.analysis());
     }
@@ -138,7 +135,7 @@
      * @return
      */
     @GetMapping("/report/income")
-    @ApiOperation("璐㈠姟鎶ヨ〃鍥捐〃鏀跺叆骞村害鏌ヨ")
+    @Operation(summary = "璐㈠姟鎶ヨ〃鍥捐〃鏀跺叆骞村害鏌ヨ")
     public AjaxResult reportIncome(ReportDateDto reportDateDto) {
         return AjaxResult.success(accountIncomeService.reportIncome(reportDateDto));
     }
@@ -149,7 +146,7 @@
      * @return
      */
     @GetMapping("/report/expense")
-    @ApiOperation("璐㈠姟鎶ヨ〃鍥捐〃鏀嚭骞村害鏌ヨ")
+    @Operation(summary = "璐㈠姟鎶ヨ〃鍥捐〃鏀嚭骞村害鏌ヨ")
     public AjaxResult reportExpense(ReportDateDto reportDateDto) {
         return AjaxResult.success(accountExpenseService.reportExpense(reportDateDto));
     }
diff --git a/src/main/java/com/ruoyi/account/controller/AccountFileController.java b/src/main/java/com/ruoyi/account/controller/AccountFileController.java
index 130e7c8..42c20d1 100644
--- a/src/main/java/com/ruoyi/account/controller/AccountFileController.java
+++ b/src/main/java/com/ruoyi/account/controller/AccountFileController.java
@@ -6,12 +6,12 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.quality.pojo.QualityInspectFile;
 import com.ruoyi.quality.service.IQualityInspectFileService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
@@ -19,7 +19,7 @@
  */
 @RestController
 @RequestMapping("/account/accountFile")
-@Api(tags = "璐㈠姟闄勪欢")
+@Tag(name = "璐㈠姟闄勪欢")
 public class AccountFileController {
 
 
@@ -33,7 +33,7 @@
      * @return
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody AccountFile accountFile) {
         return AjaxResult.success(accountFileService.save(accountFile));
     }
@@ -44,7 +44,7 @@
      * @return
      */
     @DeleteMapping("/del")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delAccountFile(@RequestBody List<Integer> ids) {
         if(CollectionUtils.isEmpty(ids)){
             return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -60,7 +60,7 @@
      * @return
      */
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult accountFileListPage(Page page, AccountFile accountFile) {
         return AjaxResult.success(accountFileService.accountFileListPage(page, accountFile));
     }
diff --git a/src/main/java/com/ruoyi/account/controller/AccountIncomeController.java b/src/main/java/com/ruoyi/account/controller/AccountIncomeController.java
index c6a24d7..690e75a 100644
--- a/src/main/java/com/ruoyi/account/controller/AccountIncomeController.java
+++ b/src/main/java/com/ruoyi/account/controller/AccountIncomeController.java
@@ -14,13 +14,13 @@
 import com.ruoyi.quality.service.IQualityInspectFileService;
 import com.ruoyi.quality.service.IQualityInspectParamService;
 import com.ruoyi.quality.service.IQualityInspectService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.Date;
 import java.util.List;
 
@@ -29,7 +29,7 @@
  */
 @RestController
 @RequestMapping("/account/accountIncome")
-@Api(tags = "璐㈠姟绠$悊--鏀跺叆绠$悊")
+@Tag(name = "璐㈠姟绠$悊--鏀跺叆绠$悊")
 public class AccountIncomeController {
 
     @Resource
@@ -42,7 +42,7 @@
      * @return
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody AccountIncome accountIncome) {
         accountIncome.setInputTime(new Date());
         LoginUser loginUser = SecurityUtils.getLoginUser();
@@ -56,7 +56,7 @@
      * @return
      */
     @DeleteMapping("/del")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delQualityInspect(@RequestBody List<Integer> ids) {
         if(CollectionUtils.isEmpty(ids)){
             return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -71,7 +71,7 @@
      * @return
      */
     @PostMapping("/update")
-    @ApiOperation("淇敼")
+    @Operation(summary = "淇敼")
     public AjaxResult update(@RequestBody AccountIncome accountIncome) {
         return AjaxResult.success(accountIncomeService.updateById(accountIncome));
     }
@@ -83,7 +83,7 @@
      * @return
      */
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult accountIncomeListPage(Page page, AccountIncome accountIncome) {
         return AjaxResult.success(accountIncomeService.accountIncomeListPage(page, accountIncome));
     }
@@ -94,7 +94,7 @@
      * @return
      */
     @GetMapping("/{id}")
-    @ApiOperation("璇︽儏")
+    @Operation(summary = "璇︽儏")
     public AjaxResult accountIncomeDetail(@PathVariable("id") Integer id) {
         return AjaxResult.success(accountIncomeService.getById(id));
     }
@@ -105,7 +105,7 @@
      * @param accountIncome
      */
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭")
+    @Operation(summary = "瀵煎嚭")
     public void accountIncomeExport(HttpServletResponse response,AccountIncome accountIncome) {
         accountIncomeService.accountIncomeExport(response, accountIncome);
     }
diff --git a/src/main/java/com/ruoyi/account/controller/AccountingController.java b/src/main/java/com/ruoyi/account/controller/AccountingController.java
index 332fc95..4688942 100644
--- a/src/main/java/com/ruoyi/account/controller/AccountingController.java
+++ b/src/main/java/com/ruoyi/account/controller/AccountingController.java
@@ -4,9 +4,9 @@
 import com.ruoyi.account.service.impl.AccountingServiceImpl;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -16,28 +16,28 @@
  * @author :yys
  * @date : 2026/1/17 10:40
  */
-@Api(tags = "浼氳鏍哥畻")
+@Tag(name = "浼氳鏍哥畻")
 @RestController
 @RequestMapping("/accounting")
+@AllArgsConstructor
 public class AccountingController extends BaseController {
 
 
-    @Autowired
     private AccountingServiceImpl accountingService;
 
-    @ApiOperation("鎬昏")
+    @Operation(summary = "鎬昏")
     @GetMapping("/total")
     public AjaxResult total(@RequestParam Integer year) {
         return accountingService.total(year);
     }
 
-    @ApiOperation("璁惧绫诲瀷鍒嗗竷")
+    @Operation(summary = "璁惧绫诲瀷鍒嗗竷")
     @GetMapping("/deviceTypeDistribution")
     public AjaxResult deviceTypeDistribution(@RequestParam Integer year) {
         return accountingService.deviceTypeDistribution(year);
     }
 
-    @ApiOperation("璁惧鍒嗛〉鏌ヨ璁$畻鎶樻棫")
+    @Operation(summary = "璁惧鍒嗛〉鏌ヨ璁$畻鎶樻棫")
     @GetMapping("/calculateDepreciation")
     public AjaxResult calculateDepreciation(Page page, @RequestParam Integer year) {
         return accountingService.calculateDepreciation(page,year);
diff --git a/src/main/java/com/ruoyi/account/controller/BorrowInfoController.java b/src/main/java/com/ruoyi/account/controller/BorrowInfoController.java
index b9fe0a1..7620c19 100644
--- a/src/main/java/com/ruoyi/account/controller/BorrowInfoController.java
+++ b/src/main/java/com/ruoyi/account/controller/BorrowInfoController.java
@@ -7,13 +7,14 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -24,16 +25,16 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-01-15 02:57:29
  */
-@Api(tags = "鍊熸淇℃伅琛�")
+@Tag(name = "鍊熸淇℃伅琛�")
 @RestController
 @RequestMapping("/borrowInfo")
+@AllArgsConstructor
 public class BorrowInfoController {
 
-    @Autowired
     private BorrowInfoService borrowInfoService;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, BorrowInfo borrowInfo) {
         return borrowInfoService.listPage(page,borrowInfo);
     }
@@ -73,7 +74,7 @@
      * 瀵煎嚭
      */
     @PostMapping("/export")
-    @ApiOperation(value = "瀵煎嚭鍊熸淇℃伅")
+    @Operation(summary = "瀵煎嚭鍊熸淇℃伅")
     public void export(HttpServletResponse response, BorrowInfo borrowInfo) {
         List<BorrowInfo> list = borrowInfoService.list();
         ExcelUtil<BorrowInfo> util = new ExcelUtil<>(BorrowInfo.class);
diff --git a/src/main/java/com/ruoyi/account/controller/SalesReceiptReturnController.java b/src/main/java/com/ruoyi/account/controller/SalesReceiptReturnController.java
index 7f256ab..786e7c3 100644
--- a/src/main/java/com/ruoyi/account/controller/SalesReceiptReturnController.java
+++ b/src/main/java/com/ruoyi/account/controller/SalesReceiptReturnController.java
@@ -6,7 +6,8 @@
 import com.ruoyi.account.service.SalesReceiptReturnService;
 import com.ruoyi.account.service.impl.SalesReceiptReturnServiceImpl;
 import com.ruoyi.framework.web.domain.R;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -22,15 +23,15 @@
  */
 @RestController
 @RequestMapping("/salesReceiptReturn")
+@AllArgsConstructor
 public class SalesReceiptReturnController {
 
-    @Autowired
     private  SalesReceiptReturnService salesReceiptReturnService;
 
 
 
     @GetMapping("/page")
-    @ApiOperation("鏀舵閫�璐ц〃-鍒嗛〉鏌ヨ")
+    @Operation(summary = "鏀舵閫�璐ц〃-鍒嗛〉鏌ヨ")
     public R<IPage<SalesReceiptReturnDto>> page(SalesReceiptReturnDto salesReceiptReturnDto) {
         return R.ok(salesReceiptReturnService.pageSalesReceiptReturnDto(salesReceiptReturnDto));
     }
diff --git a/src/main/java/com/ruoyi/account/controller/SalesRefundAmountOrderController.java b/src/main/java/com/ruoyi/account/controller/SalesRefundAmountOrderController.java
index daf35a4..7f8bf25 100644
--- a/src/main/java/com/ruoyi/account/controller/SalesRefundAmountOrderController.java
+++ b/src/main/java/com/ruoyi/account/controller/SalesRefundAmountOrderController.java
@@ -5,7 +5,8 @@
 import com.ruoyi.account.pojo.SalesRefundAmountOrder;
 import com.ruoyi.account.service.SalesRefundAmountOrderService;
 import com.ruoyi.framework.web.domain.R;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -23,9 +24,9 @@
  */
 @RestController
 @RequestMapping("/salesRefundAmountOrder")
+@AllArgsConstructor
 public class SalesRefundAmountOrderController {
 
-    @Autowired
     private SalesRefundAmountOrderService salesRefundAmountOrderService;
 
     @GetMapping("/page")
@@ -33,7 +34,7 @@
         return R.ok(salesRefundAmountOrderService.pageSalesRefundAmountOrderDto(page, salesRefundAmountOrder));
     }
 
-    @ApiOperation("澶勭悊")
+    @Operation(summary = "澶勭悊")
     @PostMapping("/dispose")
     public R dispose( SalesRefundAmountOrderDto salesRefundAmountOrderId) {
         return R.ok(salesRefundAmountOrderService.dispose(salesRefundAmountOrderId));
diff --git a/src/main/java/com/ruoyi/account/dto/AccountDto.java b/src/main/java/com/ruoyi/account/dto/AccountDto.java
index c8e0d06..93ed680 100644
--- a/src/main/java/com/ruoyi/account/dto/AccountDto.java
+++ b/src/main/java/com/ruoyi/account/dto/AccountDto.java
@@ -6,11 +6,11 @@
 import com.ruoyi.account.pojo.AccountIncome;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
diff --git a/src/main/java/com/ruoyi/account/dto/DeviceTypeDistributionVO.java b/src/main/java/com/ruoyi/account/dto/DeviceTypeDistributionVO.java
index f4c487b..1c294bd 100644
--- a/src/main/java/com/ruoyi/account/dto/DeviceTypeDistributionVO.java
+++ b/src/main/java/com/ruoyi/account/dto/DeviceTypeDistributionVO.java
@@ -1,6 +1,5 @@
 package com.ruoyi.account.dto;
 
-import com.mchange.v1.util.ListUtils;
 import lombok.Data;
 
 import java.math.BigDecimal;
diff --git a/src/main/java/com/ruoyi/account/dto/SalesRefundAmountOrderDto.java b/src/main/java/com/ruoyi/account/dto/SalesRefundAmountOrderDto.java
index 698e0e1..a948957 100644
--- a/src/main/java/com/ruoyi/account/dto/SalesRefundAmountOrderDto.java
+++ b/src/main/java/com/ruoyi/account/dto/SalesRefundAmountOrderDto.java
@@ -1,23 +1,23 @@
 package com.ruoyi.account.dto;
 
 import com.ruoyi.account.pojo.SalesRefundAmountOrder;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 @Data
 public class SalesRefundAmountOrderDto extends SalesRefundAmountOrder {
 
-    @ApiModelProperty("閫�璐у崟鍙�")
+    @Schema(description = "閫�璐у崟鍙�")
     private String returnManagementNo;
 
-    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
-    @ApiModelProperty("閿�鍞崟鍙�")
+    @Schema(description = "閿�鍞崟鍙�")
     private String salesContractNo;
 
-    @ApiModelProperty("鍒涘缓浜哄悕绉�")
+    @Schema(description = "鍒涘缓浜哄悕绉�")
     private String createUserName;
 
 
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountExpense.java b/src/main/java/com/ruoyi/account/pojo/AccountExpense.java
index cbb6eed..dcb6b4b 100644
--- a/src/main/java/com/ruoyi/account/pojo/AccountExpense.java
+++ b/src/main/java/com/ruoyi/account/pojo/AccountExpense.java
@@ -4,11 +4,11 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
@@ -105,25 +105,28 @@
     private Date inputTime;
 
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountFile.java b/src/main/java/com/ruoyi/account/pojo/AccountFile.java
index 4dad77d..b22ab91 100644
--- a/src/main/java/com/ruoyi/account/pojo/AccountFile.java
+++ b/src/main/java/com/ruoyi/account/pojo/AccountFile.java
@@ -2,10 +2,10 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.time.LocalDateTime;
 
@@ -24,44 +24,47 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty(value = "鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private int fileSize;
 
-    @ApiModelProperty(value = "璐㈠姟ID")
+    @Schema(description = "璐㈠姟ID")
     @NotBlank(message = "璐㈠姟id涓嶈兘涓虹┖!")
     private Long accountId;
 
     /**
      * 绫诲瀷(鏀跺叆/鏀嚭)
      */
-    @ApiModelProperty(value = "绫诲瀷(鏀跺叆/鏀嚭)")
+    @Schema(description = "绫诲瀷(鏀跺叆/鏀嚭)")
     private String accountType;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/account/pojo/AccountIncome.java b/src/main/java/com/ruoyi/account/pojo/AccountIncome.java
index fee01ad..d6ce79c 100644
--- a/src/main/java/com/ruoyi/account/pojo/AccountIncome.java
+++ b/src/main/java/com/ruoyi/account/pojo/AccountIncome.java
@@ -4,15 +4,16 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.List;
 
 /**
  * 璐㈠姟绠$悊--鏀跺叆绠$悊
@@ -20,7 +21,7 @@
  */
 @TableName(value = "account_income")
 @Data
-public class AccountIncome extends DateQueryDto  implements Serializable {
+public class AccountIncome extends DateQueryDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
     /**
@@ -50,7 +51,7 @@
     /**
      * 鏀跺叆绫诲瀷(閿�鍞敹鍏ワ紝鏈嶅姟鏀跺叆锛屽叾浠栨敹鍏�)
      */
-    @Excel(name = "鏀跺叆绫诲瀷",readConverterExp = "0=閿�鍞敹鍏�,1=鏈嶅姟鏀跺叆,2=鍏朵粬鏀跺叆,3=鍥炴鏀跺叆")
+    @Excel(name = "鏀跺叆绫诲瀷", readConverterExp = "0=閿�鍞敹鍏�,1=鏈嶅姟鏀跺叆,2=鍏朵粬鏀跺叆,3=鍥炴鏀跺叆")
     @NotBlank(message = "鏀跺叆绫诲瀷涓嶈兘涓虹┖!!")
     private String incomeType;
 
@@ -75,8 +76,26 @@
     /**
      * 鏀舵鏂瑰紡(鐜伴噾锛屾敮绁紝閾惰杞处锛屽叾浠�)
      */
-    @Excel(name = "鏀舵鏂瑰紡",readConverterExp = "0=鐜伴噾,1=鏀エ,2=閾惰杞处,3=鍏朵粬")
+    @Excel(name = "鏀舵鏂瑰紡", readConverterExp = "0=鐜伴噾,1=鏀エ,2=閾惰杞处,3=鍏朵粬")
     private String incomeMethod;
+
+    /**
+     * 鏀舵鏂瑰紡鏍囩
+     */
+    @TableField(exist = false)
+    private String incomeMethodLabel;
+
+    /**
+     * payment_methods 瀛楀吀缂栫爜闆嗗悎锛坆usiness_type 涓虹┖鏃讹級
+     */
+    @TableField(exist = false)
+    private List<String> paymentMethodList;
+
+    /**
+     * receipt_payment_type 瀛楀吀缂栫爜闆嗗悎锛坆usiness_type=1鏃讹級
+     */
+    @TableField(exist = false)
+    private List<String> receiptPaymentMethodList;
 
     /**
      * 鍙戠エ鍙风爜
@@ -105,25 +124,28 @@
     private Date inputTime;
 
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/account/pojo/BorrowInfo.java b/src/main/java/com/ruoyi/account/pojo/BorrowInfo.java
index 889cc4f..8e4d809 100644
--- a/src/main/java/com/ruoyi/account/pojo/BorrowInfo.java
+++ b/src/main/java/com/ruoyi/account/pojo/BorrowInfo.java
@@ -13,8 +13,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -30,64 +29,67 @@
 @Getter
 @Setter
 @TableName("borrow_info")
-@ApiModel(value = "BorrowInfo瀵硅薄", description = "鍊熸淇℃伅琛�")
+@Schema(name = "BorrowInfo瀵硅薄", description = "鍊熸淇℃伅琛�")
 public class BorrowInfo extends DateQueryDto implements Serializable{
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("鍊熸璁板綍涓婚敭ID")
+    @Schema(description = "鍊熸璁板綍涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍊熸浜哄鍚�")
+    @Schema(description = "鍊熸浜哄鍚�")
     @Excel(name = "鍊熸浜哄鍚�")
     private String borrowerName;
 
-    @ApiModelProperty("鍊熸閲戦锛堝厓锛�")
+    @Schema(description = "鍊熸閲戦锛堝厓锛�")
     @Excel(name = "鍊熸閲戦锛堝厓锛�")
     private BigDecimal borrowAmount;
 
-    @ApiModelProperty("鍊熸鍒╃巼锛堝锛�5.85 浠h〃5.85%锛�")
+    @Schema(description = "鍊熸鍒╃巼锛堝锛�5.85 浠h〃5.85%锛�")
     @Excel(name = "鍊熸鍒╃巼")
     private BigDecimal interestRate;
 
-    @ApiModelProperty("鍊熸鏃ユ湡")
+    @Schema(description = "鍊熸鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鍊熸鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private LocalDate borrowDate;
 
-    @ApiModelProperty("瀹為檯杩樻鏃ユ湡锛堣繕娆惧悗濉厖锛�")
+    @Schema(description = "瀹為檯杩樻鏃ユ湡锛堣繕娆惧悗濉厖锛�")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "瀹為檯杩樻鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private LocalDate repayDate;
 
-    @ApiModelProperty("鍊熸鐘舵�侊細1=寰呰繕娆撅紝2=宸茶繕娆�")
+    @Schema(description = "鍊熸鐘舵�侊細1=寰呰繕娆撅紝2=宸茶繕娆�")
     @Excel(name = "鍊熸鐘舵��", readConverterExp = "1=寰呰繕娆�,2=宸茶繕娆�")
     private Integer status;
 
-    @ApiModelProperty("澶囨敞锛堝�熸璇存槑锛�")
+    @Schema(description = "澶囨敞锛堝�熸璇存槑锛�")
     @Excel(name = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鑰匢D")
+    @Schema(description = "鍒涘缓鑰匢D")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鑰匢D")
+    @Schema(description = "淇敼鑰匢D")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/account/pojo/SalesReceiptReturn.java b/src/main/java/com/ruoyi/account/pojo/SalesReceiptReturn.java
index f05f9ed..939d7e9 100644
--- a/src/main/java/com/ruoyi/account/pojo/SalesReceiptReturn.java
+++ b/src/main/java/com/ruoyi/account/pojo/SalesReceiptReturn.java
@@ -8,8 +8,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -24,48 +23,51 @@
 @Getter
 @Setter
 @TableName("sales_receipt_return")
-@ApiModel(value = "SalesReceiptReturn瀵硅薄", description = "鏀舵閫�璐ц〃")
+@Schema(name = "SalesReceiptReturn瀵硅薄", description = "鏀舵閫�璐ц〃")
 public class SalesReceiptReturn implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("涓婚敭 ID")
+    @Schema(description = "涓婚敭 ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("閫�娆惧崟鍙�")
+    @Schema(description = "閫�娆惧崟鍙�")
     private String refundId;
 
-    @ApiModelProperty("浠樻璐﹀彿")
+    @Schema(description = "浠樻璐﹀彿")
     private String paymentAccount;
 
-    @ApiModelProperty("浠樻璐﹀彿鍚嶇О")
+    @Schema(description = "浠樻璐﹀彿鍚嶇О")
     private String paymentAccountName;
 
-    @ApiModelProperty("浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     private Byte paymentMethod;
 
-    @ApiModelProperty("瀹為檯浠樻閲戦")
+    @Schema(description = "瀹為檯浠樻閲戦")
     private BigDecimal actualAmount;
 
-    @ApiModelProperty("鎵嬬画璐�")
+    @Schema(description = "鎵嬬画璐�")
     private BigDecimal fee;
 
-    @ApiModelProperty("浜ゆ槗鍙�")
+    @Schema(description = "浜ゆ槗鍙�")
     private String transactionNo;
 
-    @ApiModelProperty("浼樻儬閲戦")
+    @Schema(description = "浼樻儬閲戦")
     private BigDecimal discountAmount;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓鑰�")
+    @Schema(description = "鍒涘缓鑰�")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/account/pojo/SalesRefundAmountOrder.java b/src/main/java/com/ruoyi/account/pojo/SalesRefundAmountOrder.java
index 08cb451..a83f54f 100644
--- a/src/main/java/com/ruoyi/account/pojo/SalesRefundAmountOrder.java
+++ b/src/main/java/com/ruoyi/account/pojo/SalesRefundAmountOrder.java
@@ -10,8 +10,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -27,7 +26,7 @@
 @Getter
 @Setter
 @TableName("sales_refund_amount_order")
-@ApiModel(value = "SalesRefundAmountOrder瀵硅薄", description = "閿�鍞鐞�--閫�娆惧崟")
+@Schema(name = "SalesRefundAmountOrder瀵硅薄", description = "閿�鍞鐞�--閫�娆惧崟")
 public class SalesRefundAmountOrder implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -35,36 +34,43 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("閫�璐у崟鍙穒d")
+    @Schema(description = "閫�璐у崟鍙穒d")
     private Long returnManagementId;
 
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     private Integer status;
 
-    @ApiModelProperty("搴旈��娆鹃噾棰�")
+    @Schema(description = "搴旈��娆鹃噾棰�")
     private BigDecimal refundAmount;
 
-    @ApiModelProperty("宸查��娆鹃噾棰�")
+    @Schema(description = "宸查��娆鹃噾棰�")
     private BigDecimal refundedAmount;
 
-    @ApiModelProperty("鏈��娆鹃噾棰�")
+    @Schema(description = "鏈��娆鹃噾棰�")
     private BigDecimal notRefundedAmount;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜篿d")
+    @Schema(description = "鍒涘缓浜篿d")
     private Long createUserId;
 
-    @ApiModelProperty("鏇存柊浜篿d")
+    @Schema(description = "鏇存柊浜篿d")
     private Long updateUserId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/account/service/AccountExpenseService.java b/src/main/java/com/ruoyi/account/service/AccountExpenseService.java
index ac3e0b2..4997c23 100644
--- a/src/main/java/com/ruoyi/account/service/AccountExpenseService.java
+++ b/src/main/java/com/ruoyi/account/service/AccountExpenseService.java
@@ -11,7 +11,7 @@
 import com.ruoyi.account.pojo.AccountIncome;
 import com.ruoyi.dto.DateQueryDto;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 
diff --git a/src/main/java/com/ruoyi/account/service/AccountIncomeService.java b/src/main/java/com/ruoyi/account/service/AccountIncomeService.java
index 1004f28..33bb02f 100644
--- a/src/main/java/com/ruoyi/account/service/AccountIncomeService.java
+++ b/src/main/java/com/ruoyi/account/service/AccountIncomeService.java
@@ -8,7 +8,7 @@
 import com.ruoyi.account.dto.ReportDateDto;
 import com.ruoyi.account.pojo.AccountIncome;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 public interface AccountIncomeService extends IService<AccountIncome> {
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java
index b7791a9..40b1f31 100644
--- a/src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java
+++ b/src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java
@@ -21,7 +21,7 @@
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.time.DayOfWeek;
 import java.time.LocalDate;
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java
index 4a83ecb..4a754e0 100644
--- a/src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java
@@ -5,13 +5,11 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.dto.AccountDto2;
 import com.ruoyi.account.dto.AccountDto3;
 import com.ruoyi.account.dto.ReportDateDto;
 import com.ruoyi.account.mapper.AccountIncomeMapper;
 import com.ruoyi.account.pojo.AccountIncome;
 import com.ruoyi.account.service.AccountIncomeService;
-import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.project.system.domain.SysDictData;
@@ -19,14 +17,14 @@
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
+import java.util.stream.Collectors;
 
 @AllArgsConstructor
 @Service
@@ -40,9 +38,40 @@
     //鍒嗛〉鏌ヨ
     @Override
     public IPage<AccountIncome> accountIncomeListPage(Page page, AccountIncome accountIncome) {
+        resolveIncomeMethodLabelFilter(accountIncome);
         return accountIncomeMapper.accountIncomeListPage(page,accountIncome);
     }
 
+    private void resolveIncomeMethodLabelFilter(AccountIncome accountIncome) {
+        if (accountIncome == null) {
+            return;
+        }
+        if (accountIncome.getIncomeMethodLabel() == null || accountIncome.getIncomeMethodLabel().trim().isEmpty()) {
+            return;
+        }
+        String targetLabel = accountIncome.getIncomeMethodLabel().trim();
+        List<String> paymentMethodList = selectDictValuesByLabel("payment_methods", targetLabel);
+        List<String> receiptPaymentMethodList = selectDictValuesByLabel("receipt_payment_type", targetLabel);
+        if (paymentMethodList.isEmpty()) {
+            paymentMethodList = Collections.singletonList("__NO_MATCH__");
+        }
+        if (receiptPaymentMethodList.isEmpty()) {
+            receiptPaymentMethodList = Collections.singletonList("__NO_MATCH__");
+        }
+        accountIncome.setPaymentMethodList(paymentMethodList);
+        accountIncome.setReceiptPaymentMethodList(receiptPaymentMethodList);
+        accountIncome.setIncomeMethod(null);
+    }
+
+    private List<String> selectDictValuesByLabel(String dictType, String label) {
+        return sysDictDataMapper.selectDictDataByType(dictType).stream()
+                .filter(item -> label.equals(item.getDictLabel()))
+                .map(SysDictData::getDictValue)
+                .filter(v -> v != null && !v.trim().isEmpty())
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
     //瀵煎嚭
     @Override
     public void accountIncomeExport(HttpServletResponse response, AccountIncome accountIncome) {
diff --git a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
index e9a586f..0ed77af 100644
--- a/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
+++ b/src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
@@ -17,10 +17,8 @@
 import com.ruoyi.procurementrecord.pojo.CustomStorage;
 import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
 import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
-import com.ruoyi.procurementrecord.service.impl.ProcurementRecordOutServiceImpl;
-import com.ruoyi.procurementrecord.service.impl.ProcurementRecordServiceImpl;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -36,22 +34,14 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class AccountingServiceImpl {
 
-    @Autowired
-    private DeviceLedgerMapper deviceLedgerMapper;
-
-    @Autowired
-    private BorrowInfoMapper borrowInfoMapper;
-
-    @Autowired
-    private CustomStorageMapper customStorageMapper;
-
-    @Autowired
-    private ProcurementRecordMapper procurementRecordMapper;
-
-    @Autowired
-    private ProcurementRecordOutMapper procurementRecordOutMapper;
+    private final DeviceLedgerMapper deviceLedgerMapper;
+    private final BorrowInfoMapper borrowInfoMapper;
+    private final CustomStorageMapper customStorageMapper;
+    private final ProcurementRecordMapper procurementRecordMapper;
+    private final ProcurementRecordOutMapper procurementRecordOutMapper;
 
     public AjaxResult total(Integer year) {
         Map<String,Object> map = new HashMap<>();
diff --git a/src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java
index 74692c4..773799d 100644
--- a/src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/account/service/impl/BorrowInfoServiceImpl.java
@@ -2,20 +2,19 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.mapper.BorrowInfoMapper;
 import com.ruoyi.account.pojo.AccountExpense;
 import com.ruoyi.account.pojo.AccountIncome;
 import com.ruoyi.account.pojo.BorrowInfo;
-import com.ruoyi.account.mapper.BorrowInfoMapper;
 import com.ruoyi.account.service.AccountExpenseService;
 import com.ruoyi.account.service.AccountIncomeService;
 import com.ruoyi.account.service.BorrowInfoService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.sales.service.ReceiptPaymentService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -30,16 +29,12 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class BorrowInfoServiceImpl extends ServiceImpl<BorrowInfoMapper, BorrowInfo> implements BorrowInfoService {
 
-    @Autowired
-    private BorrowInfoMapper borrowInfoMapper;
-
-    @Autowired
-    private AccountIncomeService accountIncomeService;
-
-    @Autowired
-    private AccountExpenseService accountExpenseService;
+    private final BorrowInfoMapper borrowInfoMapper;
+    private final AccountIncomeService accountIncomeService;
+    private final AccountExpenseService accountExpenseService;
 
     @Override
     public AjaxResult listPage(Page page, BorrowInfo borrowInfo) {
diff --git a/src/main/java/com/ruoyi/account/service/impl/SalesRefundAmountOrderServiceImpl.java b/src/main/java/com/ruoyi/account/service/impl/SalesRefundAmountOrderServiceImpl.java
index c04fdb5..3dcc1cd 100644
--- a/src/main/java/com/ruoyi/account/service/impl/SalesRefundAmountOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/account/service/impl/SalesRefundAmountOrderServiceImpl.java
@@ -2,12 +2,12 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.dto.SalesRefundAmountOrderDto;
-import com.ruoyi.account.pojo.SalesRefundAmountOrder;
-import com.ruoyi.account.mapper.SalesRefundAmountOrderMapper;
-import com.ruoyi.account.service.SalesRefundAmountOrderService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.account.dto.SalesRefundAmountOrderDto;
+import com.ruoyi.account.mapper.SalesRefundAmountOrderMapper;
+import com.ruoyi.account.pojo.SalesRefundAmountOrder;
+import com.ruoyi.account.service.SalesRefundAmountOrderService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 /**
@@ -19,11 +19,11 @@
  * @since 2026-03-07 10:16:47
  */
 @Service
+@RequiredArgsConstructor
 public class SalesRefundAmountOrderServiceImpl extends ServiceImpl<SalesRefundAmountOrderMapper, SalesRefundAmountOrder> implements SalesRefundAmountOrderService {
 
 
-    @Autowired
-    private SalesRefundAmountOrderMapper salesRefundAmountOrderMapper;
+    private final SalesRefundAmountOrderMapper salesRefundAmountOrderMapper;
 
     @Override
     public IPage<SalesRefundAmountOrderDto> pageSalesRefundAmountOrderDto(Page<SalesRefundAmountOrderDto> page, SalesRefundAmountOrderDto salesRefundAmountOrder) {
diff --git a/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesNearExpiryController.java b/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesNearExpiryController.java
index 69b21c7..ccc13b9 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesNearExpiryController.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesNearExpiryController.java
@@ -8,9 +8,9 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 /**
@@ -23,18 +23,18 @@
  * @since 2026/03/02 14:40
  */
 @RestController
-@Api(tags = "涓存湡鍞悗绠$悊")
+@Tag(name = "涓存湡鍞悗绠$悊")
 @RequestMapping("/afterSalesNearExpiryService")
+@AllArgsConstructor
 public class AfterSalesNearExpiryController extends BaseController {
 
-    @Autowired
     private AfterSalesNearExpiryService afterSalesNearExpiryService;
 
     /**
      * 鏂板涓存湡鍞悗
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板涓存湡鍞悗")
+    @Operation(summary = "鏂板涓存湡鍞悗")
     @Log(title = "鏂板涓存湡鍞悗", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody AfterSalesNearExpiry entity) {
         afterSalesNearExpiryService.add(entity);
@@ -45,7 +45,7 @@
      * 鏇存柊涓存湡鍞悗
      */
     @PostMapping("/update")
-    @ApiOperation("鏇存柊涓存湡鍞悗")
+    @Operation(summary = "鏇存柊涓存湡鍞悗")
     @Log(title = "鏇存柊涓存湡鍞悗", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody AfterSalesNearExpiry entity) {
         afterSalesNearExpiryService.update(entity);
@@ -56,7 +56,7 @@
      * 鍒犻櫎涓存湡鍞悗
      */
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎涓存湡鍞悗")
+    @Operation(summary = "鍒犻櫎涓存湡鍞悗")
     @Log(title = "鍒犻櫎涓存湡鍞悗", businessType = BusinessType.DELETE)
     public AjaxResult delete(Long[] ids) {
         afterSalesNearExpiryService.delete(ids);
@@ -67,7 +67,7 @@
      * 鍒嗛〉鏌ヨ涓存湡鍞悗
      */
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ涓存湡鍞悗")
+    @Operation(summary = "鍒嗛〉鏌ヨ涓存湡鍞悗")
     @Log(title = "鍒嗛〉鏌ヨ涓存湡鍞悗", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page<AfterSalesNearExpiry> page, AfterSalesNearExpiry entity) {
         IPage<AfterSalesNearExpiry> listPage = afterSalesNearExpiryService.listPage(page, entity);
diff --git a/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceController.java b/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceController.java
index 95e9999..5f4c3a8 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceController.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceController.java
@@ -15,14 +15,14 @@
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.service.ISalesLedgerService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -32,22 +32,18 @@
  * @date : 2025/7/30 9:27
  */
 @RestController
-@Api(tags = "鍞悗鏈嶅姟")
+@Tag(name = "鍞悗鏈嶅姟")
 @RequestMapping("/afterSalesService")
+@AllArgsConstructor
 public class AfterSalesServiceController extends BaseController {
 
 
-    @Autowired
     private AfterSalesServiceService afterSalesServiceService;
-
-    @Autowired
     private SysUserMapper sysUserMapper;
-
-    @Autowired
     private ISalesLedgerService salesLedgerService;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍞悗鏈嶅姟-鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍞悗鏈嶅姟-鍒嗛〉鏌ヨ")
     @Log(title = "鍞悗鏈嶅姟-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, AfterSalesServiceNewDto afterSalesService) {
         IPage<AfterSalesServiceNewDto> listPage = afterSalesServiceService.listPage(page, afterSalesService);
@@ -56,7 +52,7 @@
 
     @Log(title = "鍞悗鏈嶅姟-鍙嶉鐧昏", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("鍞悗鏈嶅姟-鍙嶉鐧昏")
+    @Operation(summary = "鍞悗鏈嶅姟-鍙嶉鐧昏")
     public void export(HttpServletResponse response) {
         Page page = new Page(-1,-1);
         AfterSalesServiceNewDto afterSalesService = new AfterSalesServiceNewDto();
@@ -74,7 +70,7 @@
 
     @Log(title = "鍞悗鏈嶅姟-鍞悗澶勭悊", businessType = BusinessType.EXPORT)
     @PostMapping("/exportTwo")
-    @ApiOperation("鍞悗鏈嶅姟-鍞悗澶勭悊")
+    @Operation(summary = "鍞悗鏈嶅姟-鍞悗澶勭悊")
     public void exportTwo(HttpServletResponse response) {
         Page page = new Page(-1,-1);
         AfterSalesServiceNewDto afterSalesService = new AfterSalesServiceNewDto();
@@ -87,14 +83,14 @@
     }
 
     @PostMapping("/add")
-    @ApiOperation("鍞悗鏈嶅姟-鏂板")
+    @Operation(summary = "鍞悗鏈嶅姟-鏂板")
     @Log(title = "鍞悗鏈嶅姟-鏂板", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody AfterSalesServiceNewDto afterSalesServiceNewDto) {
         return afterSalesServiceService.addAfterSalesServiceDto(afterSalesServiceNewDto) ? AjaxResult.success() : AjaxResult.error();
     }
 
     @PostMapping("/update")
-    @ApiOperation("鍞悗鏈嶅姟-淇敼")
+    @Operation(summary = "鍞悗鏈嶅姟-淇敼")
     @Log(title = "鍞悗鏈嶅姟-淇敼", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody AfterSalesServiceNewDto afterSalesServiceNewDto) {
         if (afterSalesServiceNewDto.getProductModelIdList() != null && afterSalesServiceNewDto.getProductModelIdList().isEmpty() ) {
@@ -108,7 +104,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍞悗鏈嶅姟-鍒犻櫎")
+    @Operation(summary = "鍞悗鏈嶅姟-鍒犻櫎")
     @Log(title = "鍞悗鏈嶅姟-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if (CollectionUtils.isEmpty(ids)) {
@@ -119,7 +115,7 @@
     }
 
     @PostMapping("/dispose")
-    @ApiOperation("鍞悗鏈嶅姟-澶勭悊")
+    @Operation(summary = "鍞悗鏈嶅姟-澶勭悊")
     @Log(title = "鍞悗鏈嶅姟-澶勭悊", businessType = BusinessType.UPDATE)
     public AjaxResult dispose(@RequestBody AfterSalesService afterSalesService) {
         AfterSalesService byId = afterSalesServiceService.getById(afterSalesService.getId());
@@ -135,7 +131,7 @@
 
 
     @GetMapping("listSalesLedger")
-    @ApiOperation("鍞悗鏈嶅姟-鑾峰彇閿�鍞彴璐�")
+    @Operation(summary = "鍞悗鏈嶅姟-鑾峰彇閿�鍞彴璐�")
     public AjaxResult listSalesLedger(SalesLedgerDto salesLedgerDto, Page page) {
         IPage<SalesLedgerDto> list = salesLedgerService.listSalesLedger(salesLedgerDto,page);
         return AjaxResult.success(list);
@@ -143,12 +139,12 @@
 
 
     @GetMapping("getById")
-    @ApiOperation("鍞悗鏈嶅姟-鏍规嵁id鑾峰彇璇︽儏")
+    @Operation(summary = "鍞悗鏈嶅姟-鏍规嵁id鑾峰彇璇︽儏")
     public AjaxResult getById(Long id) {
         return AjaxResult.success(afterSalesServiceService.getAfterSalesServiceNewDtoById(id));
     }
 
-    @ApiOperation("鍞悗鏈嶅姟-缁熻宸ュ崟鎯呭喌")
+    @Operation(summary = "鍞悗鏈嶅姟-缁熻宸ュ崟鎯呭喌")
     @GetMapping("count")
     public AjaxResult count() {
         return AjaxResult.success(afterSalesServiceService.countAfterSalesService());
diff --git a/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceFileController.java b/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceFileController.java
index 4a09c05..9032852 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceFileController.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceFileController.java
@@ -7,8 +7,9 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -23,15 +24,15 @@
  * @since 2026/03/02 11:20
  */
 @RestController
-@Api(tags = "鍞悗鏈嶅姟闄勪欢琛�")
+@Tag(name = "鍞悗鏈嶅姟闄勪欢琛�")
 @RequestMapping("/afterSalesService/file")
+@AllArgsConstructor
 public class AfterSalesServiceFileController extends BaseController {
 
-    @Autowired
     private AfterSalesServiceFileService afterSalesServiceFileService;
 
     @PostMapping("/upload")
-    @ApiOperation("鍞悗鏈嶅姟-鏂囦欢涓婁紶")
+    @Operation(summary = "鍞悗鏈嶅姟-鏂囦欢涓婁紶")
     @Log(title = "鍞悗鏈嶅姟-鏂囦欢涓婁紶", businessType = BusinessType.INSERT)
     public AjaxResult fileUpload(@RequestParam("file") MultipartFile file,
                                  @RequestParam("id") Long afterSalesServiceId) {
@@ -40,14 +41,14 @@
     }
 
     @GetMapping("/listPage")
-    @ApiOperation("鍞悗澶勭悊-鍞悗闄勪欢鍒楄〃")
+    @Operation(summary = "鍞悗澶勭悊-鍞悗闄勪欢鍒楄〃")
     @Log(title = "鍞悗澶勭悊-鍞悗闄勪欢鍒楄〃", businessType = BusinessType.OTHER)
     public AjaxResult fileList(Page<AfterSalesServiceFile> page, Long afterSalesServiceId) {
         return AjaxResult.success(afterSalesServiceFileService.fileList(page, afterSalesServiceId));
     }
 
     @DeleteMapping("/del/{fileId}")
-    @ApiOperation("鍞悗澶勭悊-鍒犻櫎闄勪欢")
+    @Operation(summary = "鍞悗澶勭悊-鍒犻櫎闄勪欢")
     @Log(title = "鍞悗澶勭悊-鍒犻櫎闄勪欢", businessType = BusinessType.DELETE)
     public AjaxResult delFile(@PathVariable Long fileId) {
         afterSalesServiceFileService.delFile(fileId);
diff --git a/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceExeclDto.java b/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceExeclDto.java
index c8526c7..472ffcd 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceExeclDto.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceExeclDto.java
@@ -2,7 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,7 +18,7 @@
     /**
      * 鐘舵�� 1-寰呭鐞� 2-宸插鐞�
      */
-    @ApiModelProperty("鐘舵�� 1-寰呭鐞� 2-宸插鐞�")
+    @Schema(description = "鐘舵�� 1-寰呭鐞� 2-宸插鐞�")
     private Integer status;
 
 
@@ -28,7 +28,7 @@
     /**
      * 鐧昏浜哄悕绉�
      */
-    @ApiModelProperty("鐧昏浜哄悕绉�")
+    @Schema(description = "鐧昏浜哄悕绉�")
     @Excel(name = "鐧昏浜哄悕绉�")
     private String checkNickName;
 
@@ -36,14 +36,14 @@
     /**
      * 瀹㈡埛鍚嶇О
      */
-    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     @Excel(name = "瀹㈡埛鍚嶇О")
     private String customerName;
 
     /**
      * 闂鎻忚堪
      */
-    @ApiModelProperty("闂鎻忚堪")
+    @Schema(description = "闂鎻忚堪")
     @Excel(name = "闂鎻忚堪")
     private String proDesc;
 
@@ -51,14 +51,14 @@
     /**
      * 鍙嶉鏃ユ湡
      */
-    @ApiModelProperty("鍙嶉鏃ユ湡")
+    @Schema(description = "鍙嶉鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鍙嶉鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private Date feedbackDate;
 
 
-    @ApiModelProperty("鍏宠仈閮ㄩ棬")
+    @Schema(description = "鍏宠仈閮ㄩ棬")
     @Excel(name = "鍏宠仈閮ㄩ棬")
     private String deptName;
 
diff --git a/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceNewDto.java b/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceNewDto.java
index dd35550..e8f4e5a 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceNewDto.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceNewDto.java
@@ -4,7 +4,7 @@
 import com.ruoyi.aftersalesservice.pojo.AfterSalesService;
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.List;
@@ -12,7 +12,7 @@
 @Data
 public class AfterSalesServiceNewDto extends AfterSalesService {
 
-    @ApiModelProperty("浜у搧鍨嬪彿ID鏁扮粍")
+    @Schema(description = "浜у搧鍨嬪彿ID鏁扮粍")
     private List<Long> productModelIdList;
 
     private SalesLedgerDto salesLedgerDto;
diff --git a/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesNearExpiry.java b/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesNearExpiry.java
index d29666d..d33a1d0 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesNearExpiry.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesNearExpiry.java
@@ -1,11 +1,12 @@
 package com.ruoyi.aftersalesservice.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -23,69 +24,72 @@
  */
 @Data
 @TableName("after_sales_near_expiry")
-@ApiModel("涓存湡鍞悗绠$悊琛�")
+@Schema(name = "涓存湡鍞悗绠$悊琛�")
 public class AfterSalesNearExpiry {
 
     @TableId(type = IdType.AUTO)
-    @ApiModelProperty("涓婚敭")
+    @Schema(description = "涓婚敭")
     private Long id;
 
-    @ApiModelProperty("涓存湡浜у搧鍚嶇О")
+    @Schema(description = "涓存湡浜у搧鍚嶇О")
     private String productName;
 
-    @ApiModelProperty("浜у搧鎵瑰彿")
+    @Schema(description = "浜у搧鎵瑰彿")
     private String batchNumber;
 
-    @ApiModelProperty("涓存湡鏃ユ湡")
+    @Schema(description = "涓存湡鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate expireDate;
 
-    @ApiModelProperty("搴撳瓨鏁伴噺")
+    @Schema(description = "搴撳瓨鏁伴噺")
     private Integer stockQuantity;
 
-    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
-    @ApiModelProperty("鑱旂郴鐢佃瘽")
+    @Schema(description = "鑱旂郴鐢佃瘽")
     private String contactPhone;
 
-    @ApiModelProperty("闂鎻忚堪")
+    @Schema(description = "闂鎻忚堪")
     private String disRes;
 
-    @ApiModelProperty("澶勭悊缁撴灉")
+    @Schema(description = "澶勭悊缁撴灉")
     private String disposeResult;
 
-    @ApiModelProperty("澶勭悊鐘舵�� (1-寰呭鐞� 2-宸插鐞�)")
+    @Schema(description = "澶勭悊鐘舵�� (1-寰呭鐞� 2-宸插鐞�)")
     private Integer status;
 
-    @ApiModelProperty("澶勭悊浜篒D")
+    @Schema(description = "澶勭悊浜篒D")
     private Long disposeUserId;
 
-    @ApiModelProperty("澶勭悊浜哄悕绉�")
+    @Schema(description = "澶勭悊浜哄悕绉�")
     private String disposeNickName;
 
-    @ApiModelProperty("澶勭悊鏃ユ湡")
+    @Schema(description = "澶勭悊鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate disDate;
 
-    @ApiModelProperty("鍒涘缓鑰�")
+    @Schema(description = "鍒涘缓鑰�")
     private Long createUser;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("淇敼鑰�")
+    @Schema(description = "淇敼鑰�")
     private Long updateUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesService.java b/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesService.java
index e11722e..43fa217 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesService.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesService.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,7 +18,7 @@
  */
 @Data
 @TableName("after_sales_service")
-@ApiModel
+@Schema
 public class AfterSalesService {
 
     private static final long serialVersionUID = 1L;
@@ -30,10 +29,10 @@
     /**
      * 鐘舵�� 1-寰呭鐞� 2-宸插鐞�
      */
-    @ApiModelProperty("鐘舵�� 1-寰呭鐞� 2-宸插鐞�")
+    @Schema(description = "鐘舵�� 1-寰呭鐞� 2-宸插鐞�")
     private Integer status;
 
-    @ApiModelProperty("鍞悗鍗曞彿")
+    @Schema(description = "鍞悗鍗曞彿")
     private String afterSalesServiceNo;
 
 
@@ -44,54 +43,54 @@
     /**
      * 鐧昏浜�
      */
-    @ApiModelProperty("鐧昏浜�")
+    @Schema(description = "鐧昏浜�")
     private Long checkUserId;
 
     /**
      * 鐧昏浜哄悕绉�
      */
-    @ApiModelProperty("鐧昏浜哄悕绉�")
+    @Schema(description = "鐧昏浜哄悕绉�")
     @Excel(name = "鐧昏浜哄悕绉�")
     private String checkNickName;
 
     /**
      * 澶勭悊浜�
      */
-    @ApiModelProperty("澶勭悊浜�")
+    @Schema(description = "澶勭悊浜�")
     private Long disposeUserId;
 
     /**
      * 澶勭悊浜哄悕绉�
      */
-    @ApiModelProperty("澶勭悊浜哄悕绉�")
+    @Schema(description = "澶勭悊浜哄悕绉�")
     @Excel(name = "澶勭悊浜哄悕绉�")
     private String disposeNickName;
 
     /**
      * 瀹㈡埛鍚嶇О
      */
-    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     @Excel(name = "瀹㈡埛鍚嶇О")
     private String customerName;
 
     /**
      * 闂鎻忚堪
      */
-    @ApiModelProperty("闂鎻忚堪")
+    @Schema(description = "闂鎻忚堪")
     @Excel(name = "闂鎻忚堪")
     private String proDesc;
 
     /**
      * 澶勭悊缁撴灉
      */
-    @ApiModelProperty("澶勭悊缁撴灉")
+    @Schema(description = "澶勭悊缁撴灉")
     @Excel(name = "澶勭悊缁撴灉")
     private String disRes;
 
     /**
      * 鍙嶉鏃ユ湡
      */
-    @ApiModelProperty("鍙嶉鏃ユ湡")
+    @Schema(description = "鍙嶉鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鍙嶉鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
@@ -100,7 +99,7 @@
     /**
      * 澶勭悊鏃ユ湡
      */
-    @ApiModelProperty("澶勭悊鏃ユ湡")
+    @Schema(description = "澶勭悊鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "澶勭悊鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
@@ -138,26 +137,29 @@
     private Long tenantId;
 
     @TableField(exist = false)
-    @ApiModelProperty("閮ㄩ棬鍚嶇О")
+    @Schema(description = "閮ㄩ棬鍚嶇О")
     private String deptName;
 
 
-    @ApiModelProperty("鍞悗绫诲瀷")
+    @Schema(description = "鍞悗绫诲瀷")
     private String serviceType;
 
-    @ApiModelProperty("绱ф�ョ▼搴�")
+    @Schema(description = "绱ф�ョ▼搴�")
     private String urgency;
 
-    @ApiModelProperty("閿�鍞彴璐D")
+    @Schema(description = "閿�鍞彴璐D")
     private Long salesLedgerId;
 
-    @ApiModelProperty("鍒嗛厤浜篒D")
+    @Schema(description = "鍒嗛厤浜篒D")
     private Long distributionUserId;
 
 
-    @ApiModelProperty("浜у搧鍨嬪彿IDs")
+    @Schema(description = "浜у搧鍨嬪彿IDs")
     private String productModelIds;
 
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesServiceFile.java b/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesServiceFile.java
index 5dcae01..3dbc478 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesServiceFile.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesServiceFile.java
@@ -1,10 +1,11 @@
 package com.ruoyi.aftersalesservice.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -20,43 +21,46 @@
  */
 @Data
 @TableName("after_sales_service_file")
-@ApiModel("鍞悗鏈嶅姟闄勪欢琛�")
+@Schema(name = "鍞悗鏈嶅姟闄勪欢琛�")
 public class AfterSalesServiceFile {
 
     @TableId(type = IdType.AUTO)
-    @ApiModelProperty("涓婚敭")
+    @Schema(description = "涓婚敭")
     private Long id;
 
-    @ApiModelProperty("鍞悗鏈嶅姟璁板綍ID")
+    @Schema(description = "鍞悗鏈嶅姟璁板綍ID")
     private Long serviceId;
 
-    @ApiModelProperty("鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String fileName;
 
-    @ApiModelProperty("鏂囦欢璁块棶鍦板潃")
+    @Schema(description = "鏂囦欢璁块棶鍦板潃")
     private String fileUrl;
 
-    @ApiModelProperty("鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private Long fileSize;
 
-    @ApiModelProperty("鏂囦欢鍚庣紑")
+    @Schema(description = "鏂囦欢鍚庣紑")
     private String fileSuffix;
 
-    @ApiModelProperty("鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 1浠h〃鍒犻櫎锛�")
+    @Schema(description = "鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 1浠h〃鍒犻櫎锛�")
     private String delFlag;
 
-    @ApiModelProperty("涓婁紶鑰�")
+    @Schema(description = "涓婁紶鑰�")
     private Long createUser;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("淇敼鑰�")
+    @Schema(description = "淇敼鑰�")
     private Long updateUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceFileServiceImpl.java b/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceFileServiceImpl.java
index c1e7bd5..e78dcbe 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceFileServiceImpl.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceFileServiceImpl.java
@@ -13,8 +13,8 @@
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUtils;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
@@ -37,10 +37,10 @@
  * @since 2026/03/02 11:19
  */
 @Service
+@RequiredArgsConstructor
 public class AfterSalesServiceFileServiceImpl extends ServiceImpl<AfterSalesServiceFileMapper, AfterSalesServiceFile> implements AfterSalesServiceFileService {
 
-    @Autowired
-    private AfterSalesServiceService afterSalesServiceService;
+    private final AfterSalesServiceService afterSalesServiceService;
 
     @Value("${file.upload-dir}")
     private String uploadDir;
diff --git a/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceServiceImpl.java b/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceServiceImpl.java
index 68dfa7f..a141327 100644
--- a/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceServiceImpl.java
+++ b/src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceServiceImpl.java
@@ -21,9 +21,9 @@
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.service.ISalesLedgerProductService;
 import com.ruoyi.sales.service.ISalesLedgerService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Arrays;
@@ -36,20 +36,14 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class AfterSalesServiceServiceImpl extends ServiceImpl<AfterSalesServiceMapper, AfterSalesService> implements AfterSalesServiceService {
 
-    @Autowired
-    private AfterSalesServiceMapper afterSalesServiceMapper;
-
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-    @Autowired
-    private ISalesLedgerProductService salesLedgerProductService;
-    @Autowired
-    private ISalesLedgerService salesLedgerService;
+    private final AfterSalesServiceMapper afterSalesServiceMapper;
+    private final SysDeptMapper sysDeptMapper;
+    private final SysUserMapper sysUserMapper;
+    private final ISalesLedgerProductService salesLedgerProductService;
+    private final ISalesLedgerService salesLedgerService;
 
     @Override
     public IPage<AfterSalesServiceNewDto> listPage(Page page, AfterSalesServiceNewDto afterSalesService) {
diff --git a/src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java
new file mode 100644
index 0000000..3b37909
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoAgent.java
@@ -0,0 +1,20 @@
+package com.ruoyi.ai.assistant;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.spring.AiService;
+import reactor.core.publisher.Flux;
+
+import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;
+
+@AiService(
+        wiringMode = EXPLICIT,
+        streamingChatModel = "qwenStreamingChatModel",
+        chatMemoryProvider = "chatMemoryProviderApproveTodo",
+        tools = "approveTodoTools")
+public interface ApproveTodoAgent {
+
+    @SystemMessage(fromResource = "approve-todo-agent-prompt.txt")
+    Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage);
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java
new file mode 100644
index 0000000..9f8499d
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/ApproveTodoIntentExecutor.java
@@ -0,0 +1,296 @@
+package com.ruoyi.ai.assistant;
+
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.ai.tools.ApproveTodoTools;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Component
+public class ApproveTodoIntentExecutor {
+
+    private static final Pattern APPROVE_ID_PATTERN = Pattern.compile("\\b[A-Za-z]*\\d{8,}\\b");
+    private static final Pattern LIMIT_PATTERN = Pattern.compile("(鍓峾鏈�杩�)?(\\d{1,2})鏉�");
+    private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})");
+    private static final Pattern NUMBER_PATTERN = Pattern.compile("(\\d+(?:\\.\\d+)?)");
+    private static final Pattern RECENT_RANGE_PATTERN = Pattern.compile("杩慭\d+(澶﹟鍛▅涓湀|鏈坾骞�)");
+    private static final Pattern HALF_RANGE_PATTERN = Pattern.compile("(鏈�杩憒杩�)?鍗�(涓�)?(鏈坾骞�)");
+    private static final Pattern EXPLICIT_RANGE_PATTERN = Pattern.compile(".*(鍒皘鑷�).*");
+
+    private final ApproveTodoTools approveTodoTools;
+
+    public ApproveTodoIntentExecutor(ApproveTodoTools approveTodoTools) {
+        this.approveTodoTools = approveTodoTools;
+    }
+
+    public String tryExecute(String memoryId, String message) {
+        if (!StringUtils.hasText(message)) {
+            return null;
+        }
+
+        String text = message.trim();
+        String approveId = extractApproveId(text);
+
+        if (isStatsIntent(text)) {
+            return approveTodoTools.getTodoStats(
+                    memoryId,
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    extractTimeRange(text)
+            );
+        }
+        if (containsAny(text, "娴佽浆", "杩涘害", "鑺傜偣", "鏃ュ織", "鍗″湪", "鍗″埌", "褰撳墠瀹℃壒浜�", "澶勭悊璁板綍")) {
+            return StringUtils.hasText(approveId)
+                    ? approveTodoTools.getTodoProgress(memoryId, approveId)
+                    : missingApproveId("todo_progress", "鏌ヨ瀹℃壒杩涘害闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
+        }
+        if (containsAny(text, "璇︽儏", "鏄庣粏") && !containsAny(text, "鍒楄〃")) {
+            return StringUtils.hasText(approveId)
+                    ? approveTodoTools.getTodoDetail(memoryId, approveId)
+                    : missingApproveId("todo_detail", "鏌ヨ瀹℃壒璇︽儏闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
+        }
+        if (containsAny(text, "鍙栨秷瀹℃牳", "鎾ら攢瀹℃牳", "鍥為��瀹℃牳", "鎾ら攢瀹℃壒", "鎾ゅ洖瀹℃壒")
+                || (containsAny(text, "鎾ら攢", "鎾ゅ洖") && containsAny(text, "瀹℃壒鎿嶄綔", "瀹℃牳鎿嶄綔"))) {
+            return StringUtils.hasText(approveId)
+                    ? approveTodoTools.cancelReviewTodo(memoryId, approveId, firstNonBlank(extractTail(text, "鍘熷洜"), extractTail(text, "澶囨敞")))
+                    : missingApproveId("cancel_review_action", "鍙栨秷瀹℃牳闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
+        }
+        if (containsAny(text, "鍒犻櫎", "绉婚櫎")) {
+            return StringUtils.hasText(approveId)
+                    ? approveTodoTools.deleteTodo(memoryId, approveId)
+                    : missingApproveId("delete_action", "鍒犻櫎瀹℃壒鍗曢渶瑕佹彁渚涙祦绋嬬紪鍙枫��");
+        }
+        if (containsAny(text, "椹冲洖", "鎷掔粷")) {
+            return StringUtils.hasText(approveId)
+                    ? approveTodoTools.reviewTodo(memoryId, approveId, "reject", firstNonBlank(extractTail(text, "鍘熷洜"), extractTail(text, "澶囨敞")))
+                    : missingApproveId("review_action", "椹冲洖瀹℃壒闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
+        }
+        if (containsAny(text, "瀹℃牳閫氳繃", "瀹℃壒閫氳繃", "閫氳繃瀹℃壒", "鍚屾剰瀹℃壒", "瀹℃壒鍚屾剰")) {
+            return StringUtils.hasText(approveId)
+                    ? approveTodoTools.reviewTodo(memoryId, approveId, "approve", extractTail(text, "澶囨敞"))
+                    : missingApproveId("review_action", "瀹℃壒閫氳繃闇�瑕佹彁渚涙祦绋嬬紪鍙枫��");
+        }
+        if (StringUtils.hasText(approveId)
+                && containsAny(text, "閫氳繃", "鍚屾剰")
+                && !containsAny(text, "鏈�氳繃", "閫氳繃鐜�", "瀹℃壒閫氳繃鐜�", "瀹℃牳閫氳繃鐜�")) {
+            return approveTodoTools.reviewTodo(memoryId, approveId, "approve", extractTail(text, "澶囨敞"));
+        }
+        if (containsAny(text, "淇敼", "鏇存柊", "鍙樻洿")) {
+            return StringUtils.hasText(approveId)
+                    ? approveTodoTools.updateTodo(
+                    memoryId,
+                    approveId,
+                    extractValue(text, "鏍囬"),
+                    extractDateValue(text, "寮�濮嬫棩鏈�"),
+                    extractDateValue(text, "缁撴潫鏃ユ湡"),
+                    extractBigDecimalValue(text, "閲戦"),
+                    extractValue(text, "鍦扮偣"),
+                    extractIntegerValue(text, "绫诲瀷"),
+                    extractValue(text, "澶囨敞"))
+                    : missingApproveId("update_action", "淇敼瀹℃壒鍗曢渶瑕佹彁渚涙祦绋嬬紪鍙枫��");
+        }
+        if (containsAny(text, "鍒楄〃", "寰呭姙", "鏌ヨ瀹℃壒", "鍗曟嵁", "娴佺▼", "瀹℃壒鎵�")) {
+            return approveTodoTools.listTodos(
+                    memoryId,
+                    extractStatus(text),
+                    extractApproveType(text),
+                    extractKeyword(text),
+                    extractLimit(text),
+                    extractScope(text));
+        }
+        return null;
+    }
+
+    private boolean isStatsIntent(String text) {
+        if (containsAny(text, "缁熻", "鍒嗘瀽", "鍥捐〃", "瓒嬪娍", "鍗犳瘮", "姹囨��", "鎬婚噺", "鍒嗗竷", "鍚勬湁澶氬皯", "鏈夊灏�")) {
+            return true;
+        }
+        boolean hasQueryWord = containsAny(text, "鏌ヨ", "鏌ョ湅", "鐪嬩笅", "鐪嬬湅", "鑾峰彇");
+        boolean hasDataWord = containsAny(text, "鏁版嵁", "鎶ヨ〃", "鎯呭喌", "鏁伴噺", "閲戦");
+        boolean hasTimeWord = containsAny(text, "浠婂ぉ", "鏄ㄦ棩", "鏄ㄥぉ", "鏈懆", "涓婂懆", "鏈湀", "涓婃湀", "鏈勾", "浠婂勾", "鍘诲勾")
+                || DATE_PATTERN.matcher(text).find()
+                || RECENT_RANGE_PATTERN.matcher(text).find()
+                || HALF_RANGE_PATTERN.matcher(text).find()
+                || EXPLICIT_RANGE_PATTERN.matcher(text).matches();
+        return hasQueryWord && hasDataWord && hasTimeWord;
+    }
+
+    private boolean containsAny(String text, String... keywords) {
+        for (String keyword : keywords) {
+            if (text.contains(keyword)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private String extractApproveId(String text) {
+        Matcher matcher = APPROVE_ID_PATTERN.matcher(text);
+        return matcher.find() ? matcher.group() : null;
+    }
+
+    private Integer extractLimit(String text) {
+        Matcher matcher = LIMIT_PATTERN.matcher(text);
+        return matcher.find() ? Integer.parseInt(matcher.group(2)) : 10;
+    }
+
+    private String extractStatus(String text) {
+        if (containsAny(text, "寰呭鏍�", "寰呭鎵�")) {
+            return "pending";
+        }
+        if (containsAny(text, "瀹℃牳涓�", "澶勭悊涓�", "澶勭悊涓殑", "鍔炵悊涓�")) {
+            return "processing";
+        }
+        if (containsAny(text, "宸查�氳繃", "閫氳繃", "瀹℃牳瀹屾垚", "瀹℃壒瀹屾垚")) {
+            return "approved";
+        }
+        if (containsAny(text, "鏈�氳繃", "椹冲洖", "宸查┏鍥�", "鎷掔粷")) {
+            return "rejected";
+        }
+        if (containsAny(text, "閲嶆柊鎻愪氦")) {
+            return "resubmitted";
+        }
+        return "all";
+    }
+
+    private Integer extractApproveType(String text) {
+        if (text.contains("鍏嚭")) {
+            return 1;
+        }
+        if (text.contains("璇峰亣")) {
+            return 2;
+        }
+        if (text.contains("鍑哄樊")) {
+            return 3;
+        }
+        if (text.contains("鎶ラ攢")) {
+            return 4;
+        }
+        if (text.contains("閲囪喘")) {
+            return 5;
+        }
+        if (text.contains("鎶ヤ环")) {
+            return 6;
+        }
+        if (text.contains("鍙戣揣")) {
+            return 7;
+        }
+        if (text.contains("鍗遍櫓浣滀笟")) {
+            return 8;
+        }
+        return null;
+    }
+
+    private String extractKeyword(String text) {
+        String cleaned = text
+                .replace("鏌ヨ", "")
+                .replace("鏌ョ湅", "")
+                .replace("鍒楀嚭", "")
+                .replace("甯垜", "")
+                .replace("瀹℃壒", "")
+                .replace("鍗曟嵁", "")
+                .replace("寰呭姙", "")
+                .replace("鍒楄〃", "")
+                .replace("鍓�10鏉�", "")
+                .replace("鏈�杩�10鏉�", "")
+                .trim();
+        return cleaned.length() >= 2 ? cleaned : null;
+    }
+
+    private String extractValue(String text, String fieldName) {
+        Pattern pattern = Pattern.compile(fieldName + "(鏀逛负|淇敼涓簗鏄�)[:锛歖?[\\s]*([^,锛屻�傦紱;\\s]+)");
+        Matcher matcher = pattern.matcher(text);
+        return matcher.find() ? matcher.group(2) : null;
+    }
+
+    private String extractDateValue(String text, String fieldName) {
+        int index = text.indexOf(fieldName);
+        if (index < 0) {
+            return null;
+        }
+        Matcher matcher = DATE_PATTERN.matcher(text.substring(index));
+        return matcher.find() ? matcher.group(1) : null;
+    }
+
+    private String extractStartDate(String text) {
+        Matcher matcher = DATE_PATTERN.matcher(text);
+        return matcher.find() ? matcher.group(1) : null;
+    }
+
+    private String extractEndDate(String text) {
+        Matcher matcher = DATE_PATTERN.matcher(text);
+        if (!matcher.find()) {
+            return null;
+        }
+        return matcher.find() ? matcher.group(1) : null;
+    }
+
+    private String extractTimeRange(String text) {
+        if (containsAny(text, "浠婂ぉ", "鏄ㄦ棩", "鏄ㄥぉ", "鏈懆", "涓婂懆", "鏈湀", "涓婃湀", "鏈勾", "浠婂勾", "鍘诲勾")) {
+            return text;
+        }
+        if (RECENT_RANGE_PATTERN.matcher(text).find()) {
+            return text;
+        }
+        if (HALF_RANGE_PATTERN.matcher(text).find()) {
+            return text;
+        }
+        if (EXPLICIT_RANGE_PATTERN.matcher(text).matches()) {
+            return text;
+        }
+        return null;
+    }
+
+    private Integer extractIntegerValue(String text, String fieldName) {
+        if (!text.contains(fieldName)) {
+            return null;
+        }
+        Matcher matcher = Pattern.compile(fieldName + "(鏀逛负|淇敼涓簗鏄�)[:锛歖?[\\s]*(\\d{1,2})").matcher(text);
+        return matcher.find() ? Integer.parseInt(matcher.group(2)) : null;
+    }
+
+    private BigDecimal extractBigDecimalValue(String text, String fieldName) {
+        int index = text.indexOf(fieldName);
+        if (index < 0) {
+            return null;
+        }
+        Matcher matcher = NUMBER_PATTERN.matcher(text.substring(index));
+        return matcher.find() ? new BigDecimal(matcher.group(1)) : null;
+    }
+
+    private String extractTail(String text, String key) {
+        Pattern pattern = Pattern.compile(key + "(鏄瘄涓�)?[:锛歖?[\\s]*(.+)");
+        Matcher matcher = pattern.matcher(text);
+        return matcher.find() ? matcher.group(2).trim() : null;
+    }
+
+    private String extractScope(String text) {
+        if (containsAny(text, "鎴戝彂璧�", "鎴戞彁浜�", "鎴戠敵璇�", "鐢宠浜烘槸鎴�")) {
+            return "applicant";
+        }
+        if (containsAny(text, "寰呮垜瀹℃壒", "寰呮垜瀹℃牳", "鎴戝鐞�", "鎴戝鎵�", "褰撳墠寰呮垜", "闇�瑕佹垜澶勭悊")) {
+            return "approver";
+        }
+        return "related";
+    }
+
+    private String firstNonBlank(String first, String second) {
+        return StringUtils.hasText(first) ? first : second;
+    }
+
+    private String missingApproveId(String type, String description) {
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("success", false);
+        result.put("type", type);
+        result.put("description", description);
+        result.put("summary", Map.of());
+        result.put("data", Map.of());
+        result.put("charts", Map.of());
+        return JSON.toJSONString(result);
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/Assistant.java b/src/main/java/com/ruoyi/ai/assistant/Assistant.java
new file mode 100644
index 0000000..f0718c0
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/Assistant.java
@@ -0,0 +1,16 @@
+package com.ruoyi.ai.assistant;
+
+import dev.langchain4j.service.spring.AiService;
+
+import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;
+
+/**
+ * @author :yys
+ * @date : 2025/5/2 18:26
+ */
+//鍥犱负鎴戜滑鍦ㄩ厤缃枃浠朵腑鍚屾椂閰嶇疆浜嗗涓ぇ璇█妯″瀷锛屾墍浠ラ渶瑕佸湪杩欓噷鏄庣‘鎸囧畾锛圗XPLICIT锛夋ā鍨嬬殑beanName
+
+@AiService(wiringMode = EXPLICIT, chatModel = "qwenChatModel")
+public interface Assistant {
+    String chat(String userMessage);
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/FileAnalyzeAgent.java b/src/main/java/com/ruoyi/ai/assistant/FileAnalyzeAgent.java
new file mode 100644
index 0000000..131a9b7
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/FileAnalyzeAgent.java
@@ -0,0 +1,24 @@
+package com.ruoyi.ai.assistant;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.spring.AiService;
+import reactor.core.publisher.Flux;
+
+import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;
+
+@AiService(
+        wiringMode = EXPLICIT,
+        streamingChatModel = "qwenStreamingChatModel",
+        chatMemoryProvider = "chatMemoryProvider"
+)
+public interface FileAnalyzeAgent {
+
+    @SystemMessage("""
+            浣犳槸浼佷笟鏂囨。鍒嗘瀽鍔╂墜銆�
+            璇蜂弗鏍煎熀浜庣敤鎴锋彁渚涚殑鏂囦欢鍐呭杩涜鍒嗘瀽锛岃緭鍑鸿缁撴瀯鍖栥�佸噯纭�佺畝娲併��
+            鑻ユ枃浠跺唴瀹逛笉瓒充互鏀寔缁撹锛屾槑纭寚鍑衡�滀笉瓒充俊鎭�濆苟缁欏嚭闇�瑕佽ˉ鍏呯殑鏁版嵁椤广��
+            """)
+    Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage);
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java b/src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java
new file mode 100644
index 0000000..6a4ff4e
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/PurchaseAgent.java
@@ -0,0 +1,21 @@
+package com.ruoyi.ai.assistant;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.spring.AiService;
+import reactor.core.publisher.Flux;
+
+import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;
+
+@AiService(
+        wiringMode = EXPLICIT,
+        streamingChatModel = "qwenStreamingChatModel",
+        chatMemoryProvider = "chatMemoryProviderPurchase",
+        tools = "purchaseAgentTools"
+)
+public interface PurchaseAgent {
+
+    @SystemMessage(fromResource = "purchase-agent-prompt.txt")
+    Flux<String> chat(@MemoryId String memoryId, @UserMessage String userMessage);
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java b/src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java
new file mode 100644
index 0000000..5991fc3
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/PurchaseIntentExecutor.java
@@ -0,0 +1,161 @@
+package com.ruoyi.ai.assistant;
+
+import com.ruoyi.ai.tools.PurchaseAgentTools;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Component
+public class PurchaseIntentExecutor {
+
+    private static final Pattern ID_PATTERN = Pattern.compile("\\b\\d{1,12}\\b");
+    private static final Pattern LIMIT_PATTERN = Pattern.compile("(鍓峾鏈�杩�)?(\\d{1,2})鏉�");
+    private static final Pattern DATE_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
+
+    private final PurchaseAgentTools purchaseAgentTools;
+
+    public PurchaseIntentExecutor(PurchaseAgentTools purchaseAgentTools) {
+        this.purchaseAgentTools = purchaseAgentTools;
+    }
+
+    public String tryExecute(String memoryId, String message) {
+        if (!StringUtils.hasText(message)) {
+            return null;
+        }
+        String text = message.trim();
+
+        if (containsAny(text, "鎺掕", "鎺掑悕", "鍓嶅嚑", "鍓嶄簲", "鍓嶅崄") && containsAny(text, "鐗╂枡", "浜у搧", "鍘熸潗鏂�", "閲囪喘閲戦", "閲戦")) {
+            return purchaseAgentTools.rankPurchaseMaterials(
+                    memoryId,
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    text,
+                    extractLimit(text)
+            );
+        }
+        if (containsAny(text, "鏈叆搴�", "寰呭叆搴�", "娌℃湁鍏ュ簱", "杩樻湭鍏ュ簱")) {
+            return purchaseAgentTools.listUnstockedPurchaseOrders(
+                    memoryId,
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    extractKeyword(text),
+                    extractLimit(text)
+            );
+        }
+        if (containsAny(text, "鍒拌揣寮傚父", "鍒拌揣鏈夊紓甯�", "寮傚父鍒拌揣", "鍒拌揣闂", "渚涘簲鍟嗗埌璐у紓甯�")) {
+            return purchaseAgentTools.listArrivalExceptions(
+                    memoryId,
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    text,
+                    extractLimit(text)
+            );
+        }
+        if (containsAny(text, "寰呬粯娆�", "鏈粯娆�", "鏈粯娓�", "寰呮敮浠�", "搴斾粯")) {
+            return purchaseAgentTools.listPendingPaymentOrders(
+                    memoryId,
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    extractKeyword(text),
+                    extractLimit(text)
+            );
+        }
+        if (containsAny(text, "閫�璐�", "閫�鏂�", "鎷掓敹")) {
+            return purchaseAgentTools.listPurchaseReturns(
+                    memoryId,
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    extractKeyword(text),
+                    extractLimit(text)
+            );
+        }
+        if (isStatsIntent(text)) {
+            return purchaseAgentTools.getPurchaseStats(
+                    memoryId,
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    text
+            );
+        }
+        if (containsAny(text, "璇︽儏", "鏄庣粏") && extractId(text) != null) {
+            return purchaseAgentTools.getPurchaseLedgerDetail(memoryId, extractId(text));
+        }
+        if (containsAny(text, "鍙拌处", "閲囪喘鍗�", "閲囪喘璁㈠崟", "璁㈠崟", "鍚堝悓", "鍒楄〃", "鏌ヨ")) {
+            return purchaseAgentTools.listPurchaseLedgers(
+                    memoryId,
+                    extractKeyword(text),
+                    extractStartDate(text),
+                    extractEndDate(text),
+                    extractLimit(text)
+            );
+        }
+        return null;
+    }
+
+    private boolean isStatsIntent(String text) {
+        if (containsAny(text, "缁熻", "鍒嗘瀽", "鎶ヨ〃", "姹囨��", "瓒嬪娍", "鏁版嵁鐪嬫澘", "鎯呭喌", "鏈夊灏�")) {
+            return true;
+        }
+        boolean queryWord = containsAny(text, "鏌ヨ", "鏌ョ湅", "鐪嬩笅", "鐪嬬湅", "鑾峰彇");
+        boolean dataWord = containsAny(text, "鏁版嵁", "閲戦", "鏁伴噺", "鍚堝悓棰�", "浠樻棰�", "鍙戠エ棰�");
+        boolean timeWord = containsAny(text, "浠婂ぉ", "鏈懆", "鏈湀", "涓婃湀", "浠婂勾", "鍘诲勾", "杩戝崐骞�", "鏈�杩戝崐涓湀", "鍗婁釜鏈�")
+                || DATE_PATTERN.matcher(text).find();
+        return queryWord && dataWord && timeWord;
+    }
+
+    private boolean containsAny(String text, String... keywords) {
+        for (String keyword : keywords) {
+            if (text.contains(keyword)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Long extractId(String text) {
+        Matcher matcher = ID_PATTERN.matcher(text);
+        if (!matcher.find()) {
+            return null;
+        }
+        return Long.parseLong(matcher.group());
+    }
+
+    private Integer extractLimit(String text) {
+        Matcher matcher = LIMIT_PATTERN.matcher(text);
+        return matcher.find() ? Integer.parseInt(matcher.group(2)) : 10;
+    }
+
+    private String extractStartDate(String text) {
+        Matcher matcher = DATE_PATTERN.matcher(text);
+        return matcher.find() ? matcher.group() : null;
+    }
+
+    private String extractEndDate(String text) {
+        Matcher matcher = DATE_PATTERN.matcher(text);
+        if (!matcher.find()) {
+            return null;
+        }
+        return matcher.find() ? matcher.group() : null;
+    }
+
+    private String extractKeyword(String text) {
+        String cleaned = text
+                .replace("鏌ヨ", "")
+                .replace("鏌ョ湅", "")
+                .replace("閲囪喘", "")
+                .replace("閲囪喘鍗�", "")
+                .replace("閲囪喘璁㈠崟", "")
+                .replace("璁㈠崟", "")
+                .replace("鍙拌处", "")
+                .replace("鍒楄〃", "")
+                .replace("鍝簺", "")
+                .replace("鍒楀嚭", "")
+                .replace("甯垜", "")
+                .replace("鏈�杩�10鏉�", "")
+                .replace("鍓�10鏉�", "")
+                .trim();
+        return cleaned.length() >= 2 ? cleaned : null;
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/assistant/SeparateChatAssistant.java b/src/main/java/com/ruoyi/ai/assistant/SeparateChatAssistant.java
new file mode 100644
index 0000000..fa36ad5
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/assistant/SeparateChatAssistant.java
@@ -0,0 +1,35 @@
+package com.ruoyi.ai.assistant;
+
+import dev.langchain4j.service.MemoryId;
+import dev.langchain4j.service.SystemMessage;
+import dev.langchain4j.service.UserMessage;
+import dev.langchain4j.service.V;
+import dev.langchain4j.service.spring.AiService;
+import dev.langchain4j.service.spring.AiServiceWiringMode;
+
+/**
+ * @author :yys
+ * @date : 2025/5/2 19:35
+ */
+@AiService(
+        wiringMode = AiServiceWiringMode.EXPLICIT,
+        chatModel = "qwenChatModel",
+        chatMemoryProvider = "chatMemoryProvider"
+)
+public interface SeparateChatAssistant {
+
+    @SystemMessage(fromResource = "my-prompt-template.txt")//绯荤粺娑堟伅鎻愮ず璇�
+    String chat(@MemoryId String memoryId, @UserMessage String userMessage);
+
+    @UserMessage("浣犳槸鎴戠殑濂芥湅鍙嬶紝璇风敤绮よ鍥炵瓟闂銆倇{message}}")
+    String chat2(@MemoryId String memoryId, @V("message") String userMessage);
+
+    @SystemMessage(fromResource = "my-prompt-template3.txt")
+    String chat3(
+            @MemoryId String memoryId,
+            @UserMessage String userMessage,
+            @V("username") String username,
+            @V("age") int age
+    );
+
+}
diff --git a/src/main/java/com/ruoyi/ai/bean/ChatForm.java b/src/main/java/com/ruoyi/ai/bean/ChatForm.java
new file mode 100644
index 0000000..60d1a6e
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/bean/ChatForm.java
@@ -0,0 +1,15 @@
+package com.ruoyi.ai.bean;
+
+import lombok.Data;
+
+/**
+ * @author :yys
+ * @date : 2025/5/2 20:03
+ */
+@Data
+public class ChatForm {
+
+    private String memoryId;//瀵硅瘽id
+    private String message;//鐢ㄦ埛闂
+
+}
diff --git a/src/main/java/com/ruoyi/ai/bean/PurchaseAiConfirmRequest.java b/src/main/java/com/ruoyi/ai/bean/PurchaseAiConfirmRequest.java
new file mode 100644
index 0000000..f727981
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/bean/PurchaseAiConfirmRequest.java
@@ -0,0 +1,26 @@
+package com.ruoyi.ai.bean;
+
+import java.util.Map;
+
+public class PurchaseAiConfirmRequest {
+
+    private String businessType;
+
+    private Map<String, Object> payload;
+
+    public String getBusinessType() {
+        return businessType;
+    }
+
+    public void setBusinessType(String businessType) {
+        this.businessType = businessType;
+    }
+
+    public Map<String, Object> getPayload() {
+        return payload;
+    }
+
+    public void setPayload(Map<String, Object> payload) {
+        this.payload = payload;
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/config/ApproveTodoAgentConfig.java b/src/main/java/com/ruoyi/ai/config/ApproveTodoAgentConfig.java
new file mode 100644
index 0000000..61cc0dd
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/config/ApproveTodoAgentConfig.java
@@ -0,0 +1,20 @@
+package com.ruoyi.ai.config;
+
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ApproveTodoAgentConfig {
+
+    @Bean
+    ChatMemoryProvider chatMemoryProviderApproveTodo(MongoChatMemoryStore mongoChatMemoryStore) {
+        return memoryId -> MessageWindowChatMemory.builder()
+                .id(memoryId)
+                .maxMessages(30)
+                .chatMemoryStore(mongoChatMemoryStore)
+                .build();
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/config/EmbeddingStoreConfig.java b/src/main/java/com/ruoyi/ai/config/EmbeddingStoreConfig.java
new file mode 100644
index 0000000..ca5156d
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/config/EmbeddingStoreConfig.java
@@ -0,0 +1,36 @@
+package com.ruoyi.ai.config;
+
+import dev.langchain4j.data.segment.TextSegment;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import dev.langchain4j.store.embedding.pinecone.PineconeEmbeddingStore;
+import dev.langchain4j.store.embedding.pinecone.PineconeServerlessIndexConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author :yys
+ * @date : 2025/5/2 21:07
+ */
+@Configuration
+public class EmbeddingStoreConfig {
+
+    @Autowired
+    private EmbeddingModel embeddingModel;
+
+    @Bean
+    public EmbeddingStore<TextSegment> embeddingStore() {
+        //鍒涘缓鍚戦噺瀛樺偍
+        return PineconeEmbeddingStore.builder()
+                .apiKey("pcsk_4SJLnh_tNB3wSLJU8tc4E5P28PcXX8eCLdURqZpVhg1FMV8CRYxjneWdzqRdB5Ftqooi9")
+                .index("xiaozhi-index")//濡傛灉鎸囧畾鐨勭储寮曚笉瀛樺湪锛屽皢鍒涘缓涓�涓柊鐨勭储寮�
+                .nameSpace("xiaozhi-namespace") //濡傛灉鎸囧畾鐨勫悕绉扮┖闂翠笉瀛樺湪锛屽皢鍒涘缓涓�涓柊鐨勫悕绉� 绌洪棿
+                .createIndex(PineconeServerlessIndexConfig.builder()
+                        .cloud("AWS") //鎸囧畾绱㈠紩閮ㄧ讲鍦� AWS 浜戞湇鍔′笂銆�
+                        .region("us-east-1") //鎸囧畾绱㈠紩鎵�鍦ㄧ殑 AWS 鍖哄煙涓� us-east-1銆�
+                        .dimension(embeddingModel.dimension()) //鎸囧畾绱㈠紩鐨勫悜閲忕淮搴︼紝璇ョ淮搴︿笌 embeddedModel 鐢熸垚鐨勫悜閲忕淮搴︾浉鍚屻��
+                        .build())
+                .build();
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/config/PurchaseAgentConfig.java b/src/main/java/com/ruoyi/ai/config/PurchaseAgentConfig.java
new file mode 100644
index 0000000..62061ee
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/config/PurchaseAgentConfig.java
@@ -0,0 +1,32 @@
+package com.ruoyi.ai.config;
+
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class PurchaseAgentConfig {
+
+    @Bean
+    ChatMemoryProvider chatMemoryProviderPurchase(MongoChatMemoryStore mongoChatMemoryStore) {
+        return memoryId -> MessageWindowChatMemory.builder()
+                .id(memoryId)
+                .maxMessages(30)
+                .chatMemoryStore(mongoChatMemoryStore)
+                .build();
+    }
+
+    @Bean("purchaseVisionStreamingChatModel")
+    QwenStreamingChatModel purchaseVisionStreamingChatModel(
+            @Value("${langchain4j.community.dashscope.streaming-chat-model.api-key}") String apiKey) {
+        return QwenStreamingChatModel.builder()
+                .apiKey(apiKey)
+                .modelName("qwen-vl-max")
+                .isMultimodalModel(true)
+                .build();
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/config/SeparateChatAssistantConfig.java b/src/main/java/com/ruoyi/ai/config/SeparateChatAssistantConfig.java
new file mode 100644
index 0000000..1927843
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/config/SeparateChatAssistantConfig.java
@@ -0,0 +1,29 @@
+package com.ruoyi.ai.config;
+
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author :yys
+ * @date : 2025/5/2 19:20
+ */
+@Configuration
+public class SeparateChatAssistantConfig {
+    //娉ㄥ叆鎸佷箙鍖栧璞�
+    @Autowired
+    private MongoChatMemoryStore mongoChatMemoryStore;
+
+    @Bean
+    ChatMemoryProvider chatMemoryProvider() {
+        return memoryId -> MessageWindowChatMemory.builder()
+                .id(memoryId)
+                .maxMessages(10)
+                .chatMemoryStore(mongoChatMemoryStore)//閰嶇疆鎸佷箙鍖栧璞�
+                .build();
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java b/src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java
new file mode 100644
index 0000000..27e5a6b
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/config/XiaozhiAgentConfig.java
@@ -0,0 +1,91 @@
+package com.ruoyi.ai.config;
+
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import dev.langchain4j.memory.chat.ChatMemoryProvider;
+import dev.langchain4j.memory.chat.MessageWindowChatMemory;
+import dev.langchain4j.model.embedding.EmbeddingModel;
+import dev.langchain4j.rag.content.retriever.ContentRetriever;
+import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
+import dev.langchain4j.store.embedding.EmbeddingStore;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author :yys
+ * @date : 2025/5/2 20:01
+ */
+@Configuration
+public class XiaozhiAgentConfig {
+
+    @Autowired
+    private MongoChatMemoryStore mongoChatMemoryStore;
+
+    @Autowired
+    private EmbeddingStore embeddingStore;
+    @Autowired
+    private EmbeddingModel embeddingModel;
+
+//    @Value("${knowledge.one}")
+//    private String one;
+//
+//    @Value("${knowledge.two}")
+//    private String two;
+//
+//    @Value("${knowledge.three}")
+//    private String three;
+
+    @Bean
+    ChatMemoryProvider chatMemoryProviderXiaozhi() {
+        return memoryId -> MessageWindowChatMemory.builder()
+                .id(memoryId)
+                .maxMessages(20)
+                .chatMemoryStore(mongoChatMemoryStore)
+                .build();
+    }
+
+//    @Bean
+//    ContentRetriever contentRetrieverXiaozhi() {
+//        //浣跨敤FileSystemDocumentLoader璇诲彇鎸囧畾鐩綍涓嬬殑鐭ヨ瘑搴撴枃妗�
+//        //骞朵娇鐢ㄩ粯璁ょ殑鏂囨。瑙f瀽鍣ㄥ鏂囨。杩涜瑙f瀽
+//        Document document1 = FileSystemDocumentLoader.loadDocument(one);
+////        Document document2 = FileSystemDocumentLoader.loadDocument(two);
+////        Document document3 = FileSystemDocumentLoader.loadDocument(three);
+////        List<Document> documents = Arrays.asList(document1, document2, document3);
+//
+//        List<Document> documents = Collections.singletonList(document1);
+////         2. 灏嗘暟鎹簱鏁版嵁杞负LangChain4j鐨凞ocument瀵硅薄
+////        List<Document> documents = new ArrayList<>();
+//
+//        //浣跨敤鍐呭瓨鍚戦噺瀛樺偍
+//        InMemoryEmbeddingStore<TextSegment> inMemoryEmbeddingStore = new InMemoryEmbeddingStore<>();
+//        //浣跨敤榛樿鐨勬枃妗e垎鍓插櫒
+//        EmbeddingStoreIngestor.builder()
+//                .embeddingModel(embeddingModel)
+//                .embeddingStore(inMemoryEmbeddingStore)
+//                .build()
+//                .ingest(documents);
+//        //浠庡祵鍏ュ瓨鍌紙EmbeddingStore锛夐噷妫�绱㈠拰鏌ヨ鍐呭鐩稿叧鐨勪俊鎭�
+//        return EmbeddingStoreContentRetriever.builder()
+//                .embeddingModel(embeddingModel)
+//                .embeddingStore(inMemoryEmbeddingStore)
+//                .build();
+//    }
+
+    @Bean
+    ContentRetriever contentRetrieverXiaozhiPincone() {
+        // 鍒涘缓涓�涓� EmbeddingStoreContentRetriever 瀵硅薄锛岀敤浜庝粠宓屽叆瀛樺偍涓绱㈠唴瀹�
+        return EmbeddingStoreContentRetriever
+                .builder()
+                // 璁剧疆鐢ㄤ簬鐢熸垚宓屽叆鍚戦噺鐨勫祵鍏ユā鍨�
+                .embeddingModel(embeddingModel)
+                // 鎸囧畾瑕佷娇鐢ㄧ殑宓屽叆瀛樺偍
+                .embeddingStore(embeddingStore)
+                // 璁剧疆鏈�澶ф绱㈢粨鏋滄暟閲忥紝杩欓噷琛ㄧず鏈�澶氳繑鍥� 1 鏉″尮閰嶇粨鏋�
+                .maxResults(1)
+                // 璁剧疆鏈�灏忓緱鍒嗛槇鍊硷紝鍙湁寰楀垎澶т簬绛変簬 0.8 鐨勭粨鏋滄墠浼氳杩斿洖
+                .minScore(0.8)
+                // 鏋勫缓鏈�缁堢殑 EmbeddingStoreContentRetriever 瀹炰緥
+                .build();
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/context/AiSessionUserContext.java b/src/main/java/com/ruoyi/ai/context/AiSessionUserContext.java
new file mode 100644
index 0000000..3a5877b
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/context/AiSessionUserContext.java
@@ -0,0 +1,35 @@
+package com.ruoyi.ai.context;
+
+import com.ruoyi.framework.security.LoginUser;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class AiSessionUserContext {
+
+    private final Map<String, LoginUser> loginUserByMemoryId = new ConcurrentHashMap<>();
+
+    public void bind(String memoryId, LoginUser loginUser) {
+        if (!StringUtils.hasText(memoryId) || loginUser == null) {
+            return;
+        }
+        loginUserByMemoryId.put(memoryId, loginUser);
+    }
+
+    public LoginUser get(String memoryId) {
+        if (!StringUtils.hasText(memoryId)) {
+            return null;
+        }
+        return loginUserByMemoryId.get(memoryId);
+    }
+
+    public void remove(String memoryId) {
+        if (!StringUtils.hasText(memoryId)) {
+            return;
+        }
+        loginUserByMemoryId.remove(memoryId);
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/controller/PurchaseAiController.java b/src/main/java/com/ruoyi/ai/controller/PurchaseAiController.java
new file mode 100644
index 0000000..2bb0625
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/controller/PurchaseAiController.java
@@ -0,0 +1,903 @@
+package com.ruoyi.ai.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.ai.assistant.PurchaseAgent;
+import com.ruoyi.ai.assistant.PurchaseIntentExecutor;
+import com.ruoyi.ai.bean.ChatForm;
+import com.ruoyi.ai.bean.PurchaseAiConfirmRequest;
+import com.ruoyi.ai.context.AiSessionUserContext;
+import com.ruoyi.ai.service.AiChatSessionService;
+import com.ruoyi.ai.service.AiFileTextExtractor;
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import com.ruoyi.basic.mapper.SupplierManageMapper;
+import com.ruoyi.basic.pojo.SupplierManage;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.purchase.dto.PurchaseLedgerDto;
+import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
+import com.ruoyi.purchase.pojo.PaymentRegistration;
+import com.ruoyi.purchase.service.IPaymentRegistrationService;
+import com.ruoyi.purchase.service.IPurchaseLedgerService;
+import com.ruoyi.purchase.service.PurchaseReturnOrdersService;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import dev.langchain4j.data.image.Image;
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.data.message.ChatMessage;
+import dev.langchain4j.data.message.Content;
+import dev.langchain4j.data.message.ImageContent;
+import dev.langchain4j.data.message.SystemMessage;
+import dev.langchain4j.data.message.TextContent;
+import dev.langchain4j.data.message.UserMessage;
+import dev.langchain4j.model.chat.StreamingChatLanguageModel;
+import dev.langchain4j.model.chat.response.ChatResponse;
+import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import reactor.core.publisher.Flux;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Base64;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.UUID;
+
+@Tag(name = "閲囪喘鏅鸿兘浣�")
+@RestController
+@RequestMapping("/purchase-ai")
+public class PurchaseAiController extends BaseController {
+
+    private static final String PURCHASE_FILE_ANALYZE_MEMORY_PREFIX = "purchase-file-analyze::";
+    private static final int MAX_FILE_COUNT = 10;
+    private static final int MAX_SINGLE_FILE_TEXT_LENGTH = 8000;
+    private static final int MAX_TOTAL_FILE_TEXT_LENGTH = 30000;
+
+    private final PurchaseAgent purchaseAgent;
+    private final PurchaseIntentExecutor purchaseIntentExecutor;
+    private final AiSessionUserContext aiSessionUserContext;
+    private final MongoChatMemoryStore mongoChatMemoryStore;
+    private final AiChatSessionService aiChatSessionService;
+    private final AiFileTextExtractor aiFileTextExtractor;
+    private final ObjectMapper objectMapper;
+    private final IPurchaseLedgerService purchaseLedgerService;
+    private final IPaymentRegistrationService paymentRegistrationService;
+    private final PurchaseReturnOrdersService purchaseReturnOrdersService;
+    private final SupplierManageMapper supplierManageMapper;
+    private final StreamingChatLanguageModel purchaseVisionStreamingChatModel;
+
+    public PurchaseAiController(PurchaseAgent purchaseAgent,
+                                PurchaseIntentExecutor purchaseIntentExecutor,
+                                AiSessionUserContext aiSessionUserContext,
+                                MongoChatMemoryStore mongoChatMemoryStore,
+                                AiChatSessionService aiChatSessionService,
+                                AiFileTextExtractor aiFileTextExtractor,
+                                ObjectMapper objectMapper,
+                                IPurchaseLedgerService purchaseLedgerService,
+                                IPaymentRegistrationService paymentRegistrationService,
+                                PurchaseReturnOrdersService purchaseReturnOrdersService,
+                                SupplierManageMapper supplierManageMapper,
+                                @Qualifier("purchaseVisionStreamingChatModel") StreamingChatLanguageModel purchaseVisionStreamingChatModel) {
+        this.purchaseAgent = purchaseAgent;
+        this.purchaseIntentExecutor = purchaseIntentExecutor;
+        this.aiSessionUserContext = aiSessionUserContext;
+        this.mongoChatMemoryStore = mongoChatMemoryStore;
+        this.aiChatSessionService = aiChatSessionService;
+        this.aiFileTextExtractor = aiFileTextExtractor;
+        this.objectMapper = objectMapper;
+        this.purchaseLedgerService = purchaseLedgerService;
+        this.paymentRegistrationService = paymentRegistrationService;
+        this.purchaseReturnOrdersService = purchaseReturnOrdersService;
+        this.supplierManageMapper = supplierManageMapper;
+        this.purchaseVisionStreamingChatModel = purchaseVisionStreamingChatModel;
+    }
+
+    @Operation(summary = "閲囪喘瀵硅瘽")
+    @PostMapping(value = "/chat", produces = "text/stream;charset=utf-8")
+    public Flux<String> chat(@RequestBody ChatForm chatForm) {
+        if (!StringUtils.hasText(chatForm.getMemoryId())) {
+            return Flux.just("memoryId涓嶈兘涓虹┖");
+        }
+        if (!StringUtils.hasText(chatForm.getMessage())) {
+            return Flux.just("message涓嶈兘涓虹┖");
+        }
+
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        String memoryId = chatForm.getMemoryId();
+        String userMessage = chatForm.getMessage();
+
+        aiSessionUserContext.bind(memoryId, loginUser);
+        aiChatSessionService.touchSession(memoryId, loginUser, userMessage);
+
+        String directResponse = purchaseIntentExecutor.tryExecute(memoryId, userMessage);
+        if (StringUtils.isNotEmpty(directResponse)) {
+            mongoChatMemoryStore.appendMessages(
+                    memoryId,
+                    List.of(UserMessage.from(userMessage), AiMessage.from(directResponse))
+            );
+            aiChatSessionService.refreshSessionStats(memoryId, loginUser);
+            return Flux.just(directResponse);
+        }
+
+        return purchaseAgent.chat(memoryId, userMessage)
+                .doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
+                .doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
+    }
+
+    @Operation(summary = "閲囪喘澶氭枃浠跺垎鏋�")
+    @PostMapping(value = "/analyze-files", consumes = "multipart/form-data", produces = "text/stream;charset=utf-8")
+    public Flux<String> analyzeFiles(@RequestParam("files") MultipartFile[] files,
+                                     @RequestParam(value = "message", required = false) String message,
+                                     @RequestParam(value = "memoryId", required = false) String memoryId) {
+        if (files == null || files.length == 0) {
+            return Flux.just("files涓嶈兘涓虹┖");
+        }
+        if (files.length > MAX_FILE_COUNT) {
+            return Flux.just("涓�娆℃渶澶氬垎鏋�" + MAX_FILE_COUNT + "涓枃浠�");
+        }
+
+        String rawMemoryId = StringUtils.hasText(memoryId) ? memoryId : UUID.randomUUID().toString();
+        String finalMemoryId = rawMemoryId.startsWith(PURCHASE_FILE_ANALYZE_MEMORY_PREFIX)
+                ? rawMemoryId
+                : PURCHASE_FILE_ANALYZE_MEMORY_PREFIX + rawMemoryId;
+
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        aiSessionUserContext.bind(finalMemoryId, loginUser);
+
+        String finalMessage = StringUtils.hasText(message)
+                ? message
+                : "璇峰垎鏋愯繖浜涢噰璐枃浠讹紝鎻愬彇鍙敤浜庝笟鍔″鐞嗙殑鏁版嵁锛屽苟鏁寸悊鎴愬緟瀹㈡埛纭鐨勬牸寮�";
+
+        String fileContent;
+        try {
+            fileContent = buildMultiFileContent(files);
+        } catch (IllegalArgumentException ex) {
+            return Flux.just(ex.getMessage());
+        } catch (IOException ex) {
+            return Flux.just("鏂囦欢璇诲彇澶辫触");
+        }
+
+        if (!StringUtils.hasText(fileContent)) {
+            return Flux.just("鏈彁鍙栧埌鏈夋晥鏂囦欢鍐呭");
+        }
+
+        String userPrompt = buildPurchaseFileAnalyzePrompt(finalMessage, fileContent);
+        aiChatSessionService.touchSession(finalMemoryId, loginUser, "閲囪喘澶氭枃浠跺垎鏋�: " + finalMessage);
+
+        if (containsImageFile(files)) {
+            return chatWithPurchaseVisionModel(finalMemoryId, userPrompt, files)
+                    .doOnComplete(() -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser))
+                    .doOnError(ex -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser));
+        }
+
+        return Flux.defer(() -> purchaseAgent.chat(finalMemoryId, userPrompt))
+                .onErrorResume(NoSuchElementException.class, ex -> {
+                    mongoChatMemoryStore.deleteMessages(finalMemoryId);
+                    return purchaseAgent.chat(finalMemoryId, userPrompt);
+                })
+                .doOnComplete(() -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser))
+                .doOnError(ex -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser));
+    }
+
+    @Operation(summary = "閲囪喘澶氭枃浠跺垎鏋愮‘璁ゅ鐞�")
+    @PostMapping("/analyze-files/confirm")
+    public AjaxResult confirmAnalyzeResult(@RequestBody PurchaseAiConfirmRequest request) {
+        if (request == null || !StringUtils.hasText(request.getBusinessType())) {
+            return AjaxResult.error("businessType涓嶈兘涓虹┖");
+        }
+        if (request.getPayload() == null || request.getPayload().isEmpty()) {
+            return AjaxResult.error("payload涓嶈兘涓虹┖");
+        }
+
+        try {
+            String businessType = request.getBusinessType().trim();
+            return switch (businessType) {
+                case "purchase_ledger" -> processPurchaseLedger(request.getPayload());
+                case "payment_registration" -> processPaymentRegistration(request.getPayload());
+                case "purchase_return_order" -> processPurchaseReturnOrder(request.getPayload());
+                default -> AjaxResult.error("鏆備笉鏀寔璇ヤ笟鍔$被鍨�: " + businessType);
+            };
+        } catch (Exception ex) {
+            return AjaxResult.error(toCustomerMessage(ex));
+        }
+    }
+
+    @Operation(summary = "閲囪喘浼氳瘽鍒楄〃")
+    @GetMapping("/history/sessions")
+    public AjaxResult listSessions() {
+        return success(aiChatSessionService.listCurrentUserSessions(SecurityUtils.getLoginUser()));
+    }
+
+    @Operation(summary = "閲囪喘浼氳瘽娑堟伅")
+    @GetMapping("/history/messages/{memoryId}")
+    public AjaxResult listMessages(@PathVariable String memoryId) {
+        return success(aiChatSessionService.listCurrentUserMessages(memoryId, SecurityUtils.getLoginUser()));
+    }
+
+    @Operation(summary = "鍒犻櫎閲囪喘浼氳瘽")
+    @DeleteMapping("/history/{memoryId}")
+    public AjaxResult deleteSession(@PathVariable String memoryId) {
+        aiSessionUserContext.remove(memoryId);
+        return toAjax(aiChatSessionService.deleteCurrentUserSession(memoryId, SecurityUtils.getLoginUser()));
+    }
+
+    private String buildMultiFileContent(MultipartFile[] files) throws IOException {
+        StringBuilder builder = new StringBuilder();
+        int totalLength = 0;
+        for (MultipartFile file : files) {
+            String text = aiFileTextExtractor.extractText(file);
+            if (!StringUtils.hasText(text)) {
+                continue;
+            }
+            String limitedText = text.length() > MAX_SINGLE_FILE_TEXT_LENGTH
+                    ? text.substring(0, MAX_SINGLE_FILE_TEXT_LENGTH)
+                    : text;
+            if (totalLength + limitedText.length() > MAX_TOTAL_FILE_TEXT_LENGTH) {
+                int remain = MAX_TOTAL_FILE_TEXT_LENGTH - totalLength;
+                if (remain <= 0) {
+                    break;
+                }
+                limitedText = limitedText.substring(0, remain);
+            }
+            builder.append("\n--- 鏂囦欢: ")
+                    .append(file.getOriginalFilename())
+                    .append(" ---\n")
+                    .append(limitedText)
+                    .append('\n');
+            totalLength += limitedText.length();
+        }
+        return builder.toString();
+    }
+
+    private boolean containsImageFile(MultipartFile[] files) {
+        for (MultipartFile file : files) {
+            if (aiFileTextExtractor.isImageFile(file)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Flux<String> chatWithPurchaseVisionModel(String memoryId, String userPrompt, MultipartFile[] files) {
+        return Flux.create(sink -> {
+            try {
+                List<Content> contents = new ArrayList<>();
+                contents.add(TextContent.from(userPrompt));
+                for (MultipartFile file : files) {
+                    if (!aiFileTextExtractor.isImageFile(file)) {
+                        continue;
+                    }
+                    contents.add(TextContent.from("涓嬮潰杩欏紶鍥剧墖鏂囦欢鍚嶏細" + file.getOriginalFilename()));
+                    contents.add(ImageContent.from(Image.builder()
+                            .base64Data(Base64.getEncoder().encodeToString(file.getBytes()))
+                            .mimeType(resolveImageMimeType(file))
+                            .build()));
+                }
+
+                List<ChatMessage> messages = List.of(
+                        SystemMessage.from("浣犳槸閲囪喘涓氬姟鏂囦欢鍒嗘瀽鍔╂墜銆傝浠庢枃鏈拰鍥剧墖涓瘑鍒噰璐彴璐︺�侀噰璐骇鍝佹槑缁嗐�佷粯娆炬垨閫�璐т俊鎭紝鍙緭鍑哄悎娉� JSON銆�"),
+                        UserMessage.from(contents)
+                );
+                purchaseVisionStreamingChatModel.chat(messages, new StreamingChatResponseHandler() {
+                    @Override
+                    public void onPartialResponse(String partialResponse) {
+                        sink.next(partialResponse);
+                    }
+
+                    @Override
+                    public void onCompleteResponse(ChatResponse completeResponse) {
+                        sink.complete();
+                    }
+
+                    @Override
+                    public void onError(Throwable error) {
+                        sink.error(error);
+                    }
+                });
+            } catch (Exception ex) {
+                sink.next("鍥剧墖鏂囦欢璇诲彇澶辫触锛岃纭鍥剧墖鏍煎紡涓� png銆乯pg銆乯peg銆亀ebp 鎴� bmp锛屼笖澶у皬涓嶈秴杩�10MB");
+                sink.complete();
+            }
+        });
+    }
+
+    private String resolveImageMimeType(MultipartFile file) {
+        String contentType = file.getContentType();
+        if (StringUtils.hasText(contentType) && contentType.startsWith("image/")) {
+            return contentType;
+        }
+        String filename = file.getOriginalFilename();
+        String ext = "";
+        if (StringUtils.hasText(filename) && filename.contains(".")) {
+            ext = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
+        }
+        return switch (ext) {
+            case "jpg", "jpeg" -> "image/jpeg";
+            case "webp" -> "image/webp";
+            case "bmp" -> "image/bmp";
+            default -> "image/png";
+        };
+    }
+
+    private String buildPurchaseFileAnalyzePrompt(String message, String fileContent) {
+        return """
+                浣犳槸閲囪喘涓氬姟鏂囦欢鍒嗘瀽鍔╂墜銆傝涓ユ牸鏍规嵁鐢ㄦ埛涓婁紶鐨勫涓枃浠跺拰鐢ㄦ埛瑕佹眰鎻愬彇閲囪喘涓氬姟鏁版嵁銆�
+
+                鐢ㄦ埛瑕佹眰:
+                %s
+
+                杈撳嚭瑕佹眰:
+                1. 鍙緭鍑哄悎娉� JSON锛屼笉瑕� Markdown锛屼笉瑕侀澶栬В閲娿��
+                2. JSON 椤跺眰瀛楁鍥哄畾涓�:
+                   - success: boolean
+                   - businessType: purchase_ledger | payment_registration | purchase_return_order | unknown
+                   - action: confirm_required
+                   - description: 涓枃璇存槑
+                   - confidence: 0鍒�1鐨勫皬鏁�
+                   - missingFields: 缂哄け瀛楁涓枃鍚嶇О鏁扮粍锛岄潰鍚戝鎴峰睍绀猴紝涓嶈杈撳嚭鑻辨枃瀛楁鍚�
+                   - warnings: 椋庨櫓鎻愮ず鏁扮粍
+                   - payload: 寰呭鎴风‘璁ょ殑鏁版嵁锛屽瓧娈靛悕蹇呴』浣跨敤鍚庣 DTO 瀛楁鍚�
+                   - preview: 缁欏鎴风‘璁ょ敤鐨勪腑鏂囨憳瑕佹暟缁�
+                3. 濡傛灉鍙垽鏂负閲囪喘鍙拌处锛宐usinessType 浣跨敤 purchase_ledger锛宲ayload.purchaseLedgers 涓洪噰璐鍗�/閲囪喘鍙拌处鏁扮粍:
+                   - purchaseLedgers: 閲囪喘璁㈠崟/閲囪喘鍙拌处鏁扮粍锛屾瘡鏉¤褰曞瓧娈靛悕蹇呴』涓� PurchaseLedgerDto 淇濇寔涓�鑷�
+                   - 浜у搧鏄庣粏蹇呴』鏀惧湪姣忔潯閲囪喘鍙拌处璁板綍鐨� productData 瀛楁涓紝productData 绫诲瀷涓� List<SalesLedgerProduct>
+                   - 涓嶈浼樺厛浣跨敤 payload 椤跺眰 productData锛涢《灞� productData 浠呬綔涓烘棫鏍煎紡鍏煎
+                   - 鏂囦欢閲岀殑鈥滈噰璐崟鍙封�濆氨鏄�滈噰璐悎鍚屽彿鈥濓紝缁熶竴鏄犲皠涓� purchaseContractNumber
+                   - 鏂囦欢閲岀殑鈥滈攢鍞崟鍙封�濆氨鏄�滈攢鍞悎鍚屽彿鈥濓紝缁熶竴鏄犲皠涓� salesContractNo
+                   - 鎵�鏈夋棩鏈熷瓧娈靛繀椤讳娇鐢� yyyy-MM-dd锛屼緥濡� 2026-04-30锛涗笉瑕佽緭鍑� 4/30/26銆�2026/4/30銆�2026骞�4鏈�30鏃� 鎴栧甫鏃跺垎绉掔殑鏍煎紡
+                   - 閲囪喘鍙拌处涓嶉渶瑕佸湪 payload 涓紶瀹℃壒浜猴紝涓嶈杈撳嚭 approveUserIds銆乤pproverId
+                   - missingFields 鍙~鍐欎笟鍔″繀濉絾鏃犳硶璇嗗埆鐨勫瓧娈碉紝涓嶈鎶� PurchaseLedgerDto 鐨勬墍鏈夌┖瀛楁閮藉垪涓虹己澶憋紱缂哄け椤瑰繀椤诲啓涓枃锛屼緥濡傗�滀緵搴斿晢鍚嶇О鈥濃�滃惈绋庡崟浠封�濓紝涓嶈鍐� supplierId銆乼axInclusiveUnitPrice
+                   - 閲囪喘鍙拌处涓昏〃蹇呭~瀛楁浠呮寜杩欎簺鍒ゆ柇: purchaseContractNumber銆乻upplierName 鎴� supplierId
+                   - productData 姣忔潯浜у搧蹇呭~瀛楁: productCategory銆乻pecificationModel銆乽nit銆乹uantity銆乼axInclusiveUnitPrice 鎴� taxInclusiveTotalPrice锛涘鏋滃彧鏈夊惈绋庢�讳环鍜屾暟閲忥紝蹇呴』璁$畻 taxInclusiveUnitPrice锛涘鏋滃彧鏈夊惈绋庡崟浠峰拰鏁伴噺锛屽繀椤昏绠� taxInclusiveTotalPrice
+                   - 浜у搧瀛楁鎸夐噰璐鍏ユ帴鍙� PurchaseLedgerProductImportDto 瀵归綈: 閲囪喘鍗曞彿銆佷骇鍝佸ぇ绫汇�佽鏍煎瀷鍙枫�佸崟浣嶃�佹暟閲忋�佺◣鐜囥�佸惈绋庡崟浠枫�佸惈绋庢�讳环銆佸彂绁ㄧ被鍨嬨�佹槸鍚﹁川妫�
+                   - 閲囪喘浜у搧 type 鍥哄畾涓� 2
+                   - purchaseLedgers 姣忔潯璁板綍鍙娇鐢ㄨ繖浜� PurchaseLedgerDto 瀛楁鍚�:
+                     entryDateStart, entryDateEnd, id, purchaseContractNumber, supplierId, supplierName, isWhite, recorderId, recorderName, salesContractNo, salesContractNoId, projectName, entryDate, executionDate, remarks, attachmentMaterials, createdAt, updatedAt, salesLedgerId, hasChildren, Type, productData, tempFileIds, SalesLedgerFiles, phoneNumber, businessPersonId, productId, productModelId, invoiceNumber, invoiceAmount, ticketRegistrationId, contractAmount, receiptPaymentAmount, unReceiptPaymentAmount, type, paymentMethod, approvalStatus, templateName
+                   - productData 姣忔潯浜у搧鍙娇鐢ㄨ繖浜� SalesLedgerProduct 瀛楁鍚�:
+                     productCategory, specificationModel, unit, quantity, taxRate, taxInclusiveUnitPrice, taxInclusiveTotalPrice, taxExclusiveTotalPrice, invoiceType, productId, productModelId, isChecked, type
+                4. 濡傛灉鍙垽鏂负浠樻鐧昏锛宐usinessType 浣跨敤 payment_registration锛宲ayload.records 涓轰粯娆剧櫥璁版暟缁勶紝瀛楁灏介噺鍖呭惈 purchaseLedgerId銆乻alesLedgerProductId銆乧urrentPaymentAmount銆乸aymentMethod銆乸aymentDate銆�
+                5. 濡傛灉鍙垽鏂负閲囪喘閫�璐э紝businessType 浣跨敤 purchase_return_order锛宲ayload 鎸� PurchaseReturnOrderDto 缁勭粐锛屾槑缁嗘斁 purchaseReturnOrderProductsDtos銆�
+                6. 缂哄皯涓氬姟澶勭悊蹇呴』瀛楁鏃讹紝涓嶈缂栭�� ID锛屾妸瀛楁鏀惧叆 missingFields锛屽苟浠嶈繑鍥炲彲纭鐨勮崏绋挎暟鎹��
+                7. 鎵�鏈変腑鏂囧唴瀹圭洿鎺ヤ繚鐣欙紝涓嶈杞箟鎴� Unicode銆�
+
+                鏂囦欢鍐呭:
+                %s
+                """.formatted(message, fileContent);
+    }
+
+    private AjaxResult processPurchaseLedger(Map<String, Object> payload) throws Exception {
+        if (payload.containsKey("purchaseLedgers")) {
+            return processPurchaseLedgerBatch(payload);
+        }
+
+        Map<String, Object> normalizedPayload = normalizePurchaseLedgerMap(payload);
+        PurchaseLedgerDto dto = objectMapper.convertValue(normalizedPayload, PurchaseLedgerDto.class);
+        AjaxResult ledgerResult = validatePurchaseLedger(dto, 0);
+        if (ledgerResult != null) {
+            return ledgerResult;
+        }
+        AjaxResult supplierResult = fillSupplierIdByName(dto);
+        if (supplierResult != null) {
+            return supplierResult;
+        }
+        AjaxResult productResult = validatePurchaseProducts(dto.getProductData(), 0);
+        if (productResult != null) {
+            return productResult;
+        }
+        int result = purchaseLedgerService.addOrEditPurchase(dto);
+        return AjaxResult.success("閲囪喘鍙拌处宸插鐞�", result);
+    }
+
+    private AjaxResult processPurchaseLedgerBatch(Map<String, Object> payload) throws Exception {
+        List<Map<String, Object>> purchaseLedgers = toMapList(payload.get("purchaseLedgers"));
+        if (purchaseLedgers.isEmpty()) {
+            return AjaxResult.error("purchaseLedgers涓嶈兘涓虹┖");
+        }
+
+        List<Map<String, Object>> topLevelProductData = toMapList(payload.get("productData"));
+        List<Map<String, Object>> results = new ArrayList<>();
+        for (int i = 0; i < purchaseLedgers.size(); i++) {
+            Map<String, Object> ledgerMap = normalizePurchaseLedgerMap(purchaseLedgers.get(i));
+            PurchaseLedgerDto dto = objectMapper.convertValue(ledgerMap, PurchaseLedgerDto.class);
+            AjaxResult ledgerResult = validatePurchaseLedger(dto, i);
+            if (ledgerResult != null) {
+                return ledgerResult;
+            }
+            AjaxResult supplierResult = fillSupplierIdByName(dto);
+            if (supplierResult != null) {
+                return supplierResult;
+            }
+
+            List<SalesLedgerProduct> products = dto.getProductData();
+            if (products == null || products.isEmpty()) {
+                products = matchProductsForLedger(ledgerMap, dto, topLevelProductData, purchaseLedgers.size() == 1);
+                dto.setProductData(products);
+            }
+            AjaxResult productResult = validatePurchaseProducts(products, i);
+            if (productResult != null) {
+                return productResult;
+            }
+            int result = purchaseLedgerService.addOrEditPurchase(dto);
+
+            Map<String, Object> item = new LinkedHashMap<>();
+            item.put("index", i);
+            item.put("purchaseContractNumber", dto.getPurchaseContractNumber());
+            item.put("supplierId", dto.getSupplierId());
+            item.put("supplierName", dto.getSupplierName());
+            item.put("productCount", products.size());
+            item.put("result", result);
+            results.add(item);
+        }
+        return AjaxResult.success("閲囪喘鍙拌处宸叉壒閲忓鐞�", results);
+    }
+
+    private List<SalesLedgerProduct> matchProductsForLedger(Map<String, Object> ledgerMap,
+                                                            PurchaseLedgerDto dto,
+                                                            List<Map<String, Object>> productData,
+                                                            boolean onlyOneLedger) {
+        List<SalesLedgerProduct> products = new ArrayList<>();
+        for (Map<String, Object> productMap : productData) {
+            if (onlyOneLedger || productBelongsToLedger(productMap, ledgerMap, dto)) {
+                products.add(objectMapper.convertValue(normalizeSalesLedgerProductMap(productMap), SalesLedgerProduct.class));
+            }
+        }
+        return products;
+    }
+
+    private boolean productBelongsToLedger(Map<String, Object> productMap, Map<String, Object> ledgerMap, PurchaseLedgerDto dto) {
+        Long productPurchaseLedgerId = longValue(productMap, "purchaseLedgerId", "purchaseId", "閲囪喘璁㈠崟id", "閲囪喘鍙拌处id");
+        if (productPurchaseLedgerId != null && dto.getId() != null && productPurchaseLedgerId.equals(dto.getId())) {
+            return true;
+        }
+
+        Long productSalesLedgerId = longValue(productMap, "salesLedgerId");
+        if (productSalesLedgerId != null && dto.getId() != null && productSalesLedgerId.equals(dto.getId())) {
+            return true;
+        }
+
+        String productContractNo = stringValue(productMap, "purchaseContractNumber", "purchaseContractNo", "閲囪喘鍚堝悓鍙�", "閲囪喘鍗曞彿", "閲囪喘璁㈠崟鍙�");
+        if (StringUtils.hasText(productContractNo)
+                && StringUtils.hasText(dto.getPurchaseContractNumber())
+                && productContractNo.trim().equals(dto.getPurchaseContractNumber().trim())) {
+            return true;
+        }
+
+        String ledgerContractNo = stringValue(ledgerMap, "purchaseContractNumber", "purchaseContractNo", "閲囪喘鍚堝悓鍙�", "閲囪喘鍗曞彿", "閲囪喘璁㈠崟鍙�");
+        if (StringUtils.hasText(productContractNo)
+                && StringUtils.hasText(ledgerContractNo)
+                && productContractNo.trim().equals(ledgerContractNo.trim())) {
+            return true;
+        }
+
+        String productSalesContractNo = stringValue(productMap, "salesContractNo", "salesContractNumber", "閿�鍞悎鍚屽彿", "閿�鍞崟鍙�", "閿�鍞鍗曞彿");
+        if (StringUtils.hasText(productSalesContractNo)
+                && StringUtils.hasText(dto.getSalesContractNo())
+                && productSalesContractNo.trim().equals(dto.getSalesContractNo().trim())) {
+            return true;
+        }
+
+        String ledgerSalesContractNo = stringValue(ledgerMap, "salesContractNo", "salesContractNumber", "閿�鍞悎鍚屽彿", "閿�鍞崟鍙�", "閿�鍞鍗曞彿");
+        if (StringUtils.hasText(productSalesContractNo)
+                && StringUtils.hasText(ledgerSalesContractNo)
+                && productSalesContractNo.trim().equals(ledgerSalesContractNo.trim())) {
+            return true;
+        }
+
+        String productSupplierName = stringValue(productMap, "supplierName", "渚涘簲鍟嗗悕绉�");
+        return StringUtils.hasText(productSupplierName)
+                && StringUtils.hasText(dto.getSupplierName())
+                && productSupplierName.trim().equals(dto.getSupplierName().trim());
+    }
+
+    private Map<String, Object> normalizePurchaseLedgerMap(Map<String, Object> source) {
+        Map<String, Object> target = new LinkedHashMap<>();
+        copyPurchaseLedgerDtoFields(source, target);
+        putDtoFieldIfPresent(source, target, "entryDateStart", "褰曞叆寮�濮嬫棩鏈�", "褰曞叆鏃ユ湡寮�濮�");
+        putDtoFieldIfPresent(source, target, "entryDateEnd", "褰曞叆缁撴潫鏃ユ湡", "褰曞叆鏃ユ湡缁撴潫");
+        putDtoFieldIfPresent(source, target, "id", "閲囪喘鍙拌处id", "閲囪喘璁㈠崟id", "涓婚敭");
+        putDtoFieldIfPresent(source, target, "purchaseContractNumber", "purchaseContractNo", "閲囪喘鍚堝悓鍙�", "閲囪喘鍗曞彿", "閲囪喘璁㈠崟鍙�");
+        putDtoFieldIfPresent(source, target, "supplierId", "渚涘簲鍟唅d", "渚涘簲鍟咺D", "渚涘簲鍟嗗悕绉癷d", "渚涘簲鍟嗗悕绉癐D");
+        putDtoFieldIfPresent(source, target, "supplierName", "渚涘簲鍟�", "渚涘簲鍟嗗悕绉�");
+        putDtoFieldIfPresent(source, target, "isWhite", "鏄惁鐧藉悕鍗�");
+        putDtoFieldIfPresent(source, target, "recorderId", "褰曞叆浜篿d", "褰曞叆浜篒D", "褰曞叆浜哄鍚峣d", "褰曞叆浜哄鍚岻D");
+        putDtoFieldIfPresent(source, target, "recorderName", "褰曞叆浜�", "褰曞叆浜哄鍚�");
+        putDtoFieldIfPresent(source, target, "salesContractNo", "salesContractNumber", "閿�鍞悎鍚屽彿", "閿�鍞崟鍙�", "閿�鍞鍗曞彿");
+        putDtoFieldIfPresent(source, target, "salesContractNoId", "閿�鍞悎鍚屽彿id", "閿�鍞悎鍚屽彿ID", "閿�鍞崟鍙穒d", "閿�鍞崟鍙稩D");
+        putDtoFieldIfPresent(source, target, "projectName", "椤圭洰", "椤圭洰鍚嶇О");
+        putDtoFieldIfPresent(source, target, "entryDate", "褰曞叆鏃ユ湡");
+        putDtoFieldIfPresent(source, target, "executionDate", "绛捐鏃ユ湡", "鍚堝悓绛捐鏃ユ湡");
+        putDtoFieldIfPresent(source, target, "remarks", "澶囨敞", "璇存槑");
+        putDtoFieldIfPresent(source, target, "attachmentMaterials", "闄勪欢鏉愭枡", "闄勪欢鏉愭枡璺緞鎴栧悕绉�");
+        putDtoFieldIfPresent(source, target, "createdAt", "鍒涘缓鏃堕棿", "璁板綍鍒涘缓鏃堕棿");
+        putDtoFieldIfPresent(source, target, "updatedAt", "鏇存柊鏃堕棿", "璁板綍鏈�鍚庢洿鏂版椂闂�");
+        putDtoFieldIfPresent(source, target, "salesLedgerId", "閿�鍞彴璐d", "閿�鍞彴璐D", "鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�");
+        putDtoFieldIfPresent(source, target, "hasChildren", "鏄惁鏈夊瓙绾�", "鏄惁鏈夋槑缁�");
+        putDtoFieldIfPresent(source, target, "Type", "鍙拌处绫诲瀷", "涓氬姟绫诲瀷");
+        putDtoFieldIfPresent(source, target, "productData", "products", "浜у搧鏄庣粏", "閲囪喘浜у搧鏄庣粏");
+        putDtoFieldIfPresent(source, target, "tempFileIds", "涓存椂鏂囦欢id", "涓存椂鏂囦欢ID", "涓存椂鏂囦欢ids");
+        putDtoFieldIfPresent(source, target, "SalesLedgerFiles", "闄勪欢鍒楄〃", "閿�鍞彴璐﹂檮浠�");
+        putDtoFieldIfPresent(source, target, "phoneNumber", "涓氬姟鍛樻墜鏈哄彿", "鎵嬫満鍙�");
+        putDtoFieldIfPresent(source, target, "businessPersonId", "涓氬姟鍛榠d", "涓氬姟鍛業D");
+        putDtoFieldIfPresent(source, target, "productId", "浜у搧id", "浜у搧ID");
+        putDtoFieldIfPresent(source, target, "productModelId", "浜у搧瑙勬牸id", "浜у搧瑙勬牸ID");
+        putDtoFieldIfPresent(source, target, "invoiceNumber", "鍙戠エ鍙�", "鍙戠エ鍙风爜");
+        putDtoFieldIfPresent(source, target, "invoiceAmount", "鍙戠エ閲戦", "鍙戠エ閲戦锛堝厓锛�");
+        putDtoFieldIfPresent(source, target, "ticketRegistrationId", "鏉ョエ鐧昏id", "鏉ョエ鐧昏ID");
+        putDtoFieldIfPresent(source, target, "contractAmount", "鍚堝悓閲戦", "鍚堝悓閲戦锛堜骇鍝佸惈绋庢�讳环锛�");
+        putDtoFieldIfPresent(source, target, "receiptPaymentAmount", "鏉ョエ閲戦", "宸叉潵绁ㄩ噾棰�", "宸叉潵绁ㄩ噾棰�(鍏�)");
+        putDtoFieldIfPresent(source, target, "unReceiptPaymentAmount", "鏈潵绁ㄩ噾棰�", "鏈潵绁ㄩ噾棰�(鍏�)");
+        putDtoFieldIfPresent(source, target, "type", "鏂囦欢绫诲瀷");
+        putDtoFieldIfPresent(source, target, "paymentMethod", "浠樻鏂瑰紡");
+        putDtoFieldIfPresent(source, target, "approvalStatus", "瀹℃壒鐘舵��");
+        putDtoFieldIfPresent(source, target, "templateName", "妯℃澘鍚嶇О");
+        target.remove("approveUserIds");
+        target.remove("approverId");
+        normalizeNestedProductData(target);
+        attachImportStyleProductData(source, target);
+        if (target.get("type") == null) {
+            target.put("type", 2);
+        }
+        target.putIfAbsent("entryDate", LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE));
+        normalizePurchaseLedgerDateFields(target);
+        return target;
+    }
+
+    private void attachImportStyleProductData(Map<String, Object> source, Map<String, Object> target) {
+        if (target.get("productData") != null) {
+            return;
+        }
+        Map<String, Object> productMap = normalizeSalesLedgerProductMap(source);
+        if (hasImportStyleProductData(productMap)) {
+            target.put("productData", List.of(productMap));
+        }
+    }
+
+    private boolean hasImportStyleProductData(Map<String, Object> productMap) {
+        return hasMapText(productMap, "productCategory")
+                || hasMapText(productMap, "specificationModel")
+                || productMap.get("quantity") != null
+                || productMap.get("taxInclusiveUnitPrice") != null
+                || productMap.get("taxInclusiveTotalPrice") != null;
+    }
+
+    private boolean hasMapText(Map<String, Object> map, String key) {
+        Object value = map.get(key);
+        return value != null && StringUtils.hasText(String.valueOf(value));
+    }
+
+    private void normalizeNestedProductData(Map<String, Object> target) {
+        Object productDataValue = target.get("productData");
+        if (productDataValue == null) {
+            return;
+        }
+        List<Map<String, Object>> productMaps = toMapList(productDataValue);
+        List<Map<String, Object>> normalizedProducts = new ArrayList<>();
+        for (Map<String, Object> productMap : productMaps) {
+            normalizedProducts.add(normalizeSalesLedgerProductMap(productMap));
+        }
+        target.put("productData", normalizedProducts);
+    }
+
+    private Map<String, Object> normalizeSalesLedgerProductMap(Map<String, Object> source) {
+        Map<String, Object> target = new LinkedHashMap<>();
+        copySalesLedgerProductFields(source, target);
+        putDtoFieldIfPresent(source, target, "productCategory", "浜у搧澶х被", "浜у搧鍚嶇О", "浜у搧", "鍝佸悕", "鐗╂枡鍚嶇О");
+        putDtoFieldIfPresent(source, target, "specificationModel", "瑙勬牸鍨嬪彿", "鍨嬪彿", "瑙勬牸", "浜у搧瑙勬牸");
+        putDtoFieldIfPresent(source, target, "unit", "鍗曚綅");
+        putDtoFieldIfPresent(source, target, "quantity", "鏁伴噺", "閲囪喘鏁伴噺");
+        putDtoFieldIfPresent(source, target, "taxRate", "绋庣巼");
+        putDtoFieldIfPresent(source, target, "taxInclusiveUnitPrice", "鍚◣鍗曚环", "鍗曚环", "閲囪喘鍗曚环", "鍚◣浠锋牸");
+        putDtoFieldIfPresent(source, target, "taxInclusiveTotalPrice", "鍚◣鎬讳环", "鎬讳环", "閲囪喘閲戦", "閲戦", "鍚堝悓閲戦");
+        putDtoFieldIfPresent(source, target, "taxExclusiveTotalPrice", "涓嶅惈绋庢�讳环");
+        putDtoFieldIfPresent(source, target, "invoiceType", "鍙戠エ绫诲瀷", "鍙戠エ绫诲埆");
+        putDtoFieldIfPresent(source, target, "productId", "浜у搧id", "浜у搧ID");
+        putDtoFieldIfPresent(source, target, "productModelId", "浜у搧瑙勬牸id", "浜у搧瑙勬牸ID", "鍨嬪彿id", "鍨嬪彿ID");
+        putDtoFieldIfPresent(source, target, "isChecked", "鏄惁璐ㄦ", "鏄惁璐ㄦ楠�", "璐ㄦ");
+        putDtoFieldIfPresent(source, target, "type", "鍙拌处绫诲瀷");
+        normalizeProductAmounts(target);
+        target.putIfAbsent("type", 2);
+        return target;
+    }
+
+    private void copySalesLedgerProductFields(Map<String, Object> source, Map<String, Object> target) {
+        String[] productFields = {
+                "id", "salesLedgerId", "warnNum", "productCategory", "specificationModel", "unit",
+                "speculativeTradingName", "quantity", "minStock", "taxRate", "taxInclusiveUnitPrice",
+                "taxInclusiveTotalPrice", "taxExclusiveTotalPrice", "invoiceType", "type", "ticketsNum",
+                "ticketsAmount", "futureTickets", "futureTicketsAmount", "invoiceNum", "noInvoiceNum",
+                "invoiceAmount", "noInvoiceAmount", "productId", "productModelId", "register", "registerDate",
+                "approveStatus", "pendingInvoiceTotal", "invoiceTotal", "pendingTicketsTotal", "ticketsTotal",
+                "isChecked", "isProduction"
+        };
+        for (String field : productFields) {
+            if (source.containsKey(field)) {
+                target.put(field, source.get(field));
+            }
+        }
+    }
+
+    private void normalizeProductAmounts(Map<String, Object> target) {
+        BigDecimal quantity = decimalValue(target.get("quantity"));
+        BigDecimal unitPrice = decimalValue(target.get("taxInclusiveUnitPrice"));
+        BigDecimal totalPrice = decimalValue(target.get("taxInclusiveTotalPrice"));
+        if (unitPrice == null && totalPrice != null && quantity != null && quantity.compareTo(BigDecimal.ZERO) != 0) {
+            target.put("taxInclusiveUnitPrice", totalPrice.divide(quantity, 6, RoundingMode.HALF_UP));
+        }
+        if (totalPrice == null && unitPrice != null && quantity != null) {
+            target.put("taxInclusiveTotalPrice", unitPrice.multiply(quantity));
+        }
+        BigDecimal taxRate = decimalValue(target.get("taxRate"));
+        totalPrice = decimalValue(target.get("taxInclusiveTotalPrice"));
+        if (target.get("taxExclusiveTotalPrice") == null && totalPrice != null && taxRate != null) {
+            BigDecimal divisor = BigDecimal.ONE.add(taxRate.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP));
+            target.put("taxExclusiveTotalPrice", totalPrice.divide(divisor, 2, RoundingMode.HALF_UP));
+        }
+    }
+
+    private AjaxResult validatePurchaseProducts(List<SalesLedgerProduct> products, int ledgerIndex) {
+        if (products == null || products.isEmpty()) {
+            return null;
+        }
+        for (int i = 0; i < products.size(); i++) {
+            SalesLedgerProduct product = products.get(i);
+            String prefix = "绗�" + (ledgerIndex + 1) + "涓噰璐彴璐︾殑绗�" + (i + 1) + "鏉′骇鍝�";
+            if (!StringUtils.hasText(product.getProductCategory())) {
+                return AjaxResult.error(prefix + "缂哄皯浜у搧鍚嶇О锛岃琛ュ厖鍚庡啀纭");
+            }
+            if (!StringUtils.hasText(product.getSpecificationModel())) {
+                return AjaxResult.error(prefix + "缂哄皯瑙勬牸鍨嬪彿锛岃琛ュ厖鍚庡啀纭");
+            }
+            if (!StringUtils.hasText(product.getUnit())) {
+                return AjaxResult.error(prefix + "缂哄皯鍗曚綅锛岃琛ュ厖鍚庡啀纭");
+            }
+            if (product.getQuantity() == null) {
+                return AjaxResult.error(prefix + "缂哄皯鏁伴噺");
+            }
+            if (product.getTaxInclusiveUnitPrice() == null) {
+                return AjaxResult.error(prefix + "缂哄皯鍚◣鍗曚环锛岃琛ュ厖鍚庡啀纭");
+            }
+            if (product.getTaxInclusiveTotalPrice() == null) {
+                return AjaxResult.error(prefix + "缂哄皯鍚◣鎬讳环锛岃琛ュ厖鍚庡啀纭");
+            }
+        }
+        return null;
+    }
+
+    private AjaxResult validatePurchaseLedger(PurchaseLedgerDto dto, int ledgerIndex) {
+        String prefix = "绗�" + (ledgerIndex + 1) + "涓噰璐彴璐�";
+        if (!StringUtils.hasText(dto.getPurchaseContractNumber())) {
+            return AjaxResult.error(prefix + "缂哄皯閲囪喘鍚堝悓鍙凤紝璇疯ˉ鍏呭悗鍐嶇‘璁�");
+        }
+        if (dto.getSupplierId() == null && !StringUtils.hasText(dto.getSupplierName())) {
+            return AjaxResult.error(prefix + "缂哄皯渚涘簲鍟嗗悕绉帮紝璇疯ˉ鍏呭悗鍐嶇‘璁�");
+        }
+        return null;
+    }
+
+    private void normalizePurchaseLedgerDateFields(Map<String, Object> target) {
+        normalizeDateField(target, "entryDate");
+        normalizeDateField(target, "executionDate");
+        normalizeDateField(target, "createdAt");
+        normalizeDateField(target, "updatedAt");
+    }
+
+    private void normalizeDateField(Map<String, Object> target, String fieldName) {
+        Object value = target.get(fieldName);
+        if (value == null) {
+            return;
+        }
+        String normalizedDate = normalizeDateValue(value);
+        if (StringUtils.hasText(normalizedDate)) {
+            target.put(fieldName, normalizedDate);
+        }
+    }
+
+    private String normalizeDateValue(Object value) {
+        if (value instanceof Date date) {
+            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ISO_LOCAL_DATE);
+        }
+        if (value instanceof Number number) {
+            return LocalDate.of(1899, 12, 30)
+                    .plusDays(number.longValue())
+                    .format(DateTimeFormatter.ISO_LOCAL_DATE);
+        }
+
+        String text = String.valueOf(value).trim();
+        if (!StringUtils.hasText(text)) {
+            return null;
+        }
+        if (text.length() >= 10 && text.charAt(4) == '-' && text.charAt(7) == '-') {
+            return text.substring(0, 10);
+        }
+
+        String normalizedText = text.replace("骞�", "-")
+                .replace("鏈�", "-")
+                .replace("鏃�", "")
+                .replace(".", "-")
+                .replace("/", "-")
+                .trim();
+        DateTimeFormatter[] formatters = {
+                DateTimeFormatter.ofPattern("yyyy-M-d"),
+                DateTimeFormatter.ofPattern("M-d-yyyy"),
+                DateTimeFormatter.ofPattern("M-d-yy")
+        };
+        for (DateTimeFormatter formatter : formatters) {
+            try {
+                return LocalDate.parse(normalizedText, formatter).format(DateTimeFormatter.ISO_LOCAL_DATE);
+            } catch (DateTimeParseException ignored) {
+                // Try the next supported input pattern.
+            }
+        }
+        return text;
+    }
+
+    private void copyPurchaseLedgerDtoFields(Map<String, Object> source, Map<String, Object> target) {
+        String[] dtoFields = {
+                "entryDateStart", "entryDateEnd", "id", "purchaseContractNumber",
+                "supplierId", "supplierName", "isWhite", "recorderId", "recorderName", "salesContractNo",
+                "salesContractNoId", "projectName", "entryDate", "executionDate", "remarks", "attachmentMaterials",
+                "createdAt", "updatedAt", "salesLedgerId", "hasChildren", "Type", "productData", "tempFileIds",
+                "SalesLedgerFiles", "phoneNumber", "businessPersonId", "productId", "productModelId", "invoiceNumber",
+                "invoiceAmount", "ticketRegistrationId", "contractAmount", "receiptPaymentAmount",
+                "unReceiptPaymentAmount", "type", "paymentMethod", "approvalStatus", "templateName"
+        };
+        for (String field : dtoFields) {
+            if (source.containsKey(field)) {
+                target.put(field, source.get(field));
+            }
+        }
+    }
+
+    private void putDtoFieldIfPresent(Map<String, Object> source, Map<String, Object> target, String dtoField, String... aliases) {
+        if (target.containsKey(dtoField) && target.get(dtoField) != null) {
+            return;
+        }
+        for (String alias : aliases) {
+            Object value = source.get(alias);
+            if (value != null && StringUtils.hasText(String.valueOf(value))) {
+                target.put(dtoField, value);
+                return;
+            }
+        }
+    }
+
+    private List<Map<String, Object>> toMapList(Object value) {
+        if (value == null) {
+            return List.of();
+        }
+        return objectMapper.convertValue(value, new TypeReference<List<Map<String, Object>>>() {
+        });
+    }
+
+    private String stringValue(Map<String, Object> map, String... keys) {
+        for (String key : keys) {
+            Object value = map.get(key);
+            if (value != null && StringUtils.hasText(String.valueOf(value))) {
+                return String.valueOf(value);
+            }
+        }
+        return null;
+    }
+
+    private Long longValue(Map<String, Object> map, String... keys) {
+        String value = stringValue(map, keys);
+        if (!StringUtils.hasText(value)) {
+            return null;
+        }
+        try {
+            return Long.parseLong(value.trim());
+        } catch (NumberFormatException ignored) {
+            return null;
+        }
+    }
+
+    private BigDecimal decimalValue(Object value) {
+        if (value == null) {
+            return null;
+        }
+        if (value instanceof BigDecimal decimal) {
+            return decimal;
+        }
+        if (value instanceof Number number) {
+            return new BigDecimal(String.valueOf(number));
+        }
+        String text = String.valueOf(value)
+                .replace(",", "")
+                .replace("锛�", "")
+                .replace("鍏�", "")
+                .replace("锟�", "")
+                .trim();
+        if (!StringUtils.hasText(text)) {
+            return null;
+        }
+        try {
+            return new BigDecimal(text);
+        } catch (NumberFormatException ignored) {
+            return null;
+        }
+    }
+
+    private String toCustomerMessage(Exception ex) {
+        String message = ex.getMessage();
+        if (!StringUtils.hasText(message)) {
+            return "澶勭悊澶辫触锛岃妫�鏌ョ‘璁ゆ暟鎹悗閲嶈瘯";
+        }
+        if (message.contains("tax_inclusive_unit_price")) {
+            return "澶勭悊澶辫触锛氫骇鍝佹槑缁嗙己灏戝惈绋庡崟浠凤紝璇疯ˉ鍏呭悗鍐嶇‘璁�";
+        }
+        if (message.contains("tax_inclusive_total_price")) {
+            return "澶勭悊澶辫触锛氫骇鍝佹槑缁嗙己灏戝惈绋庢�讳环锛岃琛ュ厖鍚庡啀纭";
+        }
+        if (message.contains("entryDate")) {
+            return "澶勭悊澶辫触锛氬綍鍏ユ棩鏈熸牸寮忎笉姝g‘锛岃浣跨敤 yyyy-MM-dd锛屼緥濡� 2026-04-30";
+        }
+        if (message.contains("supplier")) {
+            return "澶勭悊澶辫触锛氫緵搴斿晢淇℃伅涓嶅畬鏁达紝璇风‘璁や緵搴斿晢鍚嶇О鎴栦緵搴斿晢ID";
+        }
+        if (message.contains("SQL") || message.contains("java.") || message.contains("Exception")) {
+            return "澶勭悊澶辫触锛氱‘璁ゆ暟鎹笉瀹屾暣鎴栨牸寮忎笉姝g‘锛岃妫�鏌ュ繀濉瓧娈靛悗閲嶈瘯";
+        }
+        return "澶勭悊澶辫触锛�" + message;
+    }
+
+    private AjaxResult fillSupplierIdByName(PurchaseLedgerDto dto) {
+        if (dto.getSupplierId() != null) {
+            return null;
+        }
+        if (!StringUtils.hasText(dto.getSupplierName())) {
+            return AjaxResult.error("渚涘簲鍟咺D涓嶈兘涓虹┖锛涙湭璇嗗埆鍒颁緵搴斿晢鍚嶇О锛屾棤娉曡嚜鍔ㄥ尮閰嶄緵搴斿晢ID");
+        }
+
+        SupplierManage supplier = supplierManageMapper.selectOne(new LambdaQueryWrapper<SupplierManage>()
+                .eq(SupplierManage::getSupplierName, dto.getSupplierName().trim())
+                .last("limit 1"));
+        if (supplier == null) {
+            return AjaxResult.error("鏈壘鍒颁緵搴斿晢锛�" + dto.getSupplierName() + "锛岃鍏堢淮鎶や緵搴斿晢鎴栨墜鍔ㄩ�夋嫨渚涘簲鍟咺D");
+        }
+        dto.setSupplierId(supplier.getId());
+        return null;
+    }
+
+    private AjaxResult processPaymentRegistration(Map<String, Object> payload) {
+        Object recordsValue = payload.get("records");
+        List<PaymentRegistration> records;
+        if (recordsValue == null) {
+            records = Collections.singletonList(objectMapper.convertValue(payload, PaymentRegistration.class));
+        } else {
+            records = objectMapper.convertValue(recordsValue, new TypeReference<List<PaymentRegistration>>() {
+            });
+        }
+        int result = paymentRegistrationService.insertPaymentRegistration(records);
+        return AjaxResult.success("浠樻鐧昏宸插鐞�", result);
+    }
+
+    private AjaxResult processPurchaseReturnOrder(Map<String, Object> payload) {
+        PurchaseReturnOrderDto dto = objectMapper.convertValue(payload, PurchaseReturnOrderDto.class);
+        Boolean result = purchaseReturnOrdersService.add(dto);
+        return AjaxResult.success("閲囪喘閫�璐у崟宸插鐞�", result);
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/controller/XiaozhiController.java b/src/main/java/com/ruoyi/ai/controller/XiaozhiController.java
new file mode 100644
index 0000000..eac43b2
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/controller/XiaozhiController.java
@@ -0,0 +1,162 @@
+package com.ruoyi.ai.controller;
+
+import com.ruoyi.ai.assistant.ApproveTodoAgent;
+import com.ruoyi.ai.assistant.ApproveTodoIntentExecutor;
+import com.ruoyi.ai.assistant.FileAnalyzeAgent;
+import com.ruoyi.ai.bean.ChatForm;
+import com.ruoyi.ai.context.AiSessionUserContext;
+import com.ruoyi.ai.service.AiChatSessionService;
+import com.ruoyi.ai.service.AiFileTextExtractor;
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.data.message.UserMessage;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import reactor.core.publisher.Flux;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.UUID;
+
+@Tag(name = "鍗忓悓鍔炲叕鍔╂墜")
+@RestController
+@RequestMapping("/xiaozhi")
+public class XiaozhiController extends BaseController {
+
+    private static final String FILE_ANALYZE_MEMORY_PREFIX = "file-analyze::";
+
+    private final ApproveTodoAgent approveTodoAgent;
+    private final ApproveTodoIntentExecutor approveTodoIntentExecutor;
+    private final FileAnalyzeAgent fileAnalyzeAgent;
+    private final AiSessionUserContext aiSessionUserContext;
+    private final MongoChatMemoryStore mongoChatMemoryStore;
+    private final AiFileTextExtractor aiFileTextExtractor;
+    private final AiChatSessionService aiChatSessionService;
+
+    public XiaozhiController(ApproveTodoAgent approveTodoAgent,
+                             ApproveTodoIntentExecutor approveTodoIntentExecutor,
+                             FileAnalyzeAgent fileAnalyzeAgent,
+                             AiSessionUserContext aiSessionUserContext,
+                             MongoChatMemoryStore mongoChatMemoryStore,
+                             AiFileTextExtractor aiFileTextExtractor,
+                             AiChatSessionService aiChatSessionService) {
+        this.approveTodoAgent = approveTodoAgent;
+        this.approveTodoIntentExecutor = approveTodoIntentExecutor;
+        this.fileAnalyzeAgent = fileAnalyzeAgent;
+        this.aiSessionUserContext = aiSessionUserContext;
+        this.mongoChatMemoryStore = mongoChatMemoryStore;
+        this.aiFileTextExtractor = aiFileTextExtractor;
+        this.aiChatSessionService = aiChatSessionService;
+    }
+
+    @Operation(summary = "瀵硅瘽")
+    @PostMapping(value = "/chat", produces = "text/stream;charset=utf-8")
+    public Flux<String> chat(@RequestBody ChatForm chatForm) {
+        if (!StringUtils.hasText(chatForm.getMemoryId())) {
+            return Flux.just("memoryId涓嶈兘涓虹┖");
+        }
+        if (!StringUtils.hasText(chatForm.getMessage())) {
+            return Flux.just("message涓嶈兘涓虹┖");
+        }
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        String memoryId = chatForm.getMemoryId();
+        String userMessage = chatForm.getMessage();
+
+        aiSessionUserContext.bind(memoryId, loginUser);
+        aiChatSessionService.touchSession(memoryId, loginUser, userMessage);
+
+        String directResponse = approveTodoIntentExecutor.tryExecute(memoryId, userMessage);
+        if (StringUtils.isNotEmpty(directResponse)) {
+            mongoChatMemoryStore.appendMessages(
+                    memoryId,
+                    List.of(UserMessage.from(userMessage), AiMessage.from(directResponse))
+            );
+            aiChatSessionService.refreshSessionStats(memoryId, loginUser);
+            return Flux.just(directResponse);
+        }
+
+        return approveTodoAgent.chat(memoryId, userMessage)
+                .doOnComplete(() -> aiChatSessionService.refreshSessionStats(memoryId, loginUser))
+                .doOnError(ex -> aiChatSessionService.refreshSessionStats(memoryId, loginUser));
+    }
+
+    @Operation(summary = "涓婁紶鏂囦欢鍒嗘瀽")
+    @PostMapping(value = "/analyze-file", consumes = "multipart/form-data", produces = "text/stream;charset=utf-8")
+    public Flux<String> analyzeFile(@RequestParam("file") MultipartFile file,
+                                    @RequestParam(value = "message", required = false) String message,
+                                    @RequestParam(value = "memoryId", required = false) String memoryId) {
+        String rawMemoryId = StringUtils.hasText(memoryId) ? memoryId : UUID.randomUUID().toString();
+        String finalMemoryId = rawMemoryId.startsWith(FILE_ANALYZE_MEMORY_PREFIX)
+                ? rawMemoryId
+                : FILE_ANALYZE_MEMORY_PREFIX + rawMemoryId;
+
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        aiSessionUserContext.bind(finalMemoryId, loginUser);
+
+        String finalMessage = StringUtils.hasText(message) ? message : "璇峰垎鏋愯繖涓枃浠剁殑鏍稿績鍐呭骞剁粰鍑烘�荤粨";
+        String fileText;
+        try {
+            fileText = aiFileTextExtractor.extractText(file);
+        } catch (IllegalArgumentException ex) {
+            return Flux.just(ex.getMessage());
+        } catch (IOException ex) {
+            return Flux.just("鏂囦欢璇诲彇澶辫触");
+        }
+
+        if (!StringUtils.hasText(fileText)) {
+            return Flux.just("鏈彁鍙栧埌鏈夋晥鏂囦欢鍐呭");
+        }
+
+        String limitedContent = fileText.length() > 12000 ? fileText.substring(0, 12000) : fileText;
+        String userPrompt = "浣犲皢鍒嗘瀽鐢ㄦ埛涓婁紶鐨勬枃浠跺唴瀹广�俓n"
+                + "鏂囦欢鍚�: " + file.getOriginalFilename() + "\n"
+                + "鐢ㄦ埛闂: " + finalMessage + "\n"
+                + "鏂囦欢鍐呭濡備笅:\n"
+                + limitedContent;
+
+        aiChatSessionService.touchSession(finalMemoryId, loginUser, "鏂囦欢鍒嗘瀽: " + finalMessage);
+
+        return Flux.defer(() -> fileAnalyzeAgent.chat(finalMemoryId, userPrompt))
+                .onErrorResume(NoSuchElementException.class, ex -> {
+                    // DashScope 鍦ㄥ巻鍙叉秷鎭吋瀹瑰満鏅笅鍙兘鎶� NoSuchElementException锛屾竻绌哄悗閲嶈瘯涓�娆�
+                    mongoChatMemoryStore.deleteMessages(finalMemoryId);
+                    return fileAnalyzeAgent.chat(finalMemoryId, userPrompt);
+                })
+                .doOnComplete(() -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser))
+                .doOnError(ex -> aiChatSessionService.refreshSessionStats(finalMemoryId, loginUser));
+    }
+
+    @Operation(summary = "浼氳瘽鍒楄〃")
+    @GetMapping("/history/sessions")
+    public AjaxResult listSessions() {
+        return success(aiChatSessionService.listCurrentUserSessions(SecurityUtils.getLoginUser()));
+    }
+
+    @Operation(summary = "浼氳瘽娑堟伅")
+    @GetMapping("/history/messages/{memoryId}")
+    public AjaxResult listMessages(@PathVariable String memoryId) {
+        return success(aiChatSessionService.listCurrentUserMessages(memoryId, SecurityUtils.getLoginUser()));
+    }
+
+    @Operation(summary = "鍒犻櫎浼氳瘽")
+    @DeleteMapping("/history/{memoryId}")
+    public AjaxResult deleteSession(@PathVariable String memoryId) {
+        aiSessionUserContext.remove(memoryId);
+        return toAjax(aiChatSessionService.deleteCurrentUserSession(memoryId, SecurityUtils.getLoginUser()));
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/dto/AiChatMessageDto.java b/src/main/java/com/ruoyi/ai/dto/AiChatMessageDto.java
new file mode 100644
index 0000000..9242b3e
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/dto/AiChatMessageDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.ai.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class AiChatMessageDto {
+
+    private String role;
+
+    private String content;
+}
diff --git a/src/main/java/com/ruoyi/ai/dto/AiChatSessionDto.java b/src/main/java/com/ruoyi/ai/dto/AiChatSessionDto.java
new file mode 100644
index 0000000..f62f3b5
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/dto/AiChatSessionDto.java
@@ -0,0 +1,19 @@
+package com.ruoyi.ai.dto;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class AiChatSessionDto {
+
+    private String memoryId;
+
+    private String title;
+
+    private String lastMessage;
+
+    private Integer messageCount;
+
+    private Date lastChatTime;
+}
diff --git a/src/main/java/com/ruoyi/ai/mapper/AiChatSessionMapper.java b/src/main/java/com/ruoyi/ai/mapper/AiChatSessionMapper.java
new file mode 100644
index 0000000..8983396
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/mapper/AiChatSessionMapper.java
@@ -0,0 +1,7 @@
+package com.ruoyi.ai.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.ai.pojo.AiChatSession;
+
+public interface AiChatSessionMapper extends BaseMapper<AiChatSession> {
+}
diff --git a/src/main/java/com/ruoyi/ai/mongodbBean/ChatMessages.java b/src/main/java/com/ruoyi/ai/mongodbBean/ChatMessages.java
new file mode 100644
index 0000000..0a239d8
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/mongodbBean/ChatMessages.java
@@ -0,0 +1,30 @@
+package com.ruoyi.ai.mongodbBean;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.index.Indexed;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.util.Date;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Document("chat_messages")
+public class ChatMessages {
+
+    @Id
+    private ObjectId id;
+
+    @Indexed(unique = true)
+    private String memoryId;
+
+    private String content;
+
+    private Date createTime;
+
+    private Date updateTime;
+}
diff --git a/src/main/java/com/ruoyi/ai/pojo/AiChatSession.java b/src/main/java/com/ruoyi/ai/pojo/AiChatSession.java
new file mode 100644
index 0000000..cc289f8
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/pojo/AiChatSession.java
@@ -0,0 +1,34 @@
+package com.ruoyi.ai.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@TableName("ai_chat_session")
+public class AiChatSession {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String memoryId;
+
+    private Long userId;
+
+    private Long tenantId;
+
+    private String title;
+
+    private String lastMessage;
+
+    private Integer messageCount;
+
+    private Date lastChatTime;
+
+    private Date createTime;
+
+    private Date updateTime;
+}
diff --git a/src/main/java/com/ruoyi/ai/service/AiChatSessionService.java b/src/main/java/com/ruoyi/ai/service/AiChatSessionService.java
new file mode 100644
index 0000000..ef47e03
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/service/AiChatSessionService.java
@@ -0,0 +1,22 @@
+package com.ruoyi.ai.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.ai.dto.AiChatMessageDto;
+import com.ruoyi.ai.dto.AiChatSessionDto;
+import com.ruoyi.ai.pojo.AiChatSession;
+import com.ruoyi.framework.security.LoginUser;
+
+import java.util.List;
+
+public interface AiChatSessionService extends IService<AiChatSession> {
+
+    void touchSession(String memoryId, LoginUser loginUser, String userMessage);
+
+    void refreshSessionStats(String memoryId, LoginUser loginUser);
+
+    List<AiChatSessionDto> listCurrentUserSessions(LoginUser loginUser);
+
+    List<AiChatMessageDto> listCurrentUserMessages(String memoryId, LoginUser loginUser);
+
+    boolean deleteCurrentUserSession(String memoryId, LoginUser loginUser);
+}
diff --git a/src/main/java/com/ruoyi/ai/service/AiFileTextExtractor.java b/src/main/java/com/ruoyi/ai/service/AiFileTextExtractor.java
new file mode 100644
index 0000000..6e37451
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/service/AiFileTextExtractor.java
@@ -0,0 +1,131 @@
+package com.ruoyi.ai.service;
+
+import com.ruoyi.common.utils.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+@Component
+public class AiFileTextExtractor {
+
+    private static final long MAX_FILE_SIZE = 10L * 1024 * 1024;
+
+    public String extractText(MultipartFile file) throws IOException {
+        if (file == null || file.isEmpty()) {
+            throw new IllegalArgumentException("鏂囦欢涓嶈兘涓虹┖");
+        }
+        if (file.getSize() > MAX_FILE_SIZE) {
+            throw new IllegalArgumentException("鏂囦欢杩囧ぇ锛岃鎺у埗鍦�10MB浠ュ唴");
+        }
+
+        String filename = file.getOriginalFilename();
+        String ext = getExtension(filename);
+        byte[] bytes = file.getBytes();
+
+        if (isPlainText(ext)) {
+            return decodeText(bytes);
+        }
+        if ("docx".equals(ext)) {
+            return extractDocx(bytes);
+        }
+        if ("xlsx".equals(ext)) {
+            return extractXlsx(bytes);
+        }
+        if ("xls".equals(ext)) {
+            return extractXls(bytes);
+        }
+        if (isImage(ext)) {
+            return "鍥剧墖鏂囦欢锛�" + filename + "锛屽凡涓婁紶锛岃缁撳悎鍥剧墖鍐呭璇嗗埆閲囪喘鍗曟嵁銆佽〃鏍煎拰浜у搧鏄庣粏銆�";
+        }
+        throw new IllegalArgumentException("鏆備笉鏀寔璇ユ枃浠剁被鍨�: " + ext);
+    }
+
+    public boolean isImageFile(MultipartFile file) {
+        if (file == null) {
+            return false;
+        }
+        return isImage(getExtension(file.getOriginalFilename()));
+    }
+
+    private String extractDocx(byte[] bytes) throws IOException {
+        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
+             XWPFDocument document = new XWPFDocument(inputStream);
+             XWPFWordExtractor extractor = new XWPFWordExtractor(document)) {
+            return extractor.getText();
+        }
+    }
+
+    private String extractXlsx(byte[] bytes) throws IOException {
+        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
+             XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) {
+            return extractWorkbook(workbook);
+        }
+    }
+
+    private String extractXls(byte[] bytes) throws IOException {
+        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
+             HSSFWorkbook workbook = new HSSFWorkbook(inputStream)) {
+            return extractWorkbook(workbook);
+        }
+    }
+
+    private String extractWorkbook(org.apache.poi.ss.usermodel.Workbook workbook) {
+        StringBuilder text = new StringBuilder();
+        DataFormatter formatter = new DataFormatter();
+        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
+            Sheet sheet = workbook.getSheetAt(i);
+            text.append("Sheet: ").append(sheet.getSheetName()).append("\n");
+            for (Row row : sheet) {
+                short lastCellNum = row.getLastCellNum();
+                if (lastCellNum <= 0) {
+                    text.append("\n");
+                    continue;
+                }
+                for (int c = 0; c < lastCellNum; c++) {
+                    String cellText = formatter.formatCellValue(row.getCell(c));
+                    text.append(cellText);
+                    if (c < lastCellNum - 1) {
+                        text.append('\t');
+                    }
+                }
+                text.append('\n');
+            }
+        }
+        return text.toString();
+    }
+
+    private String decodeText(byte[] bytes) {
+        String utf8 = new String(bytes, StandardCharsets.UTF_8);
+        if (utf8.contains("锟�")) {
+            return new String(bytes, java.nio.charset.Charset.forName("GBK"));
+        }
+        return utf8;
+    }
+
+    private String getExtension(String filename) {
+        if (!StringUtils.hasText(filename) || !filename.contains(".")) {
+            return "";
+        }
+        return filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
+    }
+
+    private boolean isPlainText(String ext) {
+        return StringUtils.inStringIgnoreCase(ext,
+                "txt", "md", "markdown", "json", "xml", "yaml", "yml", "csv", "log", "properties",
+                "java", "js", "ts", "vue", "html", "css", "sql", "py", "go", "sh", "bat");
+    }
+
+    private boolean isImage(String ext) {
+        return StringUtils.inStringIgnoreCase(ext, "png", "jpg", "jpeg", "webp", "bmp");
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/service/impl/AiChatSessionServiceImpl.java b/src/main/java/com/ruoyi/ai/service/impl/AiChatSessionServiceImpl.java
new file mode 100644
index 0000000..6d8c945
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/service/impl/AiChatSessionServiceImpl.java
@@ -0,0 +1,191 @@
+package com.ruoyi.ai.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.ai.dto.AiChatMessageDto;
+import com.ruoyi.ai.dto.AiChatSessionDto;
+import com.ruoyi.ai.mapper.AiChatSessionMapper;
+import com.ruoyi.ai.pojo.AiChatSession;
+import com.ruoyi.ai.service.AiChatSessionService;
+import com.ruoyi.ai.store.MongoChatMemoryStore;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.LoginUser;
+import dev.langchain4j.data.message.AiMessage;
+import dev.langchain4j.data.message.ChatMessage;
+import dev.langchain4j.data.message.SystemMessage;
+import dev.langchain4j.data.message.ToolExecutionResultMessage;
+import dev.langchain4j.data.message.UserMessage;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class AiChatSessionServiceImpl extends ServiceImpl<AiChatSessionMapper, AiChatSession> implements AiChatSessionService {
+
+    private static final int TITLE_MAX_LENGTH = 40;
+    private static final int LAST_MESSAGE_MAX_LENGTH = 300;
+
+    private final MongoChatMemoryStore mongoChatMemoryStore;
+
+    @Override
+    public void touchSession(String memoryId, LoginUser loginUser, String userMessage) {
+        if (!StringUtils.hasText(memoryId) || loginUser == null || loginUser.getUserId() == null) {
+            return;
+        }
+        Date now = new Date();
+        AiChatSession session = getSession(memoryId, loginUser.getUserId(), loginUser.getTenantId());
+        if (session == null) {
+            AiChatSession add = new AiChatSession();
+            add.setMemoryId(memoryId);
+            add.setUserId(loginUser.getUserId());
+            add.setTenantId(loginUser.getTenantId());
+            add.setTitle(buildTitle(userMessage));
+            add.setLastMessage(trimText(userMessage, LAST_MESSAGE_MAX_LENGTH));
+            add.setMessageCount(0);
+            add.setLastChatTime(now);
+            add.setCreateTime(now);
+            add.setUpdateTime(now);
+            save(add);
+            return;
+        }
+
+        AiChatSession update = new AiChatSession();
+        update.setId(session.getId());
+        if (!StringUtils.hasText(session.getTitle())) {
+            update.setTitle(buildTitle(userMessage));
+        }
+        update.setLastMessage(trimText(userMessage, LAST_MESSAGE_MAX_LENGTH));
+        update.setLastChatTime(now);
+        update.setUpdateTime(now);
+        updateById(update);
+    }
+
+    @Override
+    public void refreshSessionStats(String memoryId, LoginUser loginUser) {
+        if (!StringUtils.hasText(memoryId) || loginUser == null || loginUser.getUserId() == null) {
+            return;
+        }
+        AiChatSession session = getSession(memoryId, loginUser.getUserId(), loginUser.getTenantId());
+        if (session == null) {
+            return;
+        }
+        List<ChatMessage> messages = mongoChatMemoryStore.getMessages(memoryId);
+        AiChatSession update = new AiChatSession();
+        update.setId(session.getId());
+        update.setMessageCount(messages.size());
+        update.setLastMessage(trimText(lastMessageText(messages), LAST_MESSAGE_MAX_LENGTH));
+        update.setLastChatTime(new Date());
+        update.setUpdateTime(new Date());
+        updateById(update);
+    }
+
+    @Override
+    public List<AiChatSessionDto> listCurrentUserSessions(LoginUser loginUser) {
+        if (loginUser == null || loginUser.getUserId() == null) {
+            return new LinkedList<>();
+        }
+        LambdaQueryWrapper<AiChatSession> queryWrapper = new LambdaQueryWrapper<AiChatSession>()
+                .eq(AiChatSession::getUserId, loginUser.getUserId())
+                .orderByDesc(AiChatSession::getLastChatTime);
+        applyTenantCondition(queryWrapper, loginUser.getTenantId());
+        return list(queryWrapper).stream().map(item -> {
+            AiChatSessionDto dto = new AiChatSessionDto();
+            dto.setMemoryId(item.getMemoryId());
+            dto.setTitle(item.getTitle());
+            dto.setLastMessage(item.getLastMessage());
+            dto.setMessageCount(item.getMessageCount());
+            dto.setLastChatTime(item.getLastChatTime());
+            return dto;
+        }).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<AiChatMessageDto> listCurrentUserMessages(String memoryId, LoginUser loginUser) {
+        if (!StringUtils.hasText(memoryId) || loginUser == null || loginUser.getUserId() == null) {
+            return new LinkedList<>();
+        }
+        AiChatSession session = getSession(memoryId, loginUser.getUserId(), loginUser.getTenantId());
+        if (session == null) {
+            return new LinkedList<>();
+        }
+        List<ChatMessage> messages = mongoChatMemoryStore.getMessages(memoryId);
+        return messages.stream().map(this::convertMessage).collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean deleteCurrentUserSession(String memoryId, LoginUser loginUser) {
+        if (!StringUtils.hasText(memoryId) || loginUser == null || loginUser.getUserId() == null) {
+            return false;
+        }
+        LambdaQueryWrapper<AiChatSession> queryWrapper = new LambdaQueryWrapper<AiChatSession>()
+                .eq(AiChatSession::getMemoryId, memoryId)
+                .eq(AiChatSession::getUserId, loginUser.getUserId());
+        applyTenantCondition(queryWrapper, loginUser.getTenantId());
+        boolean removed = remove(queryWrapper);
+        mongoChatMemoryStore.deleteMessages(memoryId);
+        return removed;
+    }
+
+    private AiChatSession getSession(String memoryId, Long userId, Long tenantId) {
+        LambdaQueryWrapper<AiChatSession> queryWrapper = new LambdaQueryWrapper<AiChatSession>()
+                .eq(AiChatSession::getMemoryId, memoryId)
+                .eq(AiChatSession::getUserId, userId);
+        applyTenantCondition(queryWrapper, tenantId);
+        return getOne(queryWrapper, false);
+    }
+
+    private void applyTenantCondition(LambdaQueryWrapper<AiChatSession> queryWrapper, Long tenantId) {
+        if (tenantId == null) {
+            queryWrapper.isNull(AiChatSession::getTenantId);
+            return;
+        }
+        queryWrapper.eq(AiChatSession::getTenantId, tenantId);
+    }
+
+    private String buildTitle(String userMessage) {
+        if (!StringUtils.hasText(userMessage)) {
+            return "鏂颁細璇�";
+        }
+        return trimText(userMessage, TITLE_MAX_LENGTH);
+    }
+
+    private String trimText(String text, int maxLength) {
+        if (!StringUtils.hasText(text)) {
+            return "";
+        }
+        String source = text.trim();
+        if (source.length() <= maxLength) {
+            return source;
+        }
+        return source.substring(0, maxLength) + "...";
+    }
+
+    private String lastMessageText(List<ChatMessage> messages) {
+        if (messages == null || messages.isEmpty()) {
+            return "";
+        }
+        ChatMessage lastMessage = messages.get(messages.size() - 1);
+        return convertMessage(lastMessage).getContent();
+    }
+
+    private AiChatMessageDto convertMessage(ChatMessage message) {
+        if (message instanceof UserMessage userMessage) {
+            return new AiChatMessageDto("user", userMessage.singleText());
+        }
+        if (message instanceof AiMessage aiMessage) {
+            return new AiChatMessageDto("assistant", aiMessage.text());
+        }
+        if (message instanceof SystemMessage systemMessage) {
+            return new AiChatMessageDto("system", systemMessage.text());
+        }
+        if (message instanceof ToolExecutionResultMessage toolExecutionResultMessage) {
+            return new AiChatMessageDto("tool", toolExecutionResultMessage.text());
+        }
+        return new AiChatMessageDto("unknown", String.valueOf(message));
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/store/MongoChatMemoryStore.java b/src/main/java/com/ruoyi/ai/store/MongoChatMemoryStore.java
new file mode 100644
index 0000000..e88f0e9
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/store/MongoChatMemoryStore.java
@@ -0,0 +1,62 @@
+package com.ruoyi.ai.store;
+
+import com.ruoyi.ai.mongodbBean.ChatMessages;
+import dev.langchain4j.data.message.ChatMessage;
+import dev.langchain4j.data.message.ChatMessageDeserializer;
+import dev.langchain4j.data.message.ChatMessageSerializer;
+import dev.langchain4j.store.memory.chat.ChatMemoryStore;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+@Component
+@RequiredArgsConstructor
+public class MongoChatMemoryStore implements ChatMemoryStore {
+
+    private final MongoTemplate mongoTemplate;
+
+    @Override
+    public List<ChatMessage> getMessages(Object memoryId) {
+        Query query = Query.query(Criteria.where("memoryId").is(memoryIdString(memoryId)));
+        ChatMessages chatMessages = mongoTemplate.findOne(query, ChatMessages.class);
+        if (chatMessages == null || chatMessages.getContent() == null) {
+            return new LinkedList<>();
+        }
+        return ChatMessageDeserializer.messagesFromJson(chatMessages.getContent());
+    }
+
+    @Override
+    public void updateMessages(Object memoryId, List<ChatMessage> messages) {
+        String memoryIdValue = memoryIdString(memoryId);
+        Query query = Query.query(Criteria.where("memoryId").is(memoryIdValue));
+        Update update = new Update();
+        update.set("memoryId", memoryIdValue);
+        update.set("content", ChatMessageSerializer.messagesToJson(messages));
+        update.set("updateTime", new Date());
+        update.setOnInsert("createTime", new Date());
+        mongoTemplate.upsert(query, update, ChatMessages.class);
+    }
+
+    @Override
+    public void deleteMessages(Object memoryId) {
+        Query query = Query.query(Criteria.where("memoryId").is(memoryIdString(memoryId)));
+        mongoTemplate.remove(query, ChatMessages.class);
+    }
+
+    public void appendMessages(Object memoryId, List<ChatMessage> appendList) {
+        List<ChatMessage> messages = new LinkedList<>(getMessages(memoryId));
+        messages.addAll(appendList);
+        updateMessages(memoryId, messages);
+    }
+
+    private String memoryIdString(Object memoryId) {
+        return memoryId == null ? "" : memoryId.toString();
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/tools/ApproveTodoTools.java b/src/main/java/com/ruoyi/ai/tools/ApproveTodoTools.java
new file mode 100644
index 0000000..cd3e933
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/tools/ApproveTodoTools.java
@@ -0,0 +1,996 @@
+package com.ruoyi.ai.tools;
+
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.ai.context.AiSessionUserContext;
+import com.ruoyi.approve.mapper.ApproveLogMapper;
+import com.ruoyi.approve.mapper.ApproveNodeMapper;
+import com.ruoyi.approve.mapper.ApproveProcessMapper;
+import com.ruoyi.approve.pojo.ApproveLog;
+import com.ruoyi.approve.pojo.ApproveNode;
+import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.approve.service.IApproveNodeService;
+import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
+import dev.langchain4j.agent.tool.P;
+import dev.langchain4j.agent.tool.Tool;
+import dev.langchain4j.agent.tool.ToolMemoryId;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.YearMonth;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+import java.util.regex.Matcher;
+import java.util.stream.Collectors;
+
+@Component
+public class ApproveTodoTools {
+
+    private static final int DEFAULT_LIMIT = 10;
+    private static final int MAX_LIMIT = 20;
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    private final ApproveProcessMapper approveProcessMapper;
+    private final ApproveNodeMapper approveNodeMapper;
+    private final ApproveLogMapper approveLogMapper;
+    private final IApproveNodeService approveNodeService;
+    private final ApproveProcessServiceImpl approveProcessService;
+    private final AiSessionUserContext aiSessionUserContext;
+
+    public ApproveTodoTools(ApproveProcessMapper approveProcessMapper,
+                            ApproveNodeMapper approveNodeMapper,
+                            ApproveLogMapper approveLogMapper,
+                            IApproveNodeService approveNodeService,
+                            ApproveProcessServiceImpl approveProcessService,
+                            AiSessionUserContext aiSessionUserContext) {
+        this.approveProcessMapper = approveProcessMapper;
+        this.approveNodeMapper = approveNodeMapper;
+        this.approveLogMapper = approveLogMapper;
+        this.approveNodeService = approveNodeService;
+        this.approveProcessService = approveProcessService;
+        this.aiSessionUserContext = aiSessionUserContext;
+    }
+
+    @Tool(name = "鏌ヨ瀹℃壒寰呭姙鍒楄〃", value = "鏌ヨ褰撳墠鐧诲綍浜虹浉鍏崇殑瀹℃壒寰呭姙锛屼紭鍏堣繑鍥炶嚜宸卞緟澶勭悊鐨勫鎵癸紝鏀寔鎸夌姸鎬併�佺被鍨嬨�佸叧閿瓧鍜岃寖鍥磋繃婊ゃ��")
+    public String listTodos(@ToolMemoryId String memoryId,
+                            @P(value = "瀹℃壒鐘舵�侊紝鍙�夊�硷細all銆乸ending銆乸rocessing銆乤pproved銆乺ejected銆乺esubmitted", required = false) String status,
+                            @P(value = "瀹℃壒绫诲瀷缂栧彿锛屽彲涓嶄紶", required = false) Integer approveType,
+                            @P(value = "鍏抽敭瀛楋紝鍙尮閰嶆祦绋嬬紪鍙枫�佹爣棰樸�佺敵璇蜂汉銆佸綋鍓嶅鎵逛汉", required = false) String keyword,
+                            @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�20", required = false) Integer limit,
+                            @P(value = "鏌ヨ鑼冨洿锛屽彲閫夊�硷細related銆乤pplicant銆乤pprover锛況elated 琛ㄧず褰撳墠鐢ㄦ埛鐩稿叧锛宎pplicant 琛ㄧず鎴戝彂璧风殑锛宎pprover 琛ㄧず寰呮垜澶勭悊鐨�", required = false) String scope) {
+
+        LoginUser loginUser = currentLoginUser(memoryId);
+        Long userId = loginUser.getUserId();
+        Integer statusCode = parseStatus(status);
+        String normalizedScope = normalizeScope(scope);
+
+        LambdaQueryWrapper<ApproveProcess> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(ApproveProcess::getApproveDelete, 0);
+        if (statusCode == null) {
+            wrapper.ne(ApproveProcess::getApproveStatus, 2);
+        }
+
+        if (approveType != null) {
+            wrapper.eq(ApproveProcess::getApproveType, approveType);
+        }
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like(ApproveProcess::getApproveId, keyword)
+                    .or().like(ApproveProcess::getApproveReason, keyword)
+                    .or().like(ApproveProcess::getApproveUserName, keyword)
+                    .or().like(ApproveProcess::getApproveUserCurrentName, keyword));
+        }
+        if ("applicant".equals(normalizedScope)) {
+            wrapper.eq(ApproveProcess::getApproveUser, userId);
+            if (statusCode != null) {
+                wrapper.eq(ApproveProcess::getApproveStatus, statusCode);
+            }
+        } else if ("approver".equals(normalizedScope)) {
+            wrapper.eq(ApproveProcess::getApproveUserCurrentId, userId);
+            if (statusCode != null) {
+                wrapper.eq(ApproveProcess::getApproveStatus, statusCode);
+            }
+        } else if (statusCode != null && (statusCode == 0 || statusCode == 1)) {
+            wrapper.eq(ApproveProcess::getApproveUserCurrentId, userId);
+            wrapper.eq(ApproveProcess::getApproveStatus, statusCode);
+        } else {
+            wrapper.and(w -> w.eq(ApproveProcess::getApproveUser, userId)
+                    .or().eq(ApproveProcess::getApproveUserCurrentId, userId)
+                    .or().apply("FIND_IN_SET({0}, approve_user_ids)", userId));
+            if (statusCode != null) {
+                wrapper.eq(ApproveProcess::getApproveStatus, statusCode);
+            }
+        }
+
+        wrapper.orderByDesc(ApproveProcess::getCreateTime)
+                .last("limit " + normalizeLimit(limit));
+
+        List<ApproveProcess> processes = defaultList(approveProcessMapper.selectList(wrapper));
+        if (processes.isEmpty()) {
+            return jsonResponse(true, "todo_list", "鏈煡璇㈠埌褰撳墠鐢ㄦ埛绗﹀悎鏉′欢鐨勫鎵瑰緟鍔炪��",
+                    Map.of("count", 0),
+                    Map.of("columns", todoColumns(), "items", List.of()),
+                    Map.of());
+        }
+
+        List<Map<String, Object>> items = processes.stream()
+                .filter(process -> canView(process, userId))
+                .sorted(Comparator
+                        .comparing((ApproveProcess process) -> !Objects.equals(process.getApproveUserCurrentId(), userId))
+                        .thenComparing(ApproveProcess::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder())))
+                .map(process -> {
+                    Map<String, Object> item = new LinkedHashMap<>();
+                    item.put("approveId", process.getApproveId());
+                    item.put("approveType", approveTypeName(process.getApproveType()));
+                    item.put("approveUserName", safe(process.getApproveUserName()));
+                    item.put("approveUserCurrentName", safe(process.getApproveUserCurrentName()));
+                    item.put("approveReason", safe(process.getApproveReason()));
+                    item.put("approveStatus", approveStatusName(process.getApproveStatus()));
+                    item.put("createTime", formatDateTime(process.getCreateTime()));
+                    item.put("relation", relationName(process, userId));
+                    return item;
+                })
+                .collect(Collectors.toList());
+
+        return jsonResponse(true, "todo_list", "宸茶繑鍥炲綋鍓嶇敤鎴风浉鍏冲鎵瑰垪琛ㄣ��",
+                Map.of(
+                        "count", items.size(),
+                        "statusFilter", StringUtils.hasText(status) ? status : "all",
+                        "approveType", approveType == null ? "" : approveType,
+                        "keyword", keyword == null ? "" : keyword,
+                        "scope", normalizedScope
+                ),
+                Map.of("columns", todoColumns(), "items", items),
+                Map.of());
+    }
+
+    @Tool(name = "鏌ヨ瀹℃壒寰呭姙璇︽儏", value = "鏍规嵁娴佺▼缂栧彿鏌ヨ褰撳墠鐧诲綍浜哄彲瑙佺殑瀹℃壒璇︽儏銆�")
+    public String getTodoDetail(@ToolMemoryId String memoryId,
+                                @P("娴佺▼缂栧彿 approveId") String approveId) {
+        ApproveProcess process = getAccessibleProcess(memoryId, approveId);
+        if (process == null) {
+            return "鏈壘鍒板搴斿鎵癸紝鎴栧綋鍓嶇敤鎴锋棤鏉冩煡鐪嬭娴佺▼銆�";
+        }
+
+        StringJoiner detail = new StringJoiner("\n");
+        detail.add("瀹℃壒璇︽儏");
+        detail.add("娴佺▼缂栧彿: " + safe(process.getApproveId()));
+        detail.add("瀹℃壒绫诲瀷: " + approveTypeName(process.getApproveType()));
+        detail.add("鐢宠浜�: " + safe(process.getApproveUserName()));
+        detail.add("鐢宠閮ㄩ棬: " + safe(process.getApproveDeptName()));
+        detail.add("褰撳墠瀹℃壒浜�: " + safe(process.getApproveUserCurrentName()));
+        detail.add("鏍囬: " + safe(process.getApproveReason()));
+        detail.add("鐘舵��: " + approveStatusName(process.getApproveStatus()));
+        detail.add("鐢宠鏃ユ湡: " + formatDate(process.getApproveTime()));
+        detail.add("寮�濮嬫棩鏈�: " + formatDate(process.getStartDate()));
+        detail.add("缁撴潫鏃ユ湡: " + formatDate(process.getEndDate()));
+        detail.add("鍦扮偣: " + safe(process.getLocation()));
+        detail.add("閲戦: " + (process.getPrice() == null ? "" : process.getPrice().toPlainString()));
+        detail.add("澶囨敞: " + safe(process.getApproveRemark()));
+        detail.add("鍒涘缓鏃堕棿: " + formatDateTime(process.getCreateTime()));
+        detail.add("涓庡綋鍓嶇敤鎴峰叧绯�: " + relationName(process, currentUserId(memoryId)));
+        return detail.toString();
+    }
+
+    @Tool(name = "鏌ヨ瀹℃壒娴佽浆璁板綍", value = "鏍规嵁娴佺▼缂栧彿鏌ヨ瀹℃壒鑺傜偣鍜屽鎵规棩蹇楋紝鐢ㄤ簬鍥炵瓟杩涘害銆佸綋鍓嶅崱鐐瑰拰鍘嗗彶澶勭悊璁板綍銆�")
+    public String getTodoProgress(@ToolMemoryId String memoryId,
+                                  @P("娴佺▼缂栧彿 approveId") String approveId) {
+        ApproveProcess process = getAccessibleProcess(memoryId, approveId);
+        if (process == null) {
+            return jsonResponse(false, "todo_progress", "鏈壘鍒板搴斿鎵癸紝鎴栧綋鍓嶇敤鎴锋棤鏉冩煡鐪嬭娴佺▼銆�",
+                    Map.of("approveId", safe(approveId)),
+                    Map.of(),
+                    Map.of());
+        }
+
+        List<ApproveNode> nodes = listNodes(process);
+        List<ApproveLog> logs = listLogs(process.getId());
+        ApproveNode currentNode = findCurrentNode(nodes);
+
+        List<Map<String, Object>> nodeItems = nodes.stream().map(node -> {
+            Map<String, Object> item = new LinkedHashMap<>();
+            item.put("approveNodeOrder", node.getApproveNodeOrder());
+            item.put("approveNodeUser", safe(node.getApproveNodeUser()));
+            item.put("approveNodeUserId", node.getApproveNodeUserId());
+            item.put("approveNodeStatus", approveNodeStatusName(node.getApproveNodeStatus()));
+            item.put("approveNodeTime", formatDate(node.getApproveNodeTime()));
+            item.put("approveNodeReason", safe(node.getApproveNodeReason()));
+            item.put("approveNodeRemark", safe(node.getApproveNodeRemark()));
+            item.put("isCurrent", currentNode != null && Objects.equals(currentNode.getId(), node.getId()));
+            return item;
+        }).collect(Collectors.toList());
+
+        List<Map<String, Object>> logItems = logs.stream().map(log -> {
+            Map<String, Object> item = new LinkedHashMap<>();
+            item.put("approveNodeOrder", log.getApproveNodeOrder());
+            item.put("approveUser", log.getApproveUser());
+            item.put("approveStatus", approveStatusName(log.getApproveStatus()));
+            item.put("approveTime", formatDate(log.getApproveTime()));
+            item.put("approveRemark", safe(log.getApproveRemark()));
+            return item;
+        }).collect(Collectors.toList());
+
+        return jsonResponse(true, "todo_progress", "宸茶繑鍥炲鎵规祦杞褰曘��",
+                Map.of(
+                        "approveId", safe(process.getApproveId()),
+                        "currentStatus", approveStatusName(process.getApproveStatus()),
+                        "currentApprover", safe(process.getApproveUserCurrentName()),
+                        "currentNodeOrder", currentNode == null ? "" : currentNode.getApproveNodeOrder(),
+                        "nodeCount", nodeItems.size(),
+                        "logCount", logItems.size()
+                ),
+                Map.of("nodes", nodeItems, "logs", logItems),
+                Map.of());
+    }
+
+    @Tool(name = "缁熻瀹℃壒寰呭姙鏁版嵁", value = "鎸夌敤鎴锋寚瀹氱殑鏃堕棿鑼冨洿缁熻褰撳墠鐧诲綍浜虹浉鍏冲鎵圭殑鐘舵�佸垎甯冦�佺被鍨嬪垎甯冨拰瓒嬪娍锛涙湭鎸囧畾鏃堕粯璁よ繎7澶┿��")
+    public String getTodoStats(@ToolMemoryId String memoryId,
+                               @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd锛屽彲涓嶄紶", required = false) String startDate,
+                               @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd锛屽彲涓嶄紶", required = false) String endDate,
+                               @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屼緥濡� 浠婂ぉ銆佹湰鏈堛�佽繎30澶┿��2026-04-01鍒�2026-04-27", required = false) String timeRange) {
+        Long userId = currentUserId(memoryId);
+        List<ApproveProcess> processes = defaultList(approveProcessMapper.selectList(new LambdaQueryWrapper<ApproveProcess>()
+                .eq(ApproveProcess::getApproveDelete, 0)
+                .and(w -> w.eq(ApproveProcess::getApproveUser, userId)
+                        .or().eq(ApproveProcess::getApproveUserCurrentId, userId)
+                        .or().apply("FIND_IN_SET({0}, approve_user_ids)", userId))));
+
+        DateRange dateRange = resolveDateRange(startDate, endDate, timeRange);
+        List<ApproveProcess> filteredProcesses = processes.stream()
+                .filter(process -> withinDateRange(process.getCreateTime(), dateRange))
+                .collect(Collectors.toList());
+
+        if (filteredProcesses.isEmpty()) {
+            return jsonResponse(true, "todo_stats", "褰撳墠鐢ㄦ埛娌℃湁鐩稿叧瀹℃壒鏁版嵁銆�",
+                    Map.of(
+                            "total", 0,
+                            "startDate", dateRange.start().toString(),
+                            "endDate", dateRange.end().toString(),
+                            "timeRange", dateRange.label()
+                    ),
+                    Map.of(
+                            "statusDistribution", Map.of(),
+                            "typeDistribution", Map.of(),
+                            "trend", List.of()
+                    ),
+                    Map.of());
+        }
+
+        Map<String, Long> statusStats = filteredProcesses.stream()
+                .collect(Collectors.groupingBy(p -> approveStatusName(p.getApproveStatus()), LinkedHashMap::new, Collectors.counting()));
+        Map<String, Long> typeStats = filteredProcesses.stream()
+                .collect(Collectors.groupingBy(p -> approveTypeName(p.getApproveType()), LinkedHashMap::new, Collectors.counting()));
+
+        long pendingCount = countByStatus(filteredProcesses, 0);
+        long processingCount = countByStatus(filteredProcesses, 1);
+        long approvedCount = countByStatus(filteredProcesses, 2);
+        long rejectedCount = countByStatus(filteredProcesses, 3);
+        long resubmittedCount = countByStatus(filteredProcesses, 4);
+
+        TrendRange trendRange = buildTrendRange(dateRange.start(), dateRange.end(), filteredProcesses);
+
+        Map<String, Object> summary = new LinkedHashMap<>();
+        summary.put("total", filteredProcesses.size());
+        summary.put("pending", pendingCount);
+        summary.put("processing", processingCount);
+        summary.put("approved", approvedCount);
+        summary.put("rejected", rejectedCount);
+        summary.put("resubmitted", resubmittedCount);
+        summary.put("approvalCompletionRate", calculateRate(approvedCount, filteredProcesses.size()));
+        summary.put("rejectionRate", calculateRate(rejectedCount, filteredProcesses.size()));
+        summary.put("startDate", dateRange.start().toString());
+        summary.put("endDate", dateRange.end().toString());
+        summary.put("timeRange", dateRange.label());
+        summary.put("trendGranularity", trendRange.granularity());
+
+        Map<String, Object> charts = new LinkedHashMap<>();
+        charts.put("statusBarOption", buildStatusBarOption(statusStats));
+        charts.put("typePieOption", buildTypePieOption(typeStats));
+        charts.put("trendLineOption", buildTrendLineOption(trendRange.labels(), trendRange.values(), trendRange.label()));
+
+        return jsonResponse(true, "todo_stats", "宸茶繑鍥炲綋鍓嶇敤鎴风浉鍏冲鎵圭粺璁°��",
+                summary,
+                Map.of(
+                        "statusDistribution", statusStats,
+                        "typeDistribution", typeStats,
+                        "trend", toTrendItems(trendRange.labels(), trendRange.values())
+                ),
+                charts);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Tool(name = "瀹℃壒寰呭姙", value = "鎵ц瀹℃壒鍔ㄤ綔锛宎ction 浠呮敮鎸� approve 鎴� reject锛屼笖鍙兘澶勭悊褰撳墠鐧诲綍浜鸿嚜宸辩殑寰呭鑺傜偣銆�")
+    public String reviewTodo(@ToolMemoryId String memoryId,
+                             @P("娴佺▼缂栧彿 approveId") String approveId,
+                             @P("鍔ㄤ綔锛宎pprove=閫氳繃锛宺eject=椹冲洖") String action,
+                             @P(value = "瀹℃壒澶囨敞锛屽彲涓嶄紶", required = false) String remark) {
+
+        ApproveProcess process = getAccessibleProcess(memoryId, approveId);
+        if (process == null) {
+            return actionResult(false, "review_action", "鏈壘鍒板搴斿鎵癸紝鎴栧綋鍓嶇敤鎴锋棤鏉冭闂娴佺▼銆�", approveId, null);
+        }
+        if (!canOperate(process, currentUserId(memoryId))) {
+            return actionResult(false, "review_action", "褰撳墠鐧诲綍浜轰笉鏄瀹℃壒鐨勫綋鍓嶅鐞嗕汉銆�", approveId, null);
+        }
+        if (process.getApproveStatus() != null && (process.getApproveStatus() == 2 || process.getApproveStatus() == 3)) {
+            return actionResult(false, "review_action", "璇ュ鎵瑰凡缁撴潫锛屼笉鑳介噸澶嶅鐞嗐��", approveId, null);
+        }
+
+        List<ApproveNode> nodes = listNodes(process);
+        ApproveNode currentNode = findCurrentNode(nodes);
+        if (currentNode == null || !Objects.equals(currentNode.getApproveNodeUserId(), currentUserId(memoryId))) {
+            return actionResult(false, "review_action", "鏈壘鍒板綋鍓嶇敤鎴峰彲澶勭悊鐨勫鎵硅妭鐐广��", approveId, null);
+        }
+
+        String normalizedAction = action == null ? "" : action.trim().toLowerCase();
+        currentNode.setApproveNodeRemark(remark);
+        currentNode.setApproveNodeReason("reject".equals(normalizedAction) ? remark : null);
+        currentNode.setUpdateUser(currentUserId(memoryId));
+        currentNode.setUpdateTime(LocalDateTime.now());
+        currentNode.setIsLast(isLastNode(nodes, currentNode));
+
+        try {
+            switch (normalizedAction) {
+                case "approve" -> currentNode.setApproveNodeStatus(1);
+                case "reject" -> currentNode.setApproveNodeStatus(2);
+                default -> {
+                    return actionResult(false, "review_action", "action 鍙敮鎸� approve 鎴� reject銆�", approveId, null);
+                }
+            }
+            approveNodeService.updateApproveNode(currentNode);
+        } catch (IOException e) {
+            throw new RuntimeException("瀹℃壒澶勭悊澶辫触", e);
+        }
+
+        ApproveProcess refreshed = getProcessByApproveId(approveId);
+        writeApproveLog(memoryId, refreshed, currentNode, remark);
+        ApproveNode nextNode = refreshed == null ? null : findCurrentNode(listNodes(refreshed));
+
+        return actionResult(true, "review_action",
+                "approve".equals(normalizedAction) ? "瀹℃壒宸查�氳繃銆�" : "瀹℃壒宸查┏鍥炪��",
+                approveId,
+                Map.of(
+                        "action", normalizedAction,
+                        "currentStatus", refreshed == null ? "" : approveStatusName(refreshed.getApproveStatus()),
+                        "nextApprover", nextNode == null ? "" : safe(nextNode.getApproveNodeUser()),
+                        "remark", safe(remark)
+                ));
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Tool(name = "鍙栨秷瀹℃壒寰呭姙瀹℃牳", value = "鎾ら攢鏈�杩戜竴娆″鏍哥粨鏋滐紝浠呭厑璁告渶杩戜竴娆″鏍镐汉鎴栫敵璇蜂汉鎿嶄綔銆�")
+    public String cancelReviewTodo(@ToolMemoryId String memoryId,
+                                   @P("娴佺▼缂栧彿 approveId") String approveId,
+                                   @P(value = "鍙栨秷鍘熷洜锛屽彲涓嶄紶", required = false) String reason) {
+
+        ApproveProcess process = getAccessibleProcess(memoryId, approveId);
+        if (process == null) {
+            return actionResult(false, "cancel_review_action", "鏈壘鍒板搴斿鎵癸紝鎴栧綋鍓嶇敤鎴锋棤鏉冭闂娴佺▼銆�", approveId, null);
+        }
+
+        List<ApproveNode> nodes = listNodes(process);
+        ApproveNode lastReviewedNode = nodes.stream()
+                .filter(node -> node.getApproveNodeStatus() != null && node.getApproveNodeStatus() != 0)
+                .max(Comparator.comparing(ApproveNode::getApproveNodeOrder))
+                .orElse(null);
+        if (lastReviewedNode == null) {
+            return actionResult(false, "cancel_review_action", "褰撳墠娴佺▼娌℃湁鍙挙閿�鐨勫鏍歌褰曘��", approveId, null);
+        }
+
+        Long userId = currentUserId(memoryId);
+        if (!isAdmin(userId)
+                && !Objects.equals(process.getApproveUser(), userId)
+                && !Objects.equals(lastReviewedNode.getApproveNodeUserId(), userId)) {
+            return actionResult(false, "cancel_review_action", "鍙湁鐢宠浜恒�佹渶杩戜竴娆″鏍镐汉鎴栫鐞嗗憳鍙互鎾ら攢銆�", approveId, null);
+        }
+
+        lastReviewedNode.setApproveNodeStatus(0);
+        lastReviewedNode.setApproveNodeTime(null);
+        lastReviewedNode.setApproveNodeReason(null);
+        lastReviewedNode.setApproveNodeRemark(reason);
+        lastReviewedNode.setUpdateUser(userId);
+        lastReviewedNode.setUpdateTime(LocalDateTime.now());
+        approveNodeMapper.updateById(lastReviewedNode);
+
+        ApproveLog latestLog = listLogs(process.getId()).stream()
+                .max(Comparator.comparing(ApproveLog::getApproveNodeOrder)
+                        .thenComparing(ApproveLog::getApproveTime, Comparator.nullsLast(Date::compareTo)))
+                .orElse(null);
+        if (latestLog != null) {
+            approveLogMapper.deleteById(latestLog.getId());
+        }
+
+        process.setApproveOverTime(null);
+        process.setApproveRemark(reason);
+        process.setApproveStatus(lastReviewedNode.getApproveNodeOrder() == null || lastReviewedNode.getApproveNodeOrder() <= 1 ? 0 : 1);
+        process.setApproveUserCurrentId(lastReviewedNode.getApproveNodeUserId());
+        process.setApproveUserCurrentName(lastReviewedNode.getApproveNodeUser());
+        approveProcessMapper.updateById(process);
+
+        return actionResult(true, "cancel_review_action", "鏈�杩戜竴娆″鏍稿凡鎾ら攢銆�", approveId, Map.of(
+                "rollbackNodeOrder", lastReviewedNode.getApproveNodeOrder(),
+                "currentStatus", approveStatusName(process.getApproveStatus()),
+                "currentApprover", safe(process.getApproveUserCurrentName()),
+                "reason", safe(reason)
+        ));
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Tool(name = "淇敼瀹℃壒寰呭姙", value = "淇敼瀹℃壒鍗曞熀纭�淇℃伅锛屼粎鍏佽鐢宠浜轰慨鏀癸紱涓嶆敮鎸侀�氳繃 AI 鍙樻洿瀹℃壒绫诲瀷銆�")
+    public String updateTodo(@ToolMemoryId String memoryId,
+                             @P("娴佺▼缂栧彿 approveId") String approveId,
+                             @P(value = "鏂扮殑鏍囬锛屽彲涓嶄紶", required = false) String approveReason,
+                             @P(value = "鏂扮殑寮�濮嬫棩鏈� yyyy-MM-dd锛屽彲涓嶄紶", required = false) String startDate,
+                             @P(value = "鏂扮殑缁撴潫鏃ユ湡 yyyy-MM-dd锛屽彲涓嶄紶", required = false) String endDate,
+                             @P(value = "鏂扮殑閲戦锛屽彲涓嶄紶", required = false) BigDecimal price,
+                             @P(value = "鏂扮殑鍦扮偣锛屽彲涓嶄紶", required = false) String location,
+                             @P(value = "鏂扮殑瀹℃壒绫诲瀷锛屽彲涓嶄紶", required = false) Integer approveType,
+                             @P(value = "鏂扮殑澶囨敞锛屽彲涓嶄紶", required = false) String approveRemark) {
+
+        ApproveProcess process = getAccessibleProcess(memoryId, approveId);
+        if (process == null) {
+            return actionResult(false, "update_action", "鏈壘鍒板搴斿鎵癸紝鎴栧綋鍓嶇敤鎴锋棤鏉冭闂娴佺▼銆�", approveId, null);
+        }
+        if (!Objects.equals(process.getApproveUser(), currentUserId(memoryId)) && !isAdmin(currentUserId(memoryId))) {
+            return actionResult(false, "update_action", "鍙湁鐢宠浜烘垨绠$悊鍛樺彲浠ヤ慨鏀瑰鎵瑰崟銆�", approveId, null);
+        }
+        if (process.getApproveStatus() != null && (process.getApproveStatus() == 1 || process.getApproveStatus() == 2)) {
+            return actionResult(false, "update_action", "瀹℃壒澶勭悊涓垨宸插畬鎴愭椂锛屼笉鍏佽閫氳繃 AI 淇敼銆�", approveId, null);
+        }
+        if (approveType != null && !Objects.equals(approveType, process.getApproveType())) {
+            return actionResult(false, "update_action", "AI 鍔╂墜鏆備笉鏀寔鐩存帴鍙樻洿瀹℃壒绫诲瀷锛岄伩鍏嶈妭鐐归厤缃け鐪熴��", approveId, null);
+        }
+        if (!StringUtils.hasText(approveReason)
+                && !StringUtils.hasText(startDate)
+                && !StringUtils.hasText(endDate)
+                && price == null
+                && !StringUtils.hasText(location)
+                && !StringUtils.hasText(approveRemark)) {
+            return actionResult(false, "update_action", "娌℃湁妫�娴嬪埌鍙洿鏂扮殑瀛楁銆�", approveId, null);
+        }
+
+        if (StringUtils.hasText(approveReason)) {
+            process.setApproveReason(approveReason);
+        }
+        if (StringUtils.hasText(startDate)) {
+            process.setStartDate(parseDate(startDate));
+        }
+        if (StringUtils.hasText(endDate)) {
+            process.setEndDate(parseDate(endDate));
+        }
+        if (price != null) {
+            process.setPrice(price);
+        }
+        if (StringUtils.hasText(location)) {
+            process.setLocation(location);
+        }
+        if (StringUtils.hasText(approveRemark)) {
+            process.setApproveRemark(approveRemark);
+        }
+
+        approveProcessMapper.updateById(process);
+        return actionResult(true, "update_action", "瀹℃壒鍗曞凡鏇存柊銆�", approveId, Map.of(
+                "approveReason", safe(process.getApproveReason()),
+                "startDate", formatDate(process.getStartDate()),
+                "endDate", formatDate(process.getEndDate()),
+                "price", process.getPrice() == null ? "" : process.getPrice(),
+                "location", safe(process.getLocation()),
+                "approveType", approveTypeName(process.getApproveType()),
+                "approveRemark", safe(process.getApproveRemark())
+        ));
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Tool(name = "鍒犻櫎瀹℃壒寰呭姙", value = "鍒犻櫎瀹℃壒娴佺▼锛屼粎鍏佽鐢宠浜哄垹闄ゆ湭瀹屾垚鐨勬祦绋嬨��")
+    public String deleteTodo(@ToolMemoryId String memoryId,
+                             @P("娴佺▼缂栧彿 approveId") String approveId) {
+        ApproveProcess process = getAccessibleProcess(memoryId, approveId);
+        if (process == null) {
+            return actionResult(false, "delete_action", "鏈壘鍒板搴斿鎵癸紝鎴栧綋鍓嶇敤鎴锋棤鏉冭闂娴佺▼銆�", approveId, null);
+        }
+        if (!Objects.equals(process.getApproveUser(), currentUserId(memoryId)) && !isAdmin(currentUserId(memoryId))) {
+            return actionResult(false, "delete_action", "鍙湁鐢宠浜烘垨绠$悊鍛樺彲浠ュ垹闄ゅ鎵瑰崟銆�", approveId, null);
+        }
+        if (process.getApproveStatus() != null && (process.getApproveStatus() == 1 || process.getApproveStatus() == 2)) {
+            return actionResult(false, "delete_action", "瀹℃壒澶勭悊涓垨宸插畬鎴愮殑娴佺▼涓嶅厑璁搁�氳繃 AI 鍒犻櫎銆�", approveId, null);
+        }
+
+        approveProcessService.delByIds(Collections.singletonList(process.getId()));
+        return actionResult(true, "delete_action", "瀹℃壒娴佺▼宸插垹闄ゃ��", approveId, Map.of(
+                "deletedProcessId", process.getId(),
+                "approveStatus", approveStatusName(process.getApproveStatus())
+        ));
+    }
+
+    private ApproveProcess getAccessibleProcess(String memoryId, String approveId) {
+        ApproveProcess process = getProcessByApproveId(approveId);
+        if (process == null) {
+            return null;
+        }
+        return canView(process, currentUserId(memoryId)) ? process : null;
+    }
+
+    private ApproveProcess getProcessByApproveId(String approveId) {
+        if (!StringUtils.hasText(approveId)) {
+            return null;
+        }
+        return approveProcessMapper.selectOne(new LambdaQueryWrapper<ApproveProcess>()
+                .eq(ApproveProcess::getApproveId, approveId)
+                .eq(ApproveProcess::getApproveDelete, 0)
+                .last("limit 1"));
+    }
+
+    private List<ApproveNode> listNodes(ApproveProcess process) {
+        if (process == null) {
+            return List.of();
+        }
+        List<ApproveNode> nodes = defaultList(approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>()
+                .eq(ApproveNode::getDeleteFlag, 0)
+                .eq(ApproveNode::getApproveProcessId, process.getApproveId())
+                .orderByAsc(ApproveNode::getApproveNodeOrder)));
+        if (!nodes.isEmpty()) {
+            return nodes;
+        }
+        return defaultList(approveNodeMapper.selectList(new LambdaQueryWrapper<ApproveNode>()
+                .eq(ApproveNode::getDeleteFlag, 0)
+                .eq(ApproveNode::getApproveProcessId, String.valueOf(process.getId()))
+                .orderByAsc(ApproveNode::getApproveNodeOrder)));
+    }
+
+    private List<ApproveLog> listLogs(Long processId) {
+        return defaultList(approveLogMapper.selectList(new LambdaQueryWrapper<ApproveLog>()
+                .eq(ApproveLog::getApproveId, processId)
+                .orderByAsc(ApproveLog::getApproveNodeOrder, ApproveLog::getApproveTime)));
+    }
+
+    private ApproveNode findCurrentNode(List<ApproveNode> nodes) {
+        return nodes.stream()
+                .filter(node -> node.getApproveNodeStatus() != null && node.getApproveNodeStatus() == 0)
+                .min(Comparator.comparing(ApproveNode::getApproveNodeOrder))
+                .orElse(null);
+    }
+
+    private boolean isLastNode(List<ApproveNode> nodes, ApproveNode currentNode) {
+        Integer maxOrder = nodes.stream()
+                .map(ApproveNode::getApproveNodeOrder)
+                .filter(Objects::nonNull)
+                .max(Integer::compareTo)
+                .orElse(null);
+        return maxOrder != null && Objects.equals(maxOrder, currentNode.getApproveNodeOrder());
+    }
+
+    private void writeApproveLog(String memoryId, ApproveProcess process, ApproveNode currentNode, String remark) {
+        if (process == null || currentNode == null) {
+            return;
+        }
+        ApproveLog log = new ApproveLog();
+        log.setApproveId(process.getId());
+        log.setApproveNodeOrder(currentNode.getApproveNodeOrder());
+        log.setApproveUser(currentUserId(memoryId));
+        log.setApproveTime(new Date());
+        log.setApproveStatus(process.getApproveStatus());
+        log.setApproveRemark(remark);
+        approveLogMapper.insert(log);
+    }
+
+    private boolean canView(ApproveProcess process, Long userId) {
+        if (process == null || userId == null) {
+            return false;
+        }
+        return isAdmin(userId)
+                || Objects.equals(process.getApproveUser(), userId)
+                || Objects.equals(process.getApproveUserCurrentId(), userId)
+                || containsUserId(process.getApproveUserIds(), userId);
+    }
+
+    private boolean canOperate(ApproveProcess process, Long userId) {
+        return process != null && userId != null && Objects.equals(process.getApproveUserCurrentId(), userId);
+    }
+
+    private boolean containsUserId(String csv, Long userId) {
+        if (!StringUtils.hasText(csv) || userId == null) {
+            return false;
+        }
+        String target = String.valueOf(userId);
+        for (String item : csv.split(",")) {
+            if (target.equals(item.trim())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private String relationName(ApproveProcess process, Long userId) {
+        if (Objects.equals(process.getApproveUserCurrentId(), userId)) {
+            return "褰撳墠瀹℃壒浜�";
+        }
+        if (Objects.equals(process.getApproveUser(), userId)) {
+            return "鐢宠浜�";
+        }
+        if (containsUserId(process.getApproveUserIds(), userId)) {
+            return "瀹℃壒閾炬垚鍛�";
+        }
+        return "鍙";
+    }
+
+    private List<String> todoColumns() {
+        return List.of("approveId", "approveType", "approveUserName", "approveUserCurrentName",
+                "approveReason", "approveStatus", "createTime", "relation");
+    }
+
+    private int normalizeLimit(Integer limit) {
+        if (limit == null || limit <= 0) {
+            return DEFAULT_LIMIT;
+        }
+        return Math.min(limit, MAX_LIMIT);
+    }
+
+    private Integer parseStatus(String status) {
+        if (!StringUtils.hasText(status) || "all".equalsIgnoreCase(status)) {
+            return null;
+        }
+        return switch (status.trim().toLowerCase()) {
+            case "pending" -> 0;
+            case "processing" -> 1;
+            case "approved" -> 2;
+            case "rejected" -> 3;
+            case "resubmitted" -> 4;
+            default -> null;
+        };
+    }
+
+    private String normalizeScope(String scope) {
+        if (!StringUtils.hasText(scope)) {
+            return "related";
+        }
+        return switch (scope.trim().toLowerCase()) {
+            case "applicant", "mine", "created", "initiated" -> "applicant";
+            case "approver", "handler", "todo", "pending" -> "approver";
+            default -> "related";
+        };
+    }
+
+    private String approveStatusName(Integer status) {
+        if (status == null) {
+            return "鏈煡";
+        }
+        return switch (status) {
+            case 0 -> "寰呭鏍�";
+            case 1 -> "瀹℃牳涓�";
+            case 2 -> "瀹℃牳瀹屾垚";
+            case 3 -> "瀹℃牳鏈�氳繃";
+            case 4 -> "宸查噸鏂版彁浜�";
+            default -> "鏈煡";
+        };
+    }
+
+    private String approveNodeStatusName(Integer status) {
+        if (status == null) {
+            return "鏈煡";
+        }
+        return switch (status) {
+            case 0 -> "鏈鏍�";
+            case 1 -> "鍚屾剰";
+            case 2 -> "鎷掔粷";
+            default -> "鏈煡";
+        };
+    }
+
+    private String approveTypeName(Integer type) {
+        if (type == null) {
+            return "鏈煡";
+        }
+        return switch (type) {
+            case 1 -> "鍏嚭绠$悊";
+            case 2 -> "璇峰亣绠$悊";
+            case 3 -> "鍑哄樊绠$悊";
+            case 4 -> "鎶ラ攢绠$悊";
+            case 5 -> "閲囪喘瀹℃壒";
+            case 6 -> "鎶ヤ环瀹℃壒";
+            case 7 -> "鍙戣揣瀹℃壒";
+            case 8 -> "鍗遍櫓浣滀笟瀹℃壒";
+            case 9 -> "鍔炲叕鐢ㄥ搧瀹℃壒";
+            default -> "绫诲瀷" + type;
+        };
+    }
+
+    private String safe(Object value) {
+        return value == null ? "" : String.valueOf(value).replace('\n', ' ').replace('\r', ' ');
+    }
+
+    private String formatDateTime(Object value) {
+        if (value == null) {
+            return "";
+        }
+        if (value instanceof LocalDateTime localDateTime) {
+            return localDateTime.format(DATE_TIME_FORMATTER);
+        }
+        return safe(value);
+    }
+
+    private String formatDate(Date value) {
+        return value == null ? "" : DATE_FORMAT.format(value);
+    }
+
+    private long countByStatus(List<ApproveProcess> processes, int status) {
+        return processes.stream()
+                .filter(process -> process.getApproveStatus() != null)
+                .filter(process -> process.getApproveStatus() == status)
+                .count();
+    }
+
+    private String calculateRate(long part, int total) {
+        if (total <= 0) {
+            return "0.00%";
+        }
+        return String.format("%.2f%%", part * 100.0 / total);
+    }
+
+    private List<Map<String, Object>> toTrendItems(List<String> dates, List<Long> values) {
+        List<Map<String, Object>> items = new ArrayList<>();
+        for (int i = 0; i < dates.size(); i++) {
+            Map<String, Object> item = new LinkedHashMap<>();
+            item.put("date", dates.get(i));
+            item.put("count", values.get(i));
+            items.add(item);
+        }
+        return items;
+    }
+
+    private Map<String, Object> buildStatusBarOption(Map<String, Long> statusStats) {
+        Map<String, Object> option = new LinkedHashMap<>();
+        option.put("title", Map.of("text", "瀹℃壒鐘舵�佸垎甯�", "left", "center"));
+        option.put("tooltip", Map.of("trigger", "axis"));
+        option.put("xAxis", Map.of("type", "category", "data", new ArrayList<>(statusStats.keySet())));
+        option.put("yAxis", Map.of("type", "value"));
+        option.put("series", List.of(Map.of(
+                "name", "鏁伴噺",
+                "type", "bar",
+                "data", new ArrayList<>(statusStats.values()),
+                "barWidth", "40%"
+        )));
+        return option;
+    }
+
+    private Map<String, Object> buildTypePieOption(Map<String, Long> typeStats) {
+        List<Map<String, Object>> data = typeStats.entrySet().stream()
+                .map(entry -> {
+                    Map<String, Object> item = new LinkedHashMap<>();
+                    item.put("name", entry.getKey());
+                    item.put("value", entry.getValue());
+                    return item;
+                })
+                .collect(Collectors.toList());
+
+        Map<String, Object> option = new LinkedHashMap<>();
+        option.put("title", Map.of("text", "瀹℃壒绫诲瀷鍗犳瘮", "left", "center"));
+        option.put("tooltip", Map.of("trigger", "item"));
+        option.put("legend", Map.of("orient", "vertical", "left", "left"));
+        option.put("series", List.of(Map.of(
+                "name", "瀹℃壒绫诲瀷",
+                "type", "pie",
+                "radius", List.of("35%", "65%"),
+                "data", data
+        )));
+        return option;
+    }
+
+    private Map<String, Object> buildTrendLineOption(List<String> dates, List<Long> values, String label) {
+        Map<String, Object> option = new LinkedHashMap<>();
+        option.put("title", Map.of("text", label + "瀹℃壒鏂板瓒嬪娍", "left", "center"));
+        option.put("tooltip", Map.of("trigger", "axis"));
+        option.put("xAxis", Map.of("type", "category", "data", dates));
+        option.put("yAxis", Map.of("type", "value"));
+        option.put("series", List.of(Map.of(
+                "name", "鏂板瀹℃壒",
+                "type", "line",
+                "smooth", true,
+                "data", values,
+                "areaStyle", Map.of()
+        )));
+        return option;
+    }
+
+    private Date parseDate(String dateText) {
+        try {
+            return DATE_FORMAT.parse(dateText);
+        } catch (ParseException e) {
+            throw new IllegalArgumentException("鏃ユ湡鏍煎紡蹇呴』鏄� yyyy-MM-dd");
+        }
+    }
+
+    private DateRange resolveDateRange(String startDateText, String endDateText, String timeRange) {
+        LocalDate today = LocalDate.now();
+        LocalDate explicitStart = parseLocalDate(startDateText);
+        LocalDate explicitEnd = parseLocalDate(endDateText);
+        if (explicitStart != null || explicitEnd != null) {
+            LocalDate start = explicitStart != null ? explicitStart : explicitEnd;
+            LocalDate end = explicitEnd != null ? explicitEnd : explicitStart;
+            if (start.isAfter(end)) {
+                LocalDate temp = start;
+                start = end;
+                end = temp;
+            }
+            return new DateRange(start, end, start + "鑷�" + end);
+        }
+        if (!StringUtils.hasText(timeRange)) {
+            return new DateRange(today.minusDays(6), today, "杩�7澶�");
+        }
+
+        String text = timeRange.trim();
+        if (text.contains("浠婂ぉ")) {
+            return new DateRange(today, today, "浠婂ぉ");
+        }
+        if (text.contains("鏄ㄥぉ") || text.contains("鏄ㄦ棩")) {
+            LocalDate day = today.minusDays(1);
+            return new DateRange(day, day, "鏄ㄥぉ");
+        }
+        if (text.contains("鏈懆")) {
+            LocalDate start = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+            return new DateRange(start, today, "鏈懆");
+        }
+        if (text.contains("涓婂懆")) {
+            LocalDate thisWeekStart = today.minusDays(today.getDayOfWeek().getValue() - 1L);
+            LocalDate start = thisWeekStart.minusWeeks(1);
+            LocalDate end = thisWeekStart.minusDays(1);
+            return new DateRange(start, end, "涓婂懆");
+        }
+        if (text.contains("鏈湀")) {
+            LocalDate start = today.withDayOfMonth(1);
+            return new DateRange(start, today, "鏈湀");
+        }
+        if (text.contains("涓婃湀")) {
+            YearMonth lastMonth = YearMonth.from(today).minusMonths(1);
+            return new DateRange(lastMonth.atDay(1), lastMonth.atEndOfMonth(), "涓婃湀");
+        }
+        if (text.contains("鏈勾") || text.contains("浠婂勾")) {
+            LocalDate start = today.withDayOfYear(1);
+            return new DateRange(start, today, "鏈勾");
+        }
+        if (text.contains("鍘诲勾")) {
+            LocalDate start = today.minusYears(1).withDayOfYear(1);
+            LocalDate end = today.minusYears(1).withMonth(12).withDayOfMonth(31);
+            return new DateRange(start, end, "鍘诲勾");
+        }
+
+        Matcher relativeMatcher = java.util.regex.Pattern.compile("(杩憒鏈�杩�)(\\d+)(澶﹟鍛▅涓湀|鏈坾骞�)").matcher(text);
+        if (relativeMatcher.find()) {
+            int amount = Integer.parseInt(relativeMatcher.group(2));
+            String unit = relativeMatcher.group(3);
+            LocalDate start = switch (unit) {
+                case "澶�" -> today.minusDays(Math.max(amount - 1L, 0));
+                case "鍛�" -> today.minusWeeks(Math.max(amount, 1)).plusDays(1);
+                case "涓湀", "鏈�" -> today.minusMonths(Math.max(amount, 1)).plusDays(1);
+                case "骞�" -> today.minusYears(Math.max(amount, 1)).plusDays(1);
+                default -> today.minusDays(6);
+            };
+            return new DateRange(start, today, "杩�" + amount + unit);
+        }
+
+        Matcher dateMatcher = java.util.regex.Pattern.compile("(\\d{4}-\\d{2}-\\d{2})").matcher(text);
+        if (dateMatcher.find()) {
+            LocalDate start = LocalDate.parse(dateMatcher.group(1));
+            LocalDate end = dateMatcher.find() ? LocalDate.parse(dateMatcher.group(1)) : start;
+            if (start.isAfter(end)) {
+                LocalDate temp = start;
+                start = end;
+                end = temp;
+            }
+            return new DateRange(start, end, start + "鑷�" + end);
+        }
+
+        return new DateRange(today.minusDays(6), today, "杩�7澶�");
+    }
+
+    private boolean withinDateRange(LocalDateTime createTime, DateRange dateRange) {
+        if (createTime == null) {
+            return false;
+        }
+        LocalDate date = createTime.toLocalDate();
+        return !date.isBefore(dateRange.start()) && !date.isAfter(dateRange.end());
+    }
+
+    private TrendRange buildTrendRange(LocalDate start, LocalDate end, List<ApproveProcess> processes) {
+        long days = ChronoUnit.DAYS.between(start, end) + 1;
+        if (days <= 31) {
+            List<String> labels = new ArrayList<>();
+            List<Long> values = new ArrayList<>();
+            for (LocalDate cursor = start; !cursor.isAfter(end); cursor = cursor.plusDays(1)) {
+                LocalDate current = cursor;
+                labels.add(current.toString());
+                values.add(processes.stream()
+                        .filter(process -> process.getCreateTime() != null)
+                        .filter(process -> process.getCreateTime().toLocalDate().equals(current))
+                        .count());
+            }
+            return new TrendRange(labels, values, "day", start + "鑷�" + end);
+        }
+
+        List<String> labels = new ArrayList<>();
+        List<Long> values = new ArrayList<>();
+        YearMonth startMonth = YearMonth.from(start);
+        YearMonth endMonth = YearMonth.from(end);
+        for (YearMonth cursor = startMonth; !cursor.isAfter(endMonth); cursor = cursor.plusMonths(1)) {
+            YearMonth current = cursor;
+            labels.add(current.toString());
+            values.add(processes.stream()
+                    .filter(process -> process.getCreateTime() != null)
+                    .filter(process -> YearMonth.from(process.getCreateTime()).equals(current))
+                    .count());
+        }
+        return new TrendRange(labels, values, "month", start + "鑷�" + end);
+    }
+
+    private LocalDate parseLocalDate(String text) {
+        if (!StringUtils.hasText(text)) {
+            return null;
+        }
+        return LocalDate.parse(text.trim());
+    }
+
+    private String actionResult(boolean success, String type, String description, String approveId, Map<String, Object> data) {
+        Map<String, Object> summary = new LinkedHashMap<>();
+        summary.put("approveId", safe(approveId));
+        return jsonResponse(success, type, description, summary, data == null ? Map.of() : data, Map.of());
+    }
+
+    private String jsonResponse(boolean success,
+                                String type,
+                                String description,
+                                Map<String, Object> summary,
+                                Map<String, Object> data,
+                                Map<String, Object> charts) {
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("success", success);
+        result.put("type", type);
+        result.put("description", description);
+        result.put("summary", summary == null ? Map.of() : summary);
+        result.put("data", data == null ? Map.of() : data);
+        result.put("charts", charts == null ? Map.of() : charts);
+        return JSON.toJSONString(result);
+    }
+
+    private LoginUser currentLoginUser(String memoryId) {
+        LoginUser loginUser = aiSessionUserContext.get(memoryId);
+        if (loginUser != null) {
+            return loginUser;
+        }
+        return SecurityUtils.getLoginUser();
+    }
+
+    private Long currentUserId(String memoryId) {
+        return currentLoginUser(memoryId).getUserId();
+    }
+
+    private boolean isAdmin(Long userId) {
+        return SecurityUtils.isAdmin(userId);
+    }
+
+    private <T> List<T> defaultList(List<T> list) {
+        return list == null ? List.of() : list;
+    }
+
+    private record DateRange(LocalDate start, LocalDate end, String label) {
+    }
+
+    private record TrendRange(List<String> labels, List<Long> values, String granularity, String label) {
+    }
+}
diff --git a/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
new file mode 100644
index 0000000..17b6868
--- /dev/null
+++ b/src/main/java/com/ruoyi/ai/tools/PurchaseAgentTools.java
@@ -0,0 +1,643 @@
+package com.ruoyi.ai.tools;
+
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.ai.context.AiSessionUserContext;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.purchase.mapper.InvoicePurchaseMapper;
+import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.purchase.pojo.InvoicePurchase;
+import com.ruoyi.purchase.pojo.PaymentRegistration;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import com.ruoyi.procurementrecord.mapper.InboundManagementMapper;
+import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
+import com.ruoyi.procurementrecord.pojo.InboundManagement;
+import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import dev.langchain4j.agent.tool.P;
+import dev.langchain4j.agent.tool.Tool;
+import dev.langchain4j.agent.tool.ToolMemoryId;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Comparator;
+import java.util.stream.Collectors;
+
+@Component
+public class PurchaseAgentTools {
+
+    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    private static final int DEFAULT_LIMIT = 10;
+    private static final int MAX_LIMIT = 30;
+
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
+    private final PaymentRegistrationMapper paymentRegistrationMapper;
+    private final InvoicePurchaseMapper invoicePurchaseMapper;
+    private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final ProcurementRecordMapper procurementRecordMapper;
+    private final InboundManagementMapper inboundManagementMapper;
+    private final AiSessionUserContext aiSessionUserContext;
+
+    public PurchaseAgentTools(PurchaseLedgerMapper purchaseLedgerMapper,
+                              PaymentRegistrationMapper paymentRegistrationMapper,
+                              InvoicePurchaseMapper invoicePurchaseMapper,
+                              PurchaseReturnOrdersMapper purchaseReturnOrdersMapper,
+                              SalesLedgerProductMapper salesLedgerProductMapper,
+                              ProcurementRecordMapper procurementRecordMapper,
+                              InboundManagementMapper inboundManagementMapper,
+                              AiSessionUserContext aiSessionUserContext) {
+        this.purchaseLedgerMapper = purchaseLedgerMapper;
+        this.paymentRegistrationMapper = paymentRegistrationMapper;
+        this.invoicePurchaseMapper = invoicePurchaseMapper;
+        this.purchaseReturnOrdersMapper = purchaseReturnOrdersMapper;
+        this.salesLedgerProductMapper = salesLedgerProductMapper;
+        this.procurementRecordMapper = procurementRecordMapper;
+        this.inboundManagementMapper = inboundManagementMapper;
+        this.aiSessionUserContext = aiSessionUserContext;
+    }
+
+    @Tool(name = "鏌ヨ閲囪喘鍙拌处鍒楄〃", value = "鎸夊叧閿瓧鍜屾椂闂磋寖鍥存煡璇㈤噰璐彴璐︼紝鏀寔杩斿洖鏈�杩慛鏉�")
+    public String listPurchaseLedgers(@ToolMemoryId String memoryId,
+                                      @P(value = "鍏抽敭瀛楋紝鍙尮閰嶉噰璐悎鍚屽彿/渚涘簲鍟�/椤圭洰鍚�", required = false) String keyword,
+                                      @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+                                      @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+                                      @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
+        LoginUser loginUser = currentLoginUser(memoryId);
+        LocalDate start = parseLocalDate(startDate);
+        LocalDate end = parseLocalDate(endDate);
+        int finalLimit = normalizeLimit(limit);
+
+        LambdaQueryWrapper<PurchaseLedger> wrapper = new LambdaQueryWrapper<>();
+        applyTenantFilter(wrapper, loginUser.getTenantId(), PurchaseLedger::getTenantId);
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like(PurchaseLedger::getPurchaseContractNumber, keyword)
+                    .or().like(PurchaseLedger::getSupplierName, keyword)
+                    .or().like(PurchaseLedger::getProjectName, keyword));
+        }
+        if (start != null) {
+            wrapper.ge(PurchaseLedger::getEntryDate, toDate(start));
+        }
+        if (end != null) {
+            wrapper.lt(PurchaseLedger::getEntryDate, toExclusiveEndDate(end));
+        }
+        wrapper.orderByDesc(PurchaseLedger::getEntryDate, PurchaseLedger::getId).last("limit " + finalLimit);
+
+        List<PurchaseLedger> rows = defaultList(purchaseLedgerMapper.selectList(wrapper));
+        List<Map<String, Object>> items = rows.stream().map(this::toLedgerItem).collect(Collectors.toList());
+        return jsonResponse(true, "purchase_ledger_list", "宸茶繑鍥為噰璐彴璐﹀垪琛�",
+                Map.of("count", items.size(), "limit", finalLimit, "keyword", safe(keyword)),
+                Map.of("items", items), Map.of());
+    }
+
+    @Tool(name = "鏌ヨ閲囪喘鍙拌处璇︽儏", value = "鎸夐噰璐彴璐D鏌ヨ璇︽儏")
+    public String getPurchaseLedgerDetail(@ToolMemoryId String memoryId, @P("閲囪喘鍙拌处ID") Long ledgerId) {
+        if (ledgerId == null) {
+            return jsonResponse(false, "purchase_ledger_detail", "閲囪喘鍙拌处ID涓嶈兘涓虹┖", Map.of(), Map.of(), Map.of());
+        }
+        LoginUser loginUser = currentLoginUser(memoryId);
+        PurchaseLedger ledger = purchaseLedgerMapper.selectById(ledgerId);
+        if (ledger == null || !tenantMatched(ledger.getTenantId(), loginUser.getTenantId())) {
+            return jsonResponse(false, "purchase_ledger_detail", "鏈壘鍒拌閲囪喘鍙拌处鎴栨棤鏉冮檺璁块棶", Map.of("ledgerId", ledgerId), Map.of(), Map.of());
+        }
+        return jsonResponse(true, "purchase_ledger_detail", "宸茶繑鍥為噰璐彴璐﹁鎯�",
+                Map.of("ledgerId", ledgerId),
+                Map.of("detail", toLedgerItem(ledger)),
+                Map.of());
+    }
+
+    @Tool(name = "缁熻閲囪喘鏁版嵁", value = "缁熻鏃堕棿鑼冨洿鍐呴噰璐悎鍚屾暟銆佸悎鍚岄噾棰濄�佷粯娆鹃噾棰濄�佸彂绁ㄩ噾棰濄�侀��璐ч噾棰�")
+    public String getPurchaseStats(@ToolMemoryId String memoryId,
+                                   @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+                                   @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+                                   @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屼緥濡備粖骞淬�佹湰鏈堛�佽繎30澶�", required = false) String timeRange) {
+        LoginUser loginUser = currentLoginUser(memoryId);
+        DateRange range = resolveDateRange(startDate, endDate, timeRange);
+
+        List<PurchaseLedger> ledgers = queryLedgers(loginUser, range);
+        List<PaymentRegistration> payments = queryPayments(loginUser, range);
+        List<InvoicePurchase> invoices = queryInvoices(loginUser, range);
+        List<PurchaseReturnOrders> returns = queryReturns(loginUser, range);
+
+        BigDecimal contractAmount = ledgers.stream()
+                .map(PurchaseLedger::getContractAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal paymentAmount = payments.stream()
+                .map(PaymentRegistration::getCurrentPaymentAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal invoiceAmount = invoices.stream()
+                .map(InvoicePurchase::getInvoiceAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal returnAmount = returns.stream()
+                .map(PurchaseReturnOrders::getTotalAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        Map<String, Object> summary = new LinkedHashMap<>();
+        summary.put("timeRange", range.label());
+        summary.put("startDate", range.start().toString());
+        summary.put("endDate", range.end().toString());
+        summary.put("ledgerCount", ledgers.size());
+        summary.put("paymentCount", payments.size());
+        summary.put("invoiceCount", invoices.size());
+        summary.put("returnCount", returns.size());
+        summary.put("contractAmount", contractAmount);
+        summary.put("paymentAmount", paymentAmount);
+        summary.put("invoiceAmount", invoiceAmount);
+        summary.put("returnAmount", returnAmount);
+
+        return jsonResponse(true, "purchase_stats", "宸茶繑鍥為噰璐粺璁℃暟鎹�", summary, Map.of(), Map.of());
+    }
+
+    @Tool(name = "閲囪喘鐗╂枡閲戦鎺掕", value = "鎸夋椂闂磋寖鍥寸粺璁¢噰璐墿鏂欓噾棰濇帓琛岋紝鍙洖绛旀湰鏈堥噰璐噾棰濇帓鍚嶉潬鍓嶇殑鐗╂枡銆�")
+    public String rankPurchaseMaterials(@ToolMemoryId String memoryId,
+                                        @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+                                        @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+                                        @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屼緥濡傛湰鏈堛�佽繎7澶┿�佽繎30澶�", required = false) String timeRange,
+                                        @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
+        LoginUser loginUser = currentLoginUser(memoryId);
+        DateRange range = resolveDateRange(startDate, endDate, timeRange);
+        List<Long> ledgerIds = queryLedgers(loginUser, range).stream()
+                .map(PurchaseLedger::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        if (ledgerIds.isEmpty()) {
+            return jsonResponse(true, "purchase_material_rank", "褰撳墠鏃堕棿鑼冨洿鍐呮病鏈夐噰璐墿鏂欐暟鎹��",
+                    rangeSummary(range, 0), Map.of("items", List.of()), Map.of());
+        }
+
+        List<SalesLedgerProduct> products = defaultList(salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getType, 2)
+                .in(SalesLedgerProduct::getSalesLedgerId, ledgerIds)));
+
+        Map<String, MaterialRankItem> grouped = new LinkedHashMap<>();
+        for (SalesLedgerProduct product : products) {
+            String name = safe(product.getProductCategory());
+            String model = safe(product.getSpecificationModel());
+            String key = name + "|" + model;
+            MaterialRankItem item = grouped.computeIfAbsent(key, ignored -> new MaterialRankItem(name, model, safe(product.getUnit())));
+            item.quantity = item.quantity.add(defaultDecimal(product.getQuantity()));
+            item.amount = item.amount.add(defaultDecimal(product.getTaxInclusiveTotalPrice()));
+        }
+
+        List<Map<String, Object>> items = grouped.values().stream()
+                .sorted(Comparator.comparing((MaterialRankItem item) -> item.amount).reversed())
+                .limit(normalizeLimit(limit))
+                .map(MaterialRankItem::toMap)
+                .collect(Collectors.toList());
+
+        return jsonResponse(true, "purchase_material_rank", "宸茶繑鍥為噰璐墿鏂欓噾棰濇帓琛屻��",
+                rangeSummary(range, items.size()), Map.of("items", items), Map.of());
+    }
+
+    @Tool(name = "鏌ヨ鏈叆搴撻噰璐鍗�", value = "鏌ヨ閲囪喘璁㈠崟涓嬩粛鏈夊緟鍏ュ簱鏁伴噺鐨勭墿鏂欐槑缁嗐��")
+    public String listUnstockedPurchaseOrders(@ToolMemoryId String memoryId,
+                                              @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+                                              @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+                                              @P(value = "鍏抽敭瀛楋紝鍙尮閰嶉噰璐悎鍚屽彿/渚涘簲鍟�/鐗╂枡", required = false) String keyword,
+                                              @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
+        LoginUser loginUser = currentLoginUser(memoryId);
+        DateRange range = resolveDateRange(startDate, endDate, null);
+        List<PurchaseLedger> ledgers = queryLedgers(loginUser, range).stream()
+                .filter(ledger -> matchLedgerKeyword(ledger, keyword))
+                .collect(Collectors.toList());
+        Map<Long, PurchaseLedger> ledgerMap = ledgers.stream()
+                .filter(ledger -> ledger.getId() != null)
+                .collect(Collectors.toMap(PurchaseLedger::getId, ledger -> ledger, (a, b) -> a, LinkedHashMap::new));
+        if (ledgerMap.isEmpty()) {
+            return jsonResponse(true, "purchase_unstocked_list", "鏈煡璇㈠埌绗﹀悎鏉′欢鐨勯噰璐鍗曘��",
+                    rangeSummary(range, 0), Map.of("items", List.of()), Map.of());
+        }
+
+        List<SalesLedgerProduct> products = defaultList(salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getType, 2)
+                .in(SalesLedgerProduct::getSalesLedgerId, ledgerMap.keySet())));
+
+        List<Map<String, Object>> items = products.stream()
+                .filter(product -> matchProductKeyword(product, keyword))
+                .map(product -> toUnstockedItem(product, ledgerMap.get(product.getSalesLedgerId())))
+                .filter(Objects::nonNull)
+                .limit(normalizeLimit(limit))
+                .collect(Collectors.toList());
+
+        return jsonResponse(true, "purchase_unstocked_list", "宸茶繑鍥炴湭鍏ュ簱閲囪喘璁㈠崟銆�",
+                rangeSummary(range, items.size()), Map.of("items", items), Map.of());
+    }
+
+    @Tool(name = "鏌ヨ閲囪喘鍒拌揣寮傚父", value = "鏌ヨ鍒拌揣鐘舵�佸紓甯告垨澶囨敞鍖呭惈寮傚父淇℃伅鐨勫埌璐ц褰曘��")
+    public String listArrivalExceptions(@ToolMemoryId String memoryId,
+                                        @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+                                        @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+                                        @P(value = "鏃堕棿鑼冨洿鎻忚堪锛屼緥濡傝繎7澶┿�佹湰鏈�", required = false) String timeRange,
+                                        @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
+        LoginUser loginUser = currentLoginUser(memoryId);
+        DateRange range = resolveDateRange(startDate, endDate, timeRange);
+        LambdaQueryWrapper<InboundManagement> wrapper = new LambdaQueryWrapper<>();
+        applyTenantFilter(wrapper, loginUser.getTenantId(), InboundManagement::getTenantId);
+        wrapper.ge(InboundManagement::getArrivalTime, toDate(range.start()))
+                .lt(InboundManagement::getArrivalTime, toExclusiveEndDate(range.end()))
+                .and(w -> w.notLike(InboundManagement::getStatus, "姝e父")
+                        .notLike(InboundManagement::getStatus, "瀹屾垚")
+                        .notLike(InboundManagement::getStatus, "宸插埌璐�")
+                        .or().like(InboundManagement::getStatus, "寮傚父")
+                        .or().like(InboundManagement::getRemark, "寮傚父")
+                        .or().like(InboundManagement::getRemark, "闂")
+                        .or().like(InboundManagement::getRemark, "寤惰繜")
+                        .or().like(InboundManagement::getRemark, "鐭己"));
+        wrapper.orderByDesc(InboundManagement::getArrivalTime).last("limit " + normalizeLimit(limit));
+
+        List<Map<String, Object>> items = defaultList(inboundManagementMapper.selectList(wrapper)).stream()
+                .map(this::toArrivalItem)
+                .collect(Collectors.toList());
+        return jsonResponse(true, "purchase_arrival_exception_list", "宸茶繑鍥為噰璐埌璐у紓甯歌褰曘��",
+                rangeSummary(range, items.size()), Map.of("items", items), Map.of());
+    }
+
+    @Tool(name = "鏌ヨ寰呬粯娆鹃噰璐崟", value = "鏌ヨ鍚堝悓閲戦澶т簬宸蹭粯娆鹃噾棰濈殑閲囪喘鍗曘��")
+    public String listPendingPaymentOrders(@ToolMemoryId String memoryId,
+                                           @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+                                           @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+                                           @P(value = "鍏抽敭瀛楋紝鍙尮閰嶉噰璐悎鍚屽彿/渚涘簲鍟�/椤圭洰鍚�", required = false) String keyword,
+                                           @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
+        LoginUser loginUser = currentLoginUser(memoryId);
+        DateRange range = resolveDateRange(startDate, endDate, null);
+        List<Map<String, Object>> items = queryLedgers(loginUser, range).stream()
+                .filter(ledger -> matchLedgerKeyword(ledger, keyword))
+                .map(ledger -> toPendingPaymentItem(loginUser, ledger))
+                .filter(Objects::nonNull)
+                .sorted(Comparator.comparing(item -> (BigDecimal) item.get("pendingAmount"), Comparator.reverseOrder()))
+                .limit(normalizeLimit(limit))
+                .collect(Collectors.toList());
+        return jsonResponse(true, "purchase_pending_payment_list", "宸茶繑鍥炲緟浠樻閲囪喘鍗曘��",
+                rangeSummary(range, items.size()), Map.of("items", items), Map.of());
+    }
+
+    @Tool(name = "鏌ヨ閲囪喘閫�璐ф儏鍐�", value = "鎸夋椂闂磋寖鍥存煡璇㈤噰璐��璐у崟鍒楄〃鍜岄��璐ч噾棰濄��")
+    public String listPurchaseReturns(@ToolMemoryId String memoryId,
+                                      @P(value = "寮�濮嬫棩鏈� yyyy-MM-dd", required = false) String startDate,
+                                      @P(value = "缁撴潫鏃ユ湡 yyyy-MM-dd", required = false) String endDate,
+                                      @P(value = "鍏抽敭瀛楋紝鍙尮閰嶉��璐у崟鍙�/澶囨敞", required = false) String keyword,
+                                      @P(value = "杩斿洖鏉℃暟锛岄粯璁�10锛屾渶澶�30", required = false) Integer limit) {
+        LoginUser loginUser = currentLoginUser(memoryId);
+        DateRange range = resolveDateRange(startDate, endDate, null);
+        LambdaQueryWrapper<PurchaseReturnOrders> wrapper = new LambdaQueryWrapper<>();
+        applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), PurchaseReturnOrders::getDeptId);
+        wrapper.ge(PurchaseReturnOrders::getPreparedAt, range.start())
+                .le(PurchaseReturnOrders::getPreparedAt, range.end());
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w.like(PurchaseReturnOrders::getNo, keyword)
+                    .or().like(PurchaseReturnOrders::getRemark, keyword)
+                    .or().like(PurchaseReturnOrders::getReturnUserName, keyword));
+        }
+        wrapper.orderByDesc(PurchaseReturnOrders::getPreparedAt).last("limit " + normalizeLimit(limit));
+
+        List<PurchaseReturnOrders> returns = defaultList(purchaseReturnOrdersMapper.selectList(wrapper));
+        BigDecimal totalAmount = returns.stream()
+                .map(PurchaseReturnOrders::getTotalAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        Map<String, Object> summary = rangeSummary(range, returns.size());
+        summary.put("returnAmount", totalAmount);
+
+        return jsonResponse(true, "purchase_return_list", "宸茶繑鍥為噰璐��璐ф儏鍐点��",
+                summary,
+                Map.of("items", returns.stream().map(this::toReturnItem).collect(Collectors.toList())),
+                Map.of());
+    }
+
+    private List<PurchaseLedger> queryLedgers(LoginUser loginUser, DateRange range) {
+        LambdaQueryWrapper<PurchaseLedger> wrapper = new LambdaQueryWrapper<>();
+        applyTenantFilter(wrapper, loginUser.getTenantId(), PurchaseLedger::getTenantId);
+        wrapper.ge(PurchaseLedger::getEntryDate, toDate(range.start()))
+                .lt(PurchaseLedger::getEntryDate, toExclusiveEndDate(range.end()));
+        return defaultList(purchaseLedgerMapper.selectList(wrapper));
+    }
+
+    private Map<String, Object> rangeSummary(DateRange range, int count) {
+        Map<String, Object> summary = new LinkedHashMap<>();
+        summary.put("timeRange", range.label());
+        summary.put("startDate", range.start().toString());
+        summary.put("endDate", range.end().toString());
+        summary.put("count", count);
+        return summary;
+    }
+
+    private boolean matchLedgerKeyword(PurchaseLedger ledger, String keyword) {
+        if (!StringUtils.hasText(keyword)) {
+            return true;
+        }
+        String text = keyword.trim();
+        return safe(ledger.getPurchaseContractNumber()).contains(text)
+                || safe(ledger.getSupplierName()).contains(text)
+                || safe(ledger.getProjectName()).contains(text);
+    }
+
+    private boolean matchProductKeyword(SalesLedgerProduct product, String keyword) {
+        if (!StringUtils.hasText(keyword)) {
+            return true;
+        }
+        String text = keyword.trim();
+        return safe(product.getProductCategory()).contains(text)
+                || safe(product.getSpecificationModel()).contains(text);
+    }
+
+    private Map<String, Object> toUnstockedItem(SalesLedgerProduct product, PurchaseLedger ledger) {
+        if (product == null || ledger == null || product.getId() == null) {
+            return null;
+        }
+        BigDecimal orderedQuantity = defaultDecimal(product.getQuantity());
+        BigDecimal inboundQuantity = sumInboundQuantity(product.getId());
+        BigDecimal pendingQuantity = orderedQuantity.subtract(inboundQuantity);
+        if (pendingQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return null;
+        }
+        Map<String, Object> item = new LinkedHashMap<>();
+        item.put("purchaseLedgerId", ledger.getId());
+        item.put("purchaseContractNumber", safe(ledger.getPurchaseContractNumber()));
+        item.put("supplierName", safe(ledger.getSupplierName()));
+        item.put("productCategory", safe(product.getProductCategory()));
+        item.put("specificationModel", safe(product.getSpecificationModel()));
+        item.put("unit", safe(product.getUnit()));
+        item.put("orderedQuantity", orderedQuantity);
+        item.put("inboundQuantity", inboundQuantity);
+        item.put("pendingInboundQuantity", pendingQuantity);
+        item.put("entryDate", formatDate(ledger.getEntryDate()));
+        return item;
+    }
+
+    private BigDecimal sumInboundQuantity(Long salesLedgerProductId) {
+        List<ProcurementRecordStorage> records = defaultList(procurementRecordMapper.selectList(new LambdaQueryWrapper<ProcurementRecordStorage>()
+                .eq(ProcurementRecordStorage::getType, 1)
+                .eq(ProcurementRecordStorage::getSalesLedgerProductId, salesLedgerProductId)));
+        return records.stream()
+                .map(ProcurementRecordStorage::getInboundNum)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
+    private Map<String, Object> toArrivalItem(InboundManagement item) {
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("id", item.getId());
+        map.put("orderNo", safe(item.getOrderNo()));
+        map.put("arrivalNo", safe(item.getArrivalNo()));
+        map.put("supplierName", safe(item.getSupplierName()));
+        map.put("status", safe(item.getStatus()));
+        map.put("arrivalTime", formatDate(item.getArrivalTime()));
+        map.put("arrivalQuantity", safe(item.getArrivalQuantity()));
+        map.put("remark", safe(item.getRemark()));
+        return map;
+    }
+
+    private Map<String, Object> toPendingPaymentItem(LoginUser loginUser, PurchaseLedger ledger) {
+        BigDecimal contractAmount = defaultDecimal(ledger.getContractAmount());
+        BigDecimal paidAmount = sumPaymentAmount(loginUser, ledger.getId());
+        BigDecimal pendingAmount = contractAmount.subtract(paidAmount);
+        if (pendingAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            return null;
+        }
+        Map<String, Object> item = toLedgerItem(ledger);
+        item.put("paidAmount", paidAmount);
+        item.put("pendingAmount", pendingAmount);
+        return item;
+    }
+
+    private BigDecimal sumPaymentAmount(LoginUser loginUser, Long purchaseLedgerId) {
+        LambdaQueryWrapper<PaymentRegistration> wrapper = new LambdaQueryWrapper<>();
+        applyTenantFilter(wrapper, loginUser.getTenantId(), PaymentRegistration::getTenantId);
+        wrapper.eq(PaymentRegistration::getPurchaseLedgerId, purchaseLedgerId);
+        return defaultList(paymentRegistrationMapper.selectList(wrapper)).stream()
+                .map(PaymentRegistration::getCurrentPaymentAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
+    private Map<String, Object> toReturnItem(PurchaseReturnOrders item) {
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("id", item.getId());
+        map.put("no", safe(item.getNo()));
+        map.put("returnType", item.getReturnType());
+        map.put("purchaseLedgerId", item.getPurchaseLedgerId());
+        map.put("preparedAt", item.getPreparedAt() == null ? "" : item.getPreparedAt().toString());
+        map.put("returnUserName", safe(item.getReturnUserName()));
+        map.put("totalAmount", item.getTotalAmount());
+        map.put("remark", safe(item.getRemark()));
+        return map;
+    }
+
+    private BigDecimal defaultDecimal(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value;
+    }
+
+    private List<PaymentRegistration> queryPayments(LoginUser loginUser, DateRange range) {
+        LambdaQueryWrapper<PaymentRegistration> wrapper = new LambdaQueryWrapper<>();
+        applyTenantFilter(wrapper, loginUser.getTenantId(), PaymentRegistration::getTenantId);
+        wrapper.ge(PaymentRegistration::getPaymentDate, toDate(range.start()))
+                .lt(PaymentRegistration::getPaymentDate, toExclusiveEndDate(range.end()));
+        return defaultList(paymentRegistrationMapper.selectList(wrapper));
+    }
+
+    private List<InvoicePurchase> queryInvoices(LoginUser loginUser, DateRange range) {
+        LambdaQueryWrapper<InvoicePurchase> wrapper = new LambdaQueryWrapper<>();
+        applyTenantFilter(wrapper, loginUser.getTenantId(), InvoicePurchase::getTenantId);
+        wrapper.ge(InvoicePurchase::getIssueDate, range.start())
+                .le(InvoicePurchase::getIssueDate, range.end());
+        return defaultList(invoicePurchaseMapper.selectList(wrapper));
+    }
+
+    private List<PurchaseReturnOrders> queryReturns(LoginUser loginUser, DateRange range) {
+        LambdaQueryWrapper<PurchaseReturnOrders> wrapper = new LambdaQueryWrapper<>();
+        applyDeptFilter(wrapper, loginUser.getCurrentDeptId(), PurchaseReturnOrders::getDeptId);
+        wrapper.ge(PurchaseReturnOrders::getPreparedAt, range.start())
+                .le(PurchaseReturnOrders::getPreparedAt, range.end());
+        return defaultList(purchaseReturnOrdersMapper.selectList(wrapper));
+    }
+
+    private Map<String, Object> toLedgerItem(PurchaseLedger item) {
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("id", item.getId());
+        map.put("purchaseContractNumber", safe(item.getPurchaseContractNumber()));
+        map.put("supplierName", safe(item.getSupplierName()));
+        map.put("projectName", safe(item.getProjectName()));
+        map.put("entryDate", formatDate(item.getEntryDate()));
+        map.put("contractAmount", item.getContractAmount());
+        map.put("approvalStatus", item.getApprovalStatus());
+        map.put("paymentMethod", safe(item.getPaymentMethod()));
+        return map;
+    }
+
+    private DateRange resolveDateRange(String startDate, String endDate, String timeRange) {
+        LocalDate today = LocalDate.now();
+        LocalDate start = parseLocalDate(startDate);
+        LocalDate end = parseLocalDate(endDate);
+        if (start != null || end != null) {
+            LocalDate s = start != null ? start : end;
+            LocalDate e = end != null ? end : start;
+            if (s.isAfter(e)) {
+                LocalDate temp = s;
+                s = e;
+                e = temp;
+            }
+            return new DateRange(s, e, s + "鑷�" + e);
+        }
+        if (!StringUtils.hasText(timeRange)) {
+            return new DateRange(today.minusDays(29), today, "杩�30澶�");
+        }
+        String text = timeRange.trim();
+        if (text.contains("浠婂勾") || text.contains("鏈勾")) {
+            return new DateRange(today.withDayOfYear(1), today, "浠婂勾");
+        }
+        if (text.contains("鏈湀")) {
+            return new DateRange(today.withDayOfMonth(1), today, "鏈湀");
+        }
+        if (text.contains("涓婃湀")) {
+            LocalDate first = today.minusMonths(1).withDayOfMonth(1);
+            LocalDate last = first.withDayOfMonth(first.lengthOfMonth());
+            return new DateRange(first, last, "涓婃湀");
+        }
+        if (text.contains("杩戝崐骞�") || text.contains("鏈�杩戝崐骞�")) {
+            return new DateRange(today.minusMonths(6).plusDays(1), today, "杩戝崐骞�");
+        }
+        if (text.contains("杩戝崐涓湀") || text.contains("鏈�杩戝崐涓湀") || text.contains("鍗婁釜鏈�")) {
+            return new DateRange(today.minusDays(14), today, "杩戝崐涓湀");
+        }
+        java.util.regex.Matcher relativeMatcher = java.util.regex.Pattern.compile("(杩憒鏈�杩�)(\\d+)(澶﹟鍛▅涓湀|鏈坾骞�)").matcher(text);
+        if (relativeMatcher.find()) {
+            int amount = Integer.parseInt(relativeMatcher.group(2));
+            String unit = relativeMatcher.group(3);
+            LocalDate relativeStart = switch (unit) {
+                case "澶�" -> today.minusDays(Math.max(amount - 1L, 0));
+                case "鍛�" -> today.minusWeeks(Math.max(amount, 1)).plusDays(1);
+                case "涓湀", "鏈�" -> today.minusMonths(Math.max(amount, 1)).plusDays(1);
+                case "骞�" -> today.minusYears(Math.max(amount, 1)).plusDays(1);
+                default -> today.minusDays(29);
+            };
+            return new DateRange(relativeStart, today, "杩�" + amount + unit);
+        }
+        return new DateRange(today.minusDays(29), today, "杩�30澶�");
+    }
+
+    private LocalDate parseLocalDate(String text) {
+        if (!StringUtils.hasText(text)) {
+            return null;
+        }
+        return LocalDate.parse(text.trim(), DATE_FMT);
+    }
+
+    private Date toDate(LocalDate localDate) {
+        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+    }
+
+    private Date toExclusiveEndDate(LocalDate localDate) {
+        return Date.from(localDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
+    }
+
+    private String formatDate(Date date) {
+        if (date == null) {
+            return "";
+        }
+        return DATE_FMT.format(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
+    }
+
+    private boolean tenantMatched(Long dataTenantId, Long userTenantId) {
+        if (userTenantId == null) {
+            return true;
+        }
+        return Objects.equals(dataTenantId, userTenantId);
+    }
+
+    private <T> void applyTenantFilter(LambdaQueryWrapper<T> wrapper, Long tenantId, com.baomidou.mybatisplus.core.toolkit.support.SFunction<T, Long> field) {
+        if (tenantId != null) {
+            wrapper.eq(field, tenantId);
+        }
+    }
+
+    private <T> void applyDeptFilter(LambdaQueryWrapper<T> wrapper, Long deptId, com.baomidou.mybatisplus.core.toolkit.support.SFunction<T, Long> field) {
+        if (deptId != null) {
+            wrapper.eq(field, deptId);
+        }
+    }
+
+    private LoginUser currentLoginUser(String memoryId) {
+        LoginUser loginUser = aiSessionUserContext.get(memoryId);
+        if (loginUser != null) {
+            return loginUser;
+        }
+        return SecurityUtils.getLoginUser();
+    }
+
+    private int normalizeLimit(Integer limit) {
+        if (limit == null || limit <= 0) {
+            return DEFAULT_LIMIT;
+        }
+        return Math.min(limit, MAX_LIMIT);
+    }
+
+    private String safe(Object value) {
+        return value == null ? "" : String.valueOf(value).replace('\n', ' ').replace('\r', ' ');
+    }
+
+    private <T> List<T> defaultList(List<T> list) {
+        return list == null ? List.of() : list;
+    }
+
+    private String jsonResponse(boolean success,
+                                String type,
+                                String description,
+                                Map<String, Object> summary,
+                                Map<String, Object> data,
+                                Map<String, Object> charts) {
+        Map<String, Object> result = new LinkedHashMap<>();
+        result.put("success", success);
+        result.put("type", type);
+        result.put("description", description);
+        result.put("summary", summary == null ? Map.of() : summary);
+        result.put("data", data == null ? Map.of() : data);
+        result.put("charts", charts == null ? Map.of() : charts);
+        return JSON.toJSONString(result);
+    }
+
+    private record DateRange(LocalDate start, LocalDate end, String label) {
+    }
+
+    private static class MaterialRankItem {
+        private final String productCategory;
+        private final String specificationModel;
+        private final String unit;
+        private BigDecimal quantity = BigDecimal.ZERO;
+        private BigDecimal amount = BigDecimal.ZERO;
+
+        private MaterialRankItem(String productCategory, String specificationModel, String unit) {
+            this.productCategory = productCategory;
+            this.specificationModel = specificationModel;
+            this.unit = unit;
+        }
+
+        private Map<String, Object> toMap() {
+            Map<String, Object> map = new LinkedHashMap<>();
+            map.put("productCategory", productCategory);
+            map.put("specificationModel", specificationModel);
+            map.put("unit", unit);
+            map.put("quantity", quantity);
+            map.put("amount", amount);
+            return map;
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java
new file mode 100644
index 0000000..d7acc4d
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApproveNodeDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ruoyi.approve.pojo.ApproveNode;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApproveNodeDto extends ApproveNode {
+
+
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/dto/ApproveProcessConfigNodeDto.java b/src/main/java/com/ruoyi/approve/bean/dto/ApproveProcessConfigNodeDto.java
new file mode 100644
index 0000000..0d4c34a
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/dto/ApproveProcessConfigNodeDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.approve.bean.dto;
+
+import com.ruoyi.approve.pojo.ApproveProcessConfigNode;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApproveProcessConfigNodeDto  extends ApproveProcessConfigNode {
+
+    private List<ApproveProcessConfigNode>  approveProcessConfigNodes;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java
new file mode 100644
index 0000000..f43ecac
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApproveGetAndUpdateVo.java
@@ -0,0 +1,57 @@
+package com.ruoyi.approve.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class ApproveGetAndUpdateVo {
+
+    private List<String> tempFileIds;
+    //瀹℃壒id
+    @NotBlank(message = "娴佺▼缂栧彿涓嶈兘涓虹┖")
+    private String id;
+    //鐢宠浜嬬敱
+    @NotBlank(message = "鐢宠浜嬬敱涓嶈兘涓虹┖")
+    private String approveReason;
+
+    private String approveUserIds;
+
+    private String approveDeptName;
+
+    private Long approveUser;
+
+    private String approveTime;
+
+    private Integer approveStatus;
+
+    @Excel(name = "寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd",width = 30)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Schema(description = "寮�濮嬫椂闂�")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date startDate;
+
+    @Excel(name = "缁撴潫鏃堕棿", dateFormat = "yyyy-MM-dd",width = 30)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Schema(description = "缁撴潫鏃堕棿")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endDate;
+
+    private BigDecimal price;
+
+    private String location;
+    /**
+     * 瀹℃壒绫诲瀷
+     */
+    private Integer approveType;
+
+    private List<StorageBlobDTO> storageBlobDTOS;
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessConfigNodeVo.java b/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessConfigNodeVo.java
new file mode 100644
index 0000000..fb92c55
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessConfigNodeVo.java
@@ -0,0 +1,9 @@
+package com.ruoyi.approve.bean.vo;
+
+import com.ruoyi.approve.pojo.ApproveProcessConfigNode;
+import lombok.Data;
+
+@Data
+public class ApproveProcessConfigNodeVo extends ApproveProcessConfigNode {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java b/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java
new file mode 100644
index 0000000..56d420e
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/bean/vo/ApproveProcessVO.java
@@ -0,0 +1,79 @@
+package com.ruoyi.approve.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class ApproveProcessVO {
+    /**
+     * 涓存椂鏂囦欢id鍒楄〃
+     */
+    private List<String> tempFileIds;
+    /**
+     * 瀹℃壒娴佺▼id
+     */
+    private Long id;
+
+    private String approveId;
+    /**
+     * 瀹℃壒閮ㄩ棬id
+     */
+    private Long approveDeptId;
+    /**
+     * 瀹℃壒鏃堕棿
+     */
+    private String approveTime;
+    /**
+     * 鐢宠浜篿d
+     */
+    // 鐢宠浜�
+    private Long approveUser;
+    /**
+     * 瀹℃壒浜篿d鍒楄〃
+     */
+    // 瀹℃壒浜�
+    private String approveUserIds;
+    /**
+     * 瀹℃壒鐞嗙敱
+     */
+    private String approveReason;
+
+    @Excel(name = "寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd",width = 30)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Schema(description = "寮�濮嬫椂闂�")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date startDate;
+
+    @Excel(name = "缁撴潫鏃堕棿", dateFormat = "yyyy-MM-dd",width = 30)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Schema(description = "缁撴潫鏃堕棿")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date endDate;
+
+    private BigDecimal price;
+
+    private String location;
+
+    /**
+     * 瀹℃壒绫诲瀷
+     */
+    private Integer approveType;
+     /**
+     * 璁惧鎶ヤ慨id
+     */
+    private Long deviceRepairId;
+     /**
+     * 鎶ヤ慨閲戦
+     */
+    private BigDecimal maintenancePrice;
+
+    private List<StorageBlobDTO> storageBlobDTOList;
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java b/src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java
index 5cda3a3..d0af196 100644
--- a/src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java
+++ b/src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java
@@ -3,19 +3,20 @@
 import com.ruoyi.approve.pojo.ApproveNode;
 import com.ruoyi.approve.service.IApproveNodeService;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
 
-@Api(tags = "瀹℃壒璁板綍")
+@Tag(name = "瀹℃壒璁板綍")
 @RestController
 @RequestMapping("/approveNode")
+@AllArgsConstructor
 public class ApproveNodeController {
-    @Autowired
+
     private IApproveNodeService approveNodeService;
 
     /**
@@ -24,7 +25,7 @@
      * @return
      */
     @GetMapping("/details/{id}")
-    @ApiOperation(value = "娴佺▼鐘舵�佽鎯�")
+    @Operation(summary = "娴佺▼鐘舵�佽鎯�")
     public AjaxResult details(@PathVariable String id) {
         return AjaxResult.success(approveNodeService.details(id));
     }
@@ -36,7 +37,7 @@
      */
     @PostMapping("/updateApproveNode")
     @Transactional(rollbackFor = Exception.class)
-    @ApiOperation(value = "瀹℃壒鑺傜偣")
+    @Operation(summary = "瀹℃壒鑺傜偣")
     public AjaxResult updateApproveNode(@RequestBody ApproveNode approveNode) throws IOException {
         approveNodeService.updateApproveNode(approveNode);
         return AjaxResult.success();
diff --git a/src/main/java/com/ruoyi/approve/controller/ApproveProcessConfigNodeController.java b/src/main/java/com/ruoyi/approve/controller/ApproveProcessConfigNodeController.java
new file mode 100644
index 0000000..b837af6
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/controller/ApproveProcessConfigNodeController.java
@@ -0,0 +1,49 @@
+package com.ruoyi.approve.controller;
+
+import com.ruoyi.approve.pojo.ApproveProcessConfigNode;
+import com.ruoyi.approve.service.ApproveProcessConfigNodeService;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒娴佺▼閰嶇疆鑺傜偣琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-23 10:21:41
+ */
+@RestController
+@RequestMapping("/approveProcessConfigNode")
+@AllArgsConstructor
+public class ApproveProcessConfigNodeController {
+
+    private final ApproveProcessConfigNodeService approveProcessConfigNodeService;
+
+
+    /**
+     *  鏌ヨ瀹℃壒涓嬮潰鐨勮妭鐐�
+     * @param type
+     * @return
+     */
+    @GetMapping("/list")
+    public R listNode(Integer type) {
+        return R.ok(approveProcessConfigNodeService.listNode(type));
+    }
+
+    /**
+     * 娣诲姞瀹℃壒鑺傜偣
+     * @param approveProcessConfigNodes
+     * @return
+     */
+    @ApiOperation("娣诲姞瀹℃壒鑺傜偣")
+    @PostMapping("/add")
+    public R addApproveProcessConfigNodes(@RequestBody List<ApproveProcessConfigNode> approveProcessConfigNodes) {
+        return R.ok(approveProcessConfigNodeService.addApproveProcessConfigNodes(approveProcessConfigNodes));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java b/src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java
index 7554ff4..ed02564 100644
--- a/src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java
+++ b/src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java
@@ -2,40 +2,31 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.AccountExpense;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.approve.service.IApproveProcessService;
-import com.ruoyi.approve.vo.ApproveGetAndUpdateVo;
-import com.ruoyi.approve.vo.ApproveProcessVO;
+import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo;
+import com.ruoyi.approve.bean.vo.ApproveProcessVO;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.domain.SysDept;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-import java.text.ParseException;
 import java.util.List;
 
 @RestController
 @RequestMapping("/approveProcess")
-@Api(tags = "瀹℃壒")
+@AllArgsConstructor
+@Tag(name = "瀹℃壒")
 public class ApproveProcessController {
 
-    @GetMapping("/test")
-    public AjaxResult test() {
-        System.out.println(1111);
-        return AjaxResult.success("娴嬭瘯");
-    }
-
-
-    @Autowired
     private IApproveProcessService approveProcessService;
     /**銆�
      * 鑾峰彇閮ㄩ棬鍒楄〃
@@ -58,7 +49,7 @@
      */
     @PostMapping("/add")
     @Transactional(rollbackFor = Exception.class)
-    @ApiOperation(value = "娣诲姞瀹℃壒")
+    @Operation(summary = "娣诲姞瀹℃壒")
     public AjaxResult add(@RequestBody ApproveProcessVO approveProcessVO) throws Exception {
         if (approveProcessVO == null) {
             return AjaxResult.warn("鍙傛暟涓嶈兘涓虹┖");
@@ -74,7 +65,7 @@
      * @return
      */
     @GetMapping("/get")
-    @ApiOperation(value = "瀹℃壒璇︽儏")
+    @Operation(summary = "瀹℃壒璇︽儏")
     public AjaxResult get(ApproveGetAndUpdateVo approveGetAndUpdateVo){
         if (approveGetAndUpdateVo.getId() == null || approveGetAndUpdateVo.getId().isEmpty()) {
             return AjaxResult.warn("鍙傛暟涓嶈兘涓虹┖");
@@ -89,7 +80,7 @@
      */
     @PostMapping("/update")
     @Transactional(rollbackFor = Exception.class)
-    @ApiOperation(value = "鏇存柊瀹℃壒")
+    @Operation(summary = "鏇存柊瀹℃壒")
     public AjaxResult update(@RequestBody ApproveGetAndUpdateVo approveGetAndUpdateVo) throws IOException {
         if (approveGetAndUpdateVo == null) {
             return AjaxResult.warn("鍙傛暟涓嶈兘涓虹┖");
@@ -102,7 +93,7 @@
      * @return
      */
     @GetMapping("/list")
-    @ApiOperation(value = "鑾峰彇瀹℃壒鍒楄〃")
+    @Operation(summary = "鑾峰彇瀹℃壒鍒楄〃")
     public AjaxResult list(Page page, ApproveProcess approveProcess) {
         return AjaxResult.success(approveProcessService.listAll(page, approveProcess));
     }
@@ -113,7 +104,7 @@
      * @return
      */
     @DeleteMapping("/deleteIds")
-    @ApiOperation(value = "鍒犻櫎瀹℃壒")
+    @Operation(summary = "鍒犻櫎瀹℃壒")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult deleteIds(@RequestBody List<Long> ids) {
         if (ids == null || ids.size() == 0) {
@@ -123,7 +114,7 @@
         return AjaxResult.success("鎿嶄綔鎴愬姛");
     }
 
-    @ApiOperation(value = "鍏嚭绠$悊瀵煎嚭")
+    @Operation(summary = "鍏嚭绠$悊瀵煎嚭")
     @PostMapping("/exportOne")
     public void exportOne(HttpServletResponse response) {
         List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
@@ -133,7 +124,7 @@
         util.exportExcel(response, accountExpenses, "鍏嚭绠$悊瀵煎嚭");
     }
 
-    @ApiOperation(value = "璇峰亣绠$悊瀵煎嚭")
+    @Operation(summary = "璇峰亣绠$悊瀵煎嚭")
     @PostMapping("/exportTwo")
     public void exportTwo(HttpServletResponse response) {
         List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
@@ -143,7 +134,7 @@
         util.exportExcel(response, accountExpenses, "璇峰亣绠$悊瀵煎嚭");
     }
 
-    @ApiOperation(value = "鍑哄樊绠$悊瀵煎嚭")
+    @Operation(summary = "鍑哄樊绠$悊瀵煎嚭")
     @PostMapping("/exportThree")
     public void exportThree(HttpServletResponse response) {
         List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
@@ -153,7 +144,7 @@
         util.exportExcel(response, accountExpenses, "鍑哄樊绠$悊瀵煎嚭");
     }
 
-    @ApiOperation(value = "鎶ラ攢绠$悊瀵煎嚭")
+    @Operation(summary = "鎶ラ攢绠$悊瀵煎嚭")
     @PostMapping("/exportFour")
     public void exportFour(HttpServletResponse response) {
         List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
@@ -163,7 +154,7 @@
         util.exportExcel(response, accountExpenses, "鎶ラ攢绠$悊瀵煎嚭");
     }
 
-    @ApiOperation(value = "閲囪喘鐢宠瀵煎嚭")
+    @Operation(summary = "閲囪喘鐢宠瀵煎嚭")
     @PostMapping("/exportFive")
     public void exportFive(HttpServletResponse response) {
         List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
@@ -173,7 +164,7 @@
         util.exportExcel(response, accountExpenses, "閲囪喘鐢宠瀵煎嚭");
     }
 
-    @ApiOperation(value = "鍗忓悓瀹℃壒瀵煎嚭")
+    @Operation(summary = "鍗忓悓瀹℃壒瀵煎嚭")
     @PostMapping("/exportZero")
     public void exportZero(HttpServletResponse response) {
         List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
@@ -183,7 +174,7 @@
         util.exportExcel(response, accountExpenses, "鍗忓悓瀹℃壒瀵煎嚭");
     }
 
-    @ApiOperation(value = "鍗遍櫓浣滀笟瀹℃壒瀵煎嚭")
+    @Operation(summary = "鍗遍櫓浣滀笟瀹℃壒瀵煎嚭")
     @PostMapping("/exportEight")
     public void exportEight(HttpServletResponse response) {
         List<ApproveProcess> accountExpenses = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
diff --git a/src/main/java/com/ruoyi/approve/controller/HolidaySettingsController.java b/src/main/java/com/ruoyi/approve/controller/HolidaySettingsController.java
index 2ecf29f..97abe9f 100644
--- a/src/main/java/com/ruoyi/approve/controller/HolidaySettingsController.java
+++ b/src/main/java/com/ruoyi/approve/controller/HolidaySettingsController.java
@@ -18,13 +18,9 @@
 @RequestMapping("/holidaySettings")
 @AllArgsConstructor
 public class HolidaySettingsController {
-    @Autowired
     private HolidaySettingsService holidaySettingsService;
-    @Autowired
     private AnnualLeaveSettingMapper annualLeaveSettingMapper;
-    @Autowired
     private OvertimeSettingMapper overtimeSettingMapper;
-    @Autowired
     private WorkingHoursSettingMapper workingHoursSettingMapper;
 
     /**銆�
diff --git a/src/main/java/com/ruoyi/approve/controller/KnowledgeBaseController.java b/src/main/java/com/ruoyi/approve/controller/KnowledgeBaseController.java
index b6ede4a..3ebb782 100644
--- a/src/main/java/com/ruoyi/approve/controller/KnowledgeBaseController.java
+++ b/src/main/java/com/ruoyi/approve/controller/KnowledgeBaseController.java
@@ -2,27 +2,23 @@
 
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.approve.mapper.KnowledgeBaseMapper;
 import com.ruoyi.approve.pojo.KnowledgeBase;
-import com.ruoyi.approve.pojo.RpaProcessAutomation;
 import com.ruoyi.approve.service.KnowledgeBaseService;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/knowledgeBase")
 @AllArgsConstructor
-@Api(tags = "鐭ヨ瘑搴撶鐞�")
+@Tag(name = "鐭ヨ瘑搴撶鐞�")
 public class KnowledgeBaseController {
-    @Autowired
     private KnowledgeBaseService knowledgeBaseService;
 
     /**銆�
@@ -61,7 +57,7 @@
         return AjaxResult.success(knowledgeBaseService.removeByIds(ids));
     }
 
-    @ApiOperation(value = "鐭ヨ瘑搴撶鐞嗗鍑�")
+    @Operation(summary = "鐭ヨ瘑搴撶鐞嗗鍑�")
     @PostMapping("/export")
     public void export(HttpServletResponse response) {
         List<KnowledgeBase> accountExpenses = knowledgeBaseService.list();
diff --git a/src/main/java/com/ruoyi/approve/controller/NotificationManagementController.java b/src/main/java/com/ruoyi/approve/controller/NotificationManagementController.java
index e3ac566..a1796f8 100644
--- a/src/main/java/com/ruoyi/approve/controller/NotificationManagementController.java
+++ b/src/main/java/com/ruoyi/approve/controller/NotificationManagementController.java
@@ -19,11 +19,8 @@
 @RequestMapping("/notificationManagement")
 @AllArgsConstructor
 public class NotificationManagementController {
-    @Autowired
     private NotificationManagementService notificationManagementService ;
-    @Autowired
     private OnlineMeetingMapper onlineMeetingMapper;
-    @Autowired
     private FileSharingMapper fileSharingMapper;
     /**銆�
      * 鑾峰彇鍒楄〃
diff --git a/src/main/java/com/ruoyi/approve/controller/RpaProcessAutomationController.java b/src/main/java/com/ruoyi/approve/controller/RpaProcessAutomationController.java
index e8c35f9..06a0f6d 100644
--- a/src/main/java/com/ruoyi/approve/controller/RpaProcessAutomationController.java
+++ b/src/main/java/com/ruoyi/approve/controller/RpaProcessAutomationController.java
@@ -1,31 +1,24 @@
 package com.ruoyi.approve.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.approve.pojo.RpaProcessAutomation;
 import com.ruoyi.approve.service.RpaProcessAutomationService;
-import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysDept;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/rpaProcessAutomation")
 @AllArgsConstructor
-@Api(tags = "RPA娴佺▼鑷姩鍖�")
+@Tag(name = "RPA娴佺▼鑷姩鍖�")
 public class RpaProcessAutomationController {
-    @Autowired
     private RpaProcessAutomationService rpaProcessAutomationService;
     /**銆�
      * 鑾峰彇鍒楄〃
@@ -63,7 +56,7 @@
         return AjaxResult.success(rpaProcessAutomationService.removeByIds(ids));
     }
 
-    @ApiOperation(value = "RPA娴佺▼鑷姩鍖栧鍑�")
+    @Operation(summary = "RPA娴佺▼鑷姩鍖栧鍑�")
     @PostMapping("/export")
     public void export(HttpServletResponse response) {
         List<RpaProcessAutomation> accountExpenses = rpaProcessAutomationService.list();
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApproveProcessConfigNodeMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApproveProcessConfigNodeMapper.java
new file mode 100644
index 0000000..5dbb393
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/mapper/ApproveProcessConfigNodeMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.approve.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.approve.pojo.ApproveProcessConfigNode;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 瀹℃壒娴佺▼閰嶇疆鑺傜偣琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-23 10:21:41
+ */
+@Mapper
+public interface ApproveProcessConfigNodeMapper extends BaseMapper<ApproveProcessConfigNode> {
+
+}
diff --git a/src/main/java/com/ruoyi/approve/mapper/ApproveProcessMapper.java b/src/main/java/com/ruoyi/approve/mapper/ApproveProcessMapper.java
index bddde19..513926f 100644
--- a/src/main/java/com/ruoyi/approve/mapper/ApproveProcessMapper.java
+++ b/src/main/java/com/ruoyi/approve/mapper/ApproveProcessMapper.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.approve.vo.ApproveProcessVo;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -16,7 +17,7 @@
 @Mapper
 public interface ApproveProcessMapper extends BaseMapper<ApproveProcess> {
 
-    IPage<ApproveProcess> listPage(Page page,@Param("req") ApproveProcess approveProcess);
+    IPage<ApproveProcessVo> listPage(Page page, @Param("req") ApproveProcess approveProcess);
 }
 
 
diff --git a/src/main/java/com/ruoyi/approve/pojo/AnnualLeaveSetting.java b/src/main/java/com/ruoyi/approve/pojo/AnnualLeaveSetting.java
index 2097b30..61d551e 100644
--- a/src/main/java/com/ruoyi/approve/pojo/AnnualLeaveSetting.java
+++ b/src/main/java/com/ruoyi/approve/pojo/AnnualLeaveSetting.java
@@ -67,4 +67,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApproveLog.java b/src/main/java/com/ruoyi/approve/pojo/ApproveLog.java
index 8952e0d..379dee8 100644
--- a/src/main/java/com/ruoyi/approve/pojo/ApproveLog.java
+++ b/src/main/java/com/ruoyi/approve/pojo/ApproveLog.java
@@ -1,5 +1,8 @@
 package com.ruoyi.approve.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -54,4 +57,11 @@
      */
     private String approveRemark;
 
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java b/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java
index 2ea7dd5..907f3dc 100644
--- a/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java
+++ b/src/main/java/com/ruoyi/approve/pojo/ApproveNode.java
@@ -1,18 +1,16 @@
 package com.ruoyi.approve.pojo;
 
-import java.io.Serializable;
-import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.List;
-
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.sales.pojo.CommonFile;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
 
 /**
  * 瀹℃壒鑺傜偣琛�
@@ -20,20 +18,20 @@
  */
 @Data
 @TableName("approve_node")
-@ApiModel
+@Schema
 public class ApproveNode{
 
 
-    @ApiModelProperty("闄勪欢id")
+    @Schema(description = "闄勪欢id")
     @TableField(exist = false)
     private List<String> tempFileIds;
 
     @TableField(exist = false)
-    @ApiModelProperty("闄勪欢鍒楄〃")
+    @Schema(description = "闄勪欢鍒楄〃")
     private String url;
 
     /**
-     * 
+     *
      */
     private Long id;
 
@@ -128,4 +126,10 @@
     private static final long serialVersionUID = 1L;
 
 
-}
\ No newline at end of file
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @TableField(exist = false)
+    private List<StorageBlobDTO> storageBlobDTOS;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java b/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
index 808199f..bd56b0f 100644
--- a/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
+++ b/src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java
@@ -1,19 +1,18 @@
 package com.ruoyi.approve.pojo;
 
-import java.io.Serializable;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.sales.pojo.CommonFile;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.sales.pojo.CommonFile;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * 瀹℃壒娴佺▼琛�
@@ -21,7 +20,7 @@
  */
 @Data
 @TableName("approve_process")
-@ApiModel
+@Schema
 public class ApproveProcess{
     /**
      *
@@ -35,7 +34,7 @@
     /**
      * 娴佺▼缂栧彿
      */
-    @ApiModelProperty(value = "娴佺▼缂栧彿")
+    @Schema(description = "娴佺▼缂栧彿")
     @Excel(name = "娴佺▼缂栧彿")
     private String approveId;
 
@@ -47,7 +46,7 @@
     /**
      * 鐢宠浜哄悕绉�
      */
-    @ApiModelProperty(value = "鐢宠浜哄悕绉�")
+    @Schema(description = "鐢宠浜哄悕绉�")
     @Excel(name = "鐢宠浜�")
     private String approveUserName;
 
@@ -59,7 +58,7 @@
     /**
      * 鐢宠閮ㄩ棬鍚嶇О
      */
-    @ApiModelProperty(value = "鐢宠閮ㄩ棬鍚嶇О")
+    @Schema(description = "鐢宠閮ㄩ棬鍚嶇О")
     @Excel(name = "鐢宠閮ㄩ棬")
     private String approveDeptName;
 
@@ -76,7 +75,7 @@
     /**
      * 鐢宠鍘熷洜
      */
-    @ApiModelProperty(value = "鐢宠鍘熷洜")
+    @Schema(description = "鐢宠鍘熷洜")
     @Excel(name = "瀹℃壒浜嬬敱")
     private String approveReason;
 
@@ -88,7 +87,7 @@
     /**
      * 褰撳墠瀹℃壒鐢ㄦ埛鍚嶇О
      */
-    @ApiModelProperty(value = "褰撳墠瀹℃壒浜�")
+    @Schema(description = "褰撳墠瀹℃壒浜�")
     @Excel(name = "褰撳墠瀹℃壒浜�")
     private String approveUserCurrentName;
 
@@ -96,7 +95,7 @@
      * 鐢宠鏃ユ湡
      */
     @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "鐢宠鏃ユ湡")
+    @Schema(description = "鐢宠鏃ユ湡")
     @Excel(name = "鐢宠鏃ユ湡" ,dateFormat = "yyyy-MM-dd")
     private Date approveTime;
 
@@ -104,14 +103,14 @@
      * 瀹℃壒瀹屾垚鏃堕棿
      */
     @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "瀹℃壒瀹屾垚鏃堕棿")
+    @Schema(description = "瀹℃壒瀹屾垚鏃堕棿")
     @Excel(name = "缁撴潫鏃ユ湡" ,dateFormat = "yyyy-MM-dd")
     private Date approveOverTime;
 
     /**
      * 瀹℃壒鐘舵�侊細0寰呭鏍革紝1瀹℃牳涓紝2瀹℃牳瀹屾垚 3瀹℃牳鏈�氳繃 4宸查噸鏂版彁浜�
      */
-    @ApiModelProperty(value = "瀹℃壒鐘舵�侊細0寰呭鏍革紝1瀹℃牳涓紝2瀹℃牳瀹屾垚 3瀹℃牳鏈�氳繃 4宸查噸鏂版彁浜�")
+    @Schema(description = "瀹℃壒鐘舵�侊細0寰呭鏍革紝1瀹℃牳涓紝2瀹℃牳瀹屾垚 3瀹℃牳鏈�氳繃 4宸查噸鏂版彁浜�")
     @Excel(name = "瀹℃壒鐘舵��", readConverterExp = "0=寰呭鏍�,1=瀹℃牳涓�,2=瀹℃牳瀹屾垚,3=瀹℃牳鏈�氳繃,4=宸查噸鏂版彁浜�")
     private Integer approveStatus;
 
@@ -137,18 +136,18 @@
     /**
      * 瀹℃壒澶囨敞
      */
-    @ApiModelProperty(value = "瀹℃壒澶囨敞")
+    @Schema(description = "瀹℃壒澶囨敞")
     private String approveRemark;
 
     @Excel(name = "寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd",width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
+    @Schema(description = "寮�濮嬫椂闂�")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date startDate;
 
     @Excel(name = "缁撴潫鏃堕棿", dateFormat = "yyyy-MM-dd",width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
+    @Schema(description = "缁撴潫鏃堕棿")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date endDate;
 
@@ -171,4 +170,14 @@
     private static final long serialVersionUID = 1L;
 
 
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @TableField(exist = false)
+    private List<StorageBlobVO> storageBlobVOS;
+
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/ApproveProcessConfigNode.java b/src/main/java/com/ruoyi/approve/pojo/ApproveProcessConfigNode.java
new file mode 100644
index 0000000..bcb3635
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/pojo/ApproveProcessConfigNode.java
@@ -0,0 +1,118 @@
+package com.ruoyi.approve.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 瀹℃壒娴佺▼閰嶇疆鑺傜偣琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-23 10:21:41
+ */
+@Getter
+@Setter
+@ToString
+@TableName("approve_process_config_node")
+@ApiModel(value = "ApproveProcessConfigNode瀵硅薄", description = "瀹℃壒娴佺▼閰嶇疆鑺傜偣琛�")
+public class ApproveProcessConfigNode implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭ID
+     */
+    @ApiModelProperty("涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+
+
+    //  '瀹℃壒绫诲瀷锛�1鍏嚭绠$悊锛�2璇峰亣绠$悊锛�3鍑哄樊绠$悊锛�4鎶ラ攢绠$悊锛�5閲囪喘瀹℃壒锛�6鎶ヤ环瀹℃壒锛�7鍙戣揣瀹℃壒锛�8鍗遍櫓浣滀笟瀹℃壒',
+    @ApiModelProperty("瀹℃壒绫诲瀷锛�1鍏嚭绠$悊锛�2璇峰亣绠$悊锛�3鍑哄樊绠$悊锛�4鎶ラ攢绠$悊锛�5閲囪喘瀹℃壒锛�6鎶ヤ环瀹℃壒锛�7鍙戣揣瀹℃壒锛�8鍗遍櫓浣滀笟瀹℃壒")
+    private Integer approveType;
+    /**
+     * 鑺傜偣椤哄簭
+     */
+    @ApiModelProperty("鑺傜偣椤哄簭")
+    private Integer nodeOrder;
+
+
+    /**
+     * 瀹℃壒浜篒Ds锛堝涓敤閫楀彿鍒嗛殧锛�
+     */
+    @ApiModelProperty("瀹℃壒浜篒D")
+    private Long approverId;
+
+    /**
+     * 瀹℃壒浜哄悕绉�
+     */
+    @ApiModelProperty("瀹℃壒浜哄悕绉�")
+    private String approverName;
+
+
+    /**
+     * 瓒呮椂鏃堕暱锛堝皬鏃讹級
+     */
+    @ApiModelProperty("瓒呮椂鏃堕暱锛堝皬鏃讹級")
+    private Integer timeoutHours;
+
+    /**
+     * 绉熸埛ID
+     */
+    @ApiModelProperty("绉熸埛ID")
+    private Long tenantId;
+
+    /**
+     * 鍒涘缓鐢ㄦ埛ID
+     */
+    @ApiModelProperty("鍒涘缓鐢ㄦ埛ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    /**
+     * 淇敼鐢ㄦ埛ID
+     */
+    @ApiModelProperty("淇敼鐢ㄦ埛ID")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+
+    /**
+     * 淇敼鏃堕棿
+     */
+    @ApiModelProperty("淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    /**
+     * 鍒犻櫎鏍囪锛�0姝e父锛�1鍒犻櫎
+     */
+    @ApiModelProperty("鍒犻櫎鏍囪锛�0姝e父锛�1鍒犻櫎")
+    private Boolean deleteFlag;
+
+    /**
+     * 閮ㄩ棬ID
+     */
+    @ApiModelProperty("閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/approve/pojo/FileSharing.java b/src/main/java/com/ruoyi/approve/pojo/FileSharing.java
index 9c84034..169df73 100644
--- a/src/main/java/com/ruoyi/approve/pojo/FileSharing.java
+++ b/src/main/java/com/ruoyi/approve/pojo/FileSharing.java
@@ -66,4 +66,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/HolidaySettings.java b/src/main/java/com/ruoyi/approve/pojo/HolidaySettings.java
index f3d9506..c4469dd 100644
--- a/src/main/java/com/ruoyi/approve/pojo/HolidaySettings.java
+++ b/src/main/java/com/ruoyi/approve/pojo/HolidaySettings.java
@@ -77,4 +77,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java b/src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java
index c21eb72..06dec8e 100644
--- a/src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java
+++ b/src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java
@@ -1,5 +1,6 @@
 package com.ruoyi.approve.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
@@ -83,4 +84,11 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/NotificationManagement.java b/src/main/java/com/ruoyi/approve/pojo/NotificationManagement.java
index cb91626..960b5e3 100644
--- a/src/main/java/com/ruoyi/approve/pojo/NotificationManagement.java
+++ b/src/main/java/com/ruoyi/approve/pojo/NotificationManagement.java
@@ -85,4 +85,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/OnlineMeeting.java b/src/main/java/com/ruoyi/approve/pojo/OnlineMeeting.java
index 863d348..8a52ec3 100644
--- a/src/main/java/com/ruoyi/approve/pojo/OnlineMeeting.java
+++ b/src/main/java/com/ruoyi/approve/pojo/OnlineMeeting.java
@@ -77,4 +77,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/OvertimeSetting.java b/src/main/java/com/ruoyi/approve/pojo/OvertimeSetting.java
index ed929cd..d4cd88e 100644
--- a/src/main/java/com/ruoyi/approve/pojo/OvertimeSetting.java
+++ b/src/main/java/com/ruoyi/approve/pojo/OvertimeSetting.java
@@ -76,4 +76,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/RpaProcessAutomation.java b/src/main/java/com/ruoyi/approve/pojo/RpaProcessAutomation.java
index d47f2a0..b6a0d8b 100644
--- a/src/main/java/com/ruoyi/approve/pojo/RpaProcessAutomation.java
+++ b/src/main/java/com/ruoyi/approve/pojo/RpaProcessAutomation.java
@@ -62,4 +62,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/pojo/WorkingHoursSetting.java b/src/main/java/com/ruoyi/approve/pojo/WorkingHoursSetting.java
index e457c8f..4e83d43 100644
--- a/src/main/java/com/ruoyi/approve/pojo/WorkingHoursSetting.java
+++ b/src/main/java/com/ruoyi/approve/pojo/WorkingHoursSetting.java
@@ -76,4 +76,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/approve/service/ApproveProcessConfigNodeService.java b/src/main/java/com/ruoyi/approve/service/ApproveProcessConfigNodeService.java
new file mode 100644
index 0000000..9eb0428
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/ApproveProcessConfigNodeService.java
@@ -0,0 +1,22 @@
+package com.ruoyi.approve.service;
+
+import com.ruoyi.approve.bean.vo.ApproveProcessConfigNodeVo;
+import com.ruoyi.approve.pojo.ApproveProcessConfigNode;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒娴佺▼閰嶇疆鑺傜偣琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-23 10:21:41
+ */
+public interface ApproveProcessConfigNodeService extends IService<ApproveProcessConfigNode> {
+
+    List<ApproveProcessConfigNodeVo> listNode(Integer type);
+
+    Boolean addApproveProcessConfigNodes(List<ApproveProcessConfigNode> approveProcessConfigNodes);
+}
diff --git a/src/main/java/com/ruoyi/approve/service/IApproveProcessService.java b/src/main/java/com/ruoyi/approve/service/IApproveProcessService.java
index a951ff6..49b3508 100644
--- a/src/main/java/com/ruoyi/approve/service/IApproveProcessService.java
+++ b/src/main/java/com/ruoyi/approve/service/IApproveProcessService.java
@@ -3,14 +3,13 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.approve.pojo.ApproveNode;
+import com.ruoyi.approve.vo.ApproveProcessVo;
 import com.ruoyi.approve.pojo.ApproveProcess;
-import com.ruoyi.approve.vo.ApproveGetAndUpdateVo;
-import com.ruoyi.approve.vo.ApproveProcessVO;
+import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo;
+import com.ruoyi.approve.bean.vo.ApproveProcessVO;
 import com.ruoyi.project.system.domain.SysDept;
 
 import java.io.IOException;
-import java.text.ParseException;
 import java.util.List;
 
 public interface IApproveProcessService extends IService<ApproveProcess> {
@@ -25,7 +24,7 @@
      */
     List<SysDept> selectDeptListByDeptIds(Long[] deptIds);
 
-    IPage<ApproveProcess> listAll(Page page, ApproveProcess approveProcess);
+    IPage<ApproveProcessVo> listAll(Page page, ApproveProcess approveProcess);
 
     void delApprove(List<Long> ids);
 
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
index 00a53f5..3caf7cf 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -3,7 +3,6 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.approve.mapper.ApproveNodeMapper;
@@ -11,27 +10,37 @@
 import com.ruoyi.approve.pojo.ApproveNode;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.approve.service.IApproveNodeService;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.device.mapper.DeviceRepairMapper;
-import com.ruoyi.device.pojo.DeviceRepair;
-import com.ruoyi.other.service.impl.TempFileServiceImpl;
 import com.ruoyi.procurementrecord.utils.StockUtils;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.system.service.ISysNoticeService;
 import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
-import com.ruoyi.purchase.service.impl.PurchaseLedgerServiceImpl;
-import com.ruoyi.sales.mapper.*;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.mapper.QualityInspectParamMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardParamMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.quality.pojo.QualityTestStandard;
+import com.ruoyi.quality.pojo.QualityTestStandardParam;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.mapper.SalesQuotationMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.SalesQuotation;
 import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
@@ -43,44 +52,26 @@
 import java.util.List;
 
 @Service
-//@RequiredArgsConstructor
+@RequiredArgsConstructor
 public class ApproveNodeServiceImpl extends ServiceImpl<ApproveNodeMapper, ApproveNode> implements IApproveNodeService {
 
-    @Autowired
-    private  ApproveNodeMapper approveNodeMapper;
-    @Autowired
-    private ApproveProcessMapper approveProcessMapper;
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private TempFileServiceImpl tempFileService;
-    @Autowired
-    private  ISysNoticeService sysNoticeService;
-
-    @Autowired
-    private CommonFileMapper fileMapper;
-    @Autowired
-    private DeviceRepairMapper deviceRepairMapper;
-
-    @Autowired
-    private PurchaseLedgerMapper purchaseLedgerMapper;
-
-    @Autowired
-    private SalesQuotationMapper salesQuotationMapper;
-
-    @Autowired
-    private ShippingInfoMapper shippingInfoMapper;
-
-    @Autowired
-    private CommonFileServiceImpl commonFileService;
-    @Autowired
-    private StockUtils stockUtils;
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-
-    @Autowired
-    private PurchaseLedgerServiceImpl purchaseLedgerServiceImpl;
+    private final ApproveNodeMapper approveNodeMapper;
+    private final ApproveProcessMapper approveProcessMapper;
+    private final SysUserMapper sysUserMapper;
+    private final ISysNoticeService sysNoticeService;
+    private final CommonFileMapper fileMapper;
+    private final DeviceRepairMapper deviceRepairMapper;
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
+    private final SalesQuotationMapper salesQuotationMapper;
+    private final ShippingInfoMapper shippingInfoMapper;
+    private final CommonFileServiceImpl commonFileService;
+    private final StockUtils stockUtils;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final QualityInspectMapper qualityInspectMapper;
+    private final QualityTestStandardMapper qualityTestStandardMapper;
+    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
+    private final QualityInspectParamMapper qualityInspectParamMapper;
+    private final FileUtil fileUtil;
 
 
     public ApproveProcess getApproveById(String id) {
@@ -94,7 +85,7 @@
     }
 
     @Override
-    public void initApproveNodes(String approveUserIds,String approveID,Long tenantId) {
+    public void initApproveNodes(String approveUserIds, String approveID, Long tenantId) {
         Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
         String[] names = approveUserIds.split(",");
         for (int i = 0; i < names.length; i++) {
@@ -102,7 +93,7 @@
             if (sysUser == null) continue;
             ApproveNode approveNode = new ApproveNode();
             approveNode.setApproveProcessId(approveID);
-            approveNode.setApproveNodeOrder(i +1);
+            approveNode.setApproveNodeOrder(i + 1);
             approveNode.setApproveNodeUser(sysUser.getNickName());
             approveNode.setApproveNodeUserId(sysUser.getUserId());
             approveNode.setApproveNodeTime(new Date());
@@ -132,17 +123,17 @@
 //                .eq(ApproveProcess::getApproveStatus, 0)
                 .last("limit 1");
         ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
-        if(approveProcess != null && approveProcess.getApproveStatus() == 3){
+        if (approveProcess != null && approveProcess.getApproveStatus() == 3) {
             return list;
         }
         for (ApproveNode approveNode : list) {
             List<CommonFile> commonFiles = fileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
                     .eq(CommonFile::getCommonId, approveNode.getId())
                     .eq(CommonFile::getType, FileNameType.ApproveNode.getValue()));
-            if(!CollectionUtils.isEmpty(commonFiles)){
+            if (!CollectionUtils.isEmpty(commonFiles)) {
                 approveNode.setUrl(commonFiles.get(0).getUrl());
             }
-            if(approveNode.getApproveNodeStatus() == 1){
+            if (approveNode.getApproveNodeStatus() == 1) {
                 continue;
             }
             approveNode.setIsShen(true);
@@ -151,13 +142,13 @@
         return list;
     }
 
-    public void updateApproveProcessStatus(ApproveNode approveNode,Integer status) throws IOException {
+    public void updateApproveProcessStatus(ApproveNode approveNode, Integer status) throws IOException {
         LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
         approveProcessLambdaQueryWrapper.eq(ApproveProcess::getApproveId, approveNode.getApproveProcessId())
                 .eq(ApproveProcess::getApproveDelete, 0)
                 .last("limit 1");
         ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
-        if(approveProcess == null) throw new RuntimeException("瀹℃壒涓嶅瓨鍦�");
+        if (approveProcess == null) throw new RuntimeException("瀹℃壒涓嶅瓨鍦�");
         LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
         approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveNode.getApproveProcessId())
                 .eq(ApproveNode::getApproveNodeOrder, approveNode.getApproveNodeOrder() + 1)
@@ -166,33 +157,21 @@
                 .last("limit 1");
         ApproveNode approveNode1 = approveNodeMapper.selectOne(approveNodeLambdaQueryWrapper);
         approveProcess.setApproveStatus(status);
-        if(approveNode1 != null){
+        if (approveNode1 != null) {
             approveProcess.setApproveUserCurrentId(approveNode1.getApproveNodeUserId());
             approveProcess.setApproveUserCurrentName(approveNode1.getApproveNodeUser());
         }
-        if(approveProcess.getApproveStatus().equals(2) || approveProcess.getApproveStatus().equals(3) || approveProcess.getApproveStatus().equals(4)){
+        if (approveProcess.getApproveStatus().equals(2) || approveProcess.getApproveStatus().equals(3) || approveProcess.getApproveStatus().equals(4)) {
             approveProcess.setApproveOverTime(new Date());
         }
         approveProcessMapper.updateById(approveProcess);
 
-        DeviceRepair deviceRepair = deviceRepairMapper.selectById(approveProcess.getDeviceRepairId());
-        if(ObjectUtils.isNotNull(deviceRepair)) {
-            if(approveProcess.getApproveStatus().equals(2)){
-                // 鍚屾剰
-                deviceRepair.setStatus(1);
-            }else if(approveProcess.getApproveStatus().equals(3)){
-                // 鎷掔粷
-                deviceRepair.setStatus(2);
-            }
-            deviceRepairMapper.updateById(deviceRepair);
-        }
-
         //閲囪喘瀹℃牳
-        if(approveProcess.getApproveType().equals(5)){
+        if (approveProcess.getApproveType().equals(5)) {
             PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>()
                     .eq(PurchaseLedger::getPurchaseContractNumber, approveProcess.getApproveReason())
                     .last("limit 1"));
-            if(purchaseLedger != null) {
+            if (purchaseLedger != null) {
                 if (status.equals(2)) {
                     // 鍚屾剰
                     purchaseLedger.setApprovalStatus(3);
@@ -201,8 +180,8 @@
                     for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
                         // 璐ㄦ
                         if (salesLedgerProduct.getIsChecked()) {
-                            purchaseLedgerServiceImpl.addQualityInspect(purchaseLedger, salesLedgerProduct);
-                        }else {
+                            addQualityInspect(purchaseLedger, salesLedgerProduct);
+                        } else {
                             //鐩存帴鍏ュ簱
                             stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId());
                         }
@@ -218,63 +197,60 @@
             }
         }
         // 閿�鍞姤浠风姸鎬佷慨鏀�
-        if(approveProcess.getApproveType().equals(6)){
+        if (approveProcess.getApproveType().equals(6)) {
             SalesQuotation salesQuote = salesQuotationMapper.selectOne(new LambdaQueryWrapper<SalesQuotation>()
                     .eq(SalesQuotation::getQuotationNo, approveProcess.getApproveReason())
                     .last("limit 1"));
             // 鍚屾剰
-            if(status.equals(2) && salesQuote != null){
+            if (status.equals(2) && salesQuote != null) {
                 salesQuote.setStatus("閫氳繃");
-            }else if(status.equals(3) && salesQuote != null){
+            } else if (status.equals(3) && salesQuote != null) {
                 salesQuote.setStatus("鎷掔粷");
-            }else if(status.equals(1) && salesQuote != null){
+            } else if (status.equals(1) && salesQuote != null) {
                 salesQuote.setStatus("瀹℃牳涓�");
             }
             salesQuotationMapper.updateById(salesQuote);
         }
         // 鍑哄簱瀹℃壒淇敼
-        if(approveProcess.getApproveType().equals(7)){
+        if (approveProcess.getApproveType().equals(7)) {
             String[] split = approveProcess.getApproveReason().split(":");
             ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
                     .eq(ShippingInfo::getShippingNo, split[1])
                     .orderByDesc(ShippingInfo::getCreateTime)
                     .last("limit 1"));
-            if(shippingInfo != null){
-                if(status.equals(2)){
+            if (shippingInfo != null) {
+                if (status.equals(2)) {
                     shippingInfo.setStatus("瀹℃牳閫氳繃");
-                }else if(status.equals(3)){
+                } else if (status.equals(3)) {
                     shippingInfo.setStatus("瀹℃牳鎷掔粷");
-                }else if(status.equals(1)){
+                } else if (status.equals(1)) {
                     shippingInfo.setStatus("瀹℃牳涓�");
                 }
                 shippingInfoMapper.updateById(shippingInfo);
             }
 
         }
-        // 缁戝畾闄勪欢
-        if(!CollectionUtils.isEmpty(approveNode.getTempFileIds()) && approveNode.getApproveNodeStatus() == 1){
-            tempFileService.migrateTempFilesToFormal(approveNode.getId(), approveNode.getTempFileIds(), FileNameType.ApproveNode.getValue());
-        }
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVE_NODE, approveNode.getId(), approveNode.getStorageBlobDTOS());
     }
 
     @Override
     public void updateApproveNode(ApproveNode approveNode) throws IOException {
         // 瀹℃壒鑺傜偣鐘舵��:1鍚屾剰锛�2鎷掔粷锛�0灏氭湭瀹℃牳
-        switch (approveNode.getApproveNodeStatus()){
+        switch (approveNode.getApproveNodeStatus()) {
             case 1:
                 updateApproveProcessStatus(approveNode, Boolean.TRUE.equals(approveNode.getIsLast()) ? 2 : 1);
                 /*娑堟伅閫氱煡*/
                 Integer nodeOrder = approveNode.getApproveNodeOrder();
                 ApproveProcess approveProcess = approveProcessMapper.selectList(Wrappers.<ApproveProcess>lambdaQuery()
                         .eq(ApproveProcess::getApproveId, approveNode.getApproveProcessId())).get(0);
-                if (approveProcess.getApproveUserIds().split(",").length > nodeOrder){
+                if (approveProcess.getApproveUserIds().split(",").length > nodeOrder) {
                     String id = approveProcess.getApproveUserIds().split(",")[nodeOrder];
-                    if (approveProcess.getApproveType()==8){
+                    if (approveProcess.getApproveType() == 8) {
                         sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                                 approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
                                 Arrays.asList(Long.valueOf(id)),
                                 "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
-                    }else {
+                    } else {
                         sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                                 approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
                                 Arrays.asList(Long.valueOf(id)),
@@ -307,8 +283,8 @@
     }
 
     //瀹℃壒绫诲瀷鑾峰彇(涓庡墠绔〉闈㈠搴�)
-    private String approveProcessType(Integer approveType){
-        switch (approveType){
+    private String approveProcessType(Integer approveType) {
+        switch (approveType) {
             case 1:
                 return "鍏嚭绠$悊";
             case 2:
@@ -325,8 +301,38 @@
                 return "鍙戣揣瀹℃壒";
             case 8:
                 return "鍗遍櫓浣滀笟瀹℃壒";
+            case 9:
+                return "鍔炲叕鐢ㄥ搧瀹℃壒";
         }
         return null;
     }
 
+    private void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct) {
+        QualityInspect qualityInspect = new QualityInspect();
+        qualityInspect.setInspectType(0);
+        qualityInspect.setSupplier(purchaseLedger.getSupplierName());
+        qualityInspect.setPurchaseLedgerId(purchaseLedger.getId());
+        qualityInspect.setProductId(saleProduct.getProductId());
+        qualityInspect.setProductName(saleProduct.getProductCategory());
+        qualityInspect.setModel(saleProduct.getSpecificationModel());
+        qualityInspect.setProductModelId(saleProduct.getProductModelId());
+        qualityInspect.setUnit(saleProduct.getUnit());
+        qualityInspect.setQuantity(saleProduct.getQuantity());
+        qualityInspectMapper.insert(qualityInspect);
+        List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(saleProduct.getProductId(), 0, null);
+        if (qualityTestStandard.size() > 0) {
+            qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
+            qualityInspectMapper.updateById(qualityInspect);
+            qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
+                            .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))
+                    .forEach(qualityTestStandardParam -> {
+                        QualityInspectParam param = new QualityInspectParam();
+                        com.ruoyi.common.utils.bean.BeanUtils.copyProperties(qualityTestStandardParam, param);
+                        param.setId(null);
+                        param.setInspectId(qualityInspect.getId());
+                        qualityInspectParamMapper.insert(param);
+                    });
+        }
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessConfigNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessConfigNodeServiceImpl.java
new file mode 100644
index 0000000..80d7a2c
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessConfigNodeServiceImpl.java
@@ -0,0 +1,48 @@
+package com.ruoyi.approve.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.vo.ApproveProcessConfigNodeVo;
+import com.ruoyi.approve.mapper.ApproveProcessConfigNodeMapper;
+import com.ruoyi.approve.pojo.ApproveProcessConfigNode;
+import com.ruoyi.approve.service.ApproveProcessConfigNodeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹℃壒娴佺▼閰嶇疆鑺傜偣琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-23 10:21:41
+ */
+@Service
+@RequiredArgsConstructor
+public class ApproveProcessConfigNodeServiceImpl extends ServiceImpl<ApproveProcessConfigNodeMapper, ApproveProcessConfigNode> implements ApproveProcessConfigNodeService {
+
+    private final ApproveProcessConfigNodeMapper approveProcessConfigNodeMapper;
+    @Override
+    public List<ApproveProcessConfigNodeVo> listNode(Integer type) {
+        List<ApproveProcessConfigNode> approveProcessConfigNodes = approveProcessConfigNodeMapper.selectList(new QueryWrapper<ApproveProcessConfigNode>().lambda().eq(ApproveProcessConfigNode::getApproveType, type).orderByAsc(ApproveProcessConfigNode::getNodeOrder));
+        return approveProcessConfigNodes.stream()
+                .map(node -> {
+                    ApproveProcessConfigNodeVo vo = new ApproveProcessConfigNodeVo();
+                    BeanUtils.copyProperties(node, vo);
+                    return vo;
+                })
+                .collect(java.util.stream.Collectors.toList());
+    }
+
+    @Override
+    public Boolean addApproveProcessConfigNodes(List<ApproveProcessConfigNode> approveProcessConfigNodes) {
+        //鍒犻櫎鏃ф暟鎹�
+        approveProcessConfigNodeMapper.delete(new QueryWrapper<ApproveProcessConfigNode>().lambda().eq(ApproveProcessConfigNode::getApproveType, approveProcessConfigNodes.get(0).getApproveType()));
+        //鏂板 鏁版嵁
+        approveProcessConfigNodeMapper.insert(approveProcessConfigNodes);
+        return true;
+    }
+}
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
index a624661..9f505aa 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -1,24 +1,31 @@
 package com.ruoyi.approve.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo;
+import com.ruoyi.approve.bean.vo.ApproveProcessConfigNodeVo;
+import com.ruoyi.approve.bean.vo.ApproveProcessVO;
 import com.ruoyi.approve.mapper.ApproveNodeMapper;
+import com.ruoyi.approve.mapper.ApproveProcessConfigNodeMapper;
 import com.ruoyi.approve.mapper.ApproveProcessMapper;
 import com.ruoyi.approve.pojo.ApproveNode;
 import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.approve.pojo.ApproveProcessConfigNode;
+import com.ruoyi.approve.service.ApproveProcessConfigNodeService;
 import com.ruoyi.approve.service.IApproveNodeService;
 import com.ruoyi.approve.service.IApproveProcessService;
-import com.ruoyi.approve.utils.DailyRedisCounter;
-import com.ruoyi.approve.vo.ApproveGetAndUpdateVo;
-import com.ruoyi.approve.vo.ApproveProcessVO;
+import com.ruoyi.approve.vo.ApproveProcessVo;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.other.service.impl.TempFileServiceImpl;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.domain.SysNotice;
 import com.ruoyi.project.system.domain.SysUser;
@@ -32,80 +39,74 @@
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
-import lombok.AllArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
 import java.io.IOException;
-import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
-//@RequiredArgsConstructor
+@RequiredArgsConstructor
 public class ApproveProcessServiceImpl extends ServiceImpl<ApproveProcessMapper, ApproveProcess> implements IApproveProcessService {
     private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
 
-    @Autowired
-    private  StringRedisTemplate redisTemplate;
-    @Autowired
-    private  DailyRedisCounter dailyRedisCounter;
-    @Autowired
-    private  SysDeptMapper sysDeptMapper;
-    @Autowired
-    private  IApproveNodeService approveNodeService;
-    @Autowired
-    private  SysUserMapper sysUserMapper;
-    @Autowired
-    private  ApproveProcessMapper approveProcessMapper;
-    @Autowired
-    private  TempFileServiceImpl tempFileService;
-    @Autowired
-    private  CommonFileMapper commonFileMapper;
-    @Autowired
-    private  CommonFileServiceImpl commonFileService;
-    @Autowired
-    private  ISysNoticeService sysNoticeService;
+    private final SysDeptMapper sysDeptMapper;
+    private final IApproveNodeService approveNodeService;
+    private final SysUserMapper sysUserMapper;
+    private final ApproveProcessMapper approveProcessMapper;
+    private final CommonFileMapper commonFileMapper;
+    private final CommonFileServiceImpl commonFileService;
+    private final ISysNoticeService sysNoticeService;
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
+    private final ShippingInfoMapper shippingInfoMapper;
+    private final ApproveNodeMapper approveNodeMapper;
+    private final ApproveProcessConfigNodeService approveProcessConfigNodeService;
+    private final FileUtil fileUtil;
+    private final ApproveProcessConfigNodeMapper approveProcessConfigNodeMapper;
 
     @Override
     public void addApprove(ApproveProcessVO approveProcessVO) throws Exception {
-        SysUser sysUser = sysUserMapper.selectUserById(approveProcessVO.getApproveUser());
-        SysDept sysDept = sysDeptMapper.selectDeptById(approveProcessVO.getApproveDeptId());
-        String[] split = approveProcessVO.getApproveUserIds().split(",");
-        List<Long> longList = Arrays.stream(split)
-                .map(Long::valueOf)  // 灏嗘瘡涓� String 杞崲涓� Long
+        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
+        SysDept sysDept = sysDeptMapper.selectDeptById(SecurityUtils.getLoginUser().getCurrentDeptId());
+        List<ApproveProcessConfigNodeVo> list = approveProcessConfigNodeService.listNode(approveProcessVO.getApproveType());
+        List<Long> nodeIds = list.stream()
+                .map(ApproveProcessConfigNodeVo::getApproverId)
+                .filter(Objects::nonNull)
                 .collect(Collectors.toList());
-        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(longList);
+        if (list.isEmpty()) {
+            throw new RuntimeException("娴佺▼涓嶅瓨鍦�");
+        }
+        if (CollectionUtils.isEmpty(nodeIds)) {
+            autoPassPurchaseApproveIfNoApprover(approveProcessVO);
+            return;
+        }
+        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(nodeIds);
         if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("瀹℃牳鐢ㄦ埛涓嶅瓨鍦�");
         if (sysDept == null) throw new RuntimeException("閮ㄩ棬涓嶅瓨鍦�");
         if (sysUser == null) throw new RuntimeException("鐢宠浜轰笉瀛樺湪");
-        String today = LocalDate.now().format(DATE_FORMAT);
-        Long approveId = dailyRedisCounter.incrementAndGetByDb();
-        String formattedCount = String.format("%03d", approveId);
-        //娴佺▼ ID
-        String approveID = today + formattedCount;
+//        String today = LocalDate.now().format(DATE_FORMAT);
+//        Long approveId = dailyRedisCounter.incrementAndGetByDb();
+//        String formattedCount = String.format("%03d", approveId);
+//        //娴佺▼ ID
+//        String approveID = today + formattedCount;
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
         ApproveProcess approveProcess = new ApproveProcess();
-        approveProcess.setApproveId(approveID);
-        approveProcess.setApproveUser(approveProcessVO.getApproveUser());
+        String no = OrderUtils.countTodayByCreateTime(approveProcessMapper, "", "approve_id");
+        approveProcess.setApproveId(no);
+        approveProcess.setApproveUser(sysUser.getUserId());
         approveProcess.setApproveUserName(sysUser.getNickName());
-        approveProcess.setApproveDeptId(approveProcessVO.getApproveDeptId());
+        approveProcess.setApproveDeptId(sysDept.getDeptId());
+        approveProcess.setApproveUserIds(nodeIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
         approveProcess.setApproveDeptName(sysDept.getDeptName());
         approveProcess.setApproveUserNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
-        approveProcess.setApproveTime(StringUtils.isEmpty(approveProcessVO.getApproveTime()) ? null : dateFormat.parse(approveProcessVO.getApproveTime()));
+        approveProcess.setApproveTime(StringUtils.isEmpty(approveProcessVO.getApproveTime()) ? new Date() : dateFormat.parse(approveProcessVO.getApproveTime()));
         approveProcess.setApproveReason(approveProcessVO.getApproveReason());
         approveProcess.setDeviceRepairId(approveProcessVO.getDeviceRepairId());
         approveProcess.setMaintenancePrice(approveProcessVO.getMaintenancePrice());
@@ -117,11 +118,10 @@
         approveProcess.setApproveType(approveProcessVO.getApproveType());
         approveProcess.setCreateTime(LocalDateTime.now());
         approveProcess.setTenantId(approveProcessVO.getApproveDeptId());
-        approveProcess.setApproveUserIds(approveProcessVO.getApproveUserIds());
-        approveProcess.setApproveUserCurrentId(longList.get(0));
+        approveProcess.setApproveUserCurrentId(nodeIds.get(0));
         approveProcess.setApproveUserCurrentName(sysUsers
                 .stream()
-                .filter(SysUser -> SysUser.getUserId().equals(longList.get(0)))
+                .filter(SysUser -> SysUser.getUserId().equals(nodeIds.get(0)))
                 .collect(Collectors.toList())
                 .get(0)
                 .getNickName());
@@ -133,22 +133,35 @@
         }
         save(approveProcess);
         //鍒濆鍖栧鎵硅妭鐐�
-        approveNodeService.initApproveNodes(approveProcessVO.getApproveUserIds(), approveID, approveProcessVO.getApproveDeptId());
+        String nodeIdStr = nodeIds.stream()
+                .map(String::valueOf)
+                .collect(Collectors.joining(","));
+        approveNodeService.initApproveNodes(nodeIdStr, no, approveProcessVO.getApproveDeptId());
         // 闄勪欢缁戝畾
-        tempFileService.migrateTempFilesToFormal(approveProcess.getId(), approveProcessVO.getTempFileIds(), FileNameType.ApproveProcess.getValue());
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVE_PROCESS, approveProcess.getId(), approveProcessVO.getStorageBlobDTOList());
         /*娑堟伅閫氱煡*/
-        String id = approveProcessVO.getApproveUserIds().split(",")[0];
-        if (approveProcess.getApproveType()==8){
+        Long id = nodeIds.getFirst();
+        if (approveProcess.getApproveType() == 8) {
             sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                     approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
+                    Collections.singletonList(id),
                     "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
-        }else {
+        } else {
             sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                     approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
+                    Collections.singletonList(id),
                     "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
         }
+    }
+
+    private void autoPassPurchaseApproveIfNoApprover(ApproveProcessVO approveProcessVO) {
+        if (!Objects.equals(approveProcessVO.getApproveType(), 5)
+                || !StringUtils.hasText(approveProcessVO.getApproveReason())) {
+            throw new RuntimeException("瀹℃牳鐢ㄦ埛涓嶅瓨鍦�");
+        }
+        purchaseLedgerMapper.update(null, new LambdaUpdateWrapper<PurchaseLedger>()
+                .eq(PurchaseLedger::getPurchaseContractNumber, approveProcessVO.getApproveReason())
+                .set(PurchaseLedger::getApprovalStatus, 3));
     }
 
     @Override
@@ -161,18 +174,12 @@
         return sysDeptList;
     }
 
-    @Autowired
-    private PurchaseLedgerMapper purchaseLedgerMapper;
-
-    @Autowired
-    private ShippingInfoMapper shippingInfoMapper;
-
     @Override
-    public IPage<ApproveProcess> listAll(Page page, ApproveProcess approveProcess) {
-        IPage<ApproveProcess> approveProcessIPage = approveProcessMapper.listPage(page, approveProcess);
-        List<ApproveProcess> records = approveProcessIPage.getRecords();
+    public IPage<ApproveProcessVo> listAll(Page page, ApproveProcess approveProcess) {
+        IPage<ApproveProcessVo> approveProcessIPage = approveProcessMapper.listPage(page, approveProcess);
+        List<ApproveProcessVo> records = approveProcessIPage.getRecords();
 
-        for (ApproveProcess record : records) {
+        for (ApproveProcessVo record : records) {
             List<CommonFile> allFiles = new ArrayList<>();
 
             //  閲囪喘瀹℃壒鏌ヨ
@@ -216,6 +223,7 @@
             }
 
             record.setCommonFileList(allFiles);
+            record.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.APPROVE_PROCESS, record.getId()));
         }
         return approveProcessIPage;
     }
@@ -286,9 +294,9 @@
 
             //  鍒犻櫎瀵瑰簲鐨勬秷鎭�氱煡
             sysNoticeService.remove(new LambdaQueryWrapper<SysNotice>()
-                            .eq(SysNotice::getNoticeTitle, approveProcessType(latestProcess.getApproveType()))
-                            .eq(SysNotice::getSenderId, latestProcess.getApproveUser())
-                            .apply("CAST(notice_content AS CHAR) LIKE CONCAT('%', {0}, '%')", latestProcess.getApproveId()));
+                    .eq(SysNotice::getNoticeTitle, approveProcessType(latestProcess.getApproveType()))
+                    .eq(SysNotice::getSenderId, latestProcess.getApproveUser())
+                    .apply("CAST(notice_content AS CHAR) LIKE CONCAT('%', {0}, '%')", latestProcess.getApproveId()));
         }
 
     }
@@ -296,16 +304,12 @@
     @Override
     public ApproveProcess getApproveById(String id) {
         ApproveProcess one = approveProcessMapper.selectList(Wrappers.<ApproveProcess>lambdaQuery()
-                .eq(ApproveProcess::getApproveId,id)
-                .eq(ApproveProcess::getApproveDelete,0)).get(0);
-        one.setCommonFileList(commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
-                .eq(CommonFile::getCommonId, one.getId())
-                .eq(CommonFile::getType, FileNameType.ApproveProcess.getValue())));
+                .eq(ApproveProcess::getApproveId, id)
+                .eq(ApproveProcess::getApproveDelete, 0)).get(0);
+        one.setStorageBlobVOS(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.APPROVE_PROCESS, one.getId()));
         return one;
     }
 
-    @Autowired
-    private ApproveNodeMapper approveNodeMapper;
 
     // 鎶ヤ环瀹℃壒缂栬緫瀹℃牳浜�
     public void updateApproveUser(ApproveGetAndUpdateVo approveGetAndUpdateVo) {
@@ -314,17 +318,20 @@
                 .eq(ApproveProcess::getApproveReason, approveGetAndUpdateVo.getApproveReason())
                 .last("limit 1");
         ApproveProcess approveProcess = approveProcessMapper.selectOne(approveProcessLambdaQueryWrapper);
+
         if (approveProcess == null) throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
-        String[] split = approveGetAndUpdateVo.getApproveUserIds().split(",");
-        if (split.length == 0) {
-            throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
-        }
-        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(Arrays.asList(split).stream().map(Long::parseLong).collect(Collectors.toList()));
+        //鏌ヨ瀹℃壒閰嶇疆
+        List<ApproveProcessConfigNode> approveProcessConfig = approveProcessConfigNodeMapper.selectList(new LambdaQueryWrapper<ApproveProcessConfigNode>().eq(ApproveProcessConfigNode::getApproveType, approveGetAndUpdateVo.getApproveType()));
+        List<Long> configNodeIds = approveProcessConfig.stream()
+                .sorted(Comparator.comparing(ApproveProcessConfigNode::getNodeOrder))
+                .map(ApproveProcessConfigNode::getApproverId)
+                .collect(Collectors.toList());
+        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(configNodeIds);
         if (CollectionUtils.isEmpty(sysUsers)) throw new RuntimeException("璇烽�夋嫨瀹℃壒浜�");
         //瀹℃牳涓笉鍙互缂栬緫瀹℃牳浜�
         if (approveProcess.getApproveStatus() != 1) {
-            approveProcess.setApproveUserCurrentId(Long.parseLong(split[0]));
-            approveProcess.setApproveUserCurrentName(sysUsers.stream().filter(user -> user.getUserId().equals(Long.parseLong(split[0]))).collect(Collectors.toList()).get(0).getNickName());
+            approveProcess.setApproveUserCurrentId(configNodeIds.get(0));
+            approveProcess.setApproveUserCurrentName(sysUsers.stream().filter(user -> user.getUserId().equals(configNodeIds.get(0))).collect(Collectors.toList()).get(0).getNickName());
         }
         if (approveGetAndUpdateVo.getApproveStatus() != null) {
             approveProcess.setApproveStatus(approveGetAndUpdateVo.getApproveStatus());
@@ -336,21 +343,24 @@
         LambdaQueryWrapper<ApproveNode> approveNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
         approveNodeLambdaQueryWrapper.eq(ApproveNode::getApproveProcessId, approveProcess.getApproveId())
                 .eq(ApproveNode::getDeleteFlag, 0)
-//                .eq(ApproveNode::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                 .orderByAsc(ApproveNode::getApproveNodeOrder);
         approveNodeMapper.delete(approveNodeLambdaQueryWrapper);
+        //鏌ヨ瀹℃壒閰嶇疆
+        approveGetAndUpdateVo.setApproveUserIds(configNodeIds.stream()
+                .map(String::valueOf)
+                .collect(Collectors.joining(",")));
         approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approveProcess.getApproveId(), approveProcess.getTenantId());
         /*娑堟伅閫氱煡*/
-        String id = approveProcess.getApproveUserIds().split(",")[0];
-        if (approveProcess.getApproveType()==8){
+        Long id = configNodeIds.get(0);
+        if (approveProcess.getApproveType() == 8) {
             sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                     approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
+                    Collections.singletonList(id),
                     "/safeProduction/safeWorkApproval?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
-        }else {
+        } else {
             sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
                     approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                    Arrays.asList(Long.valueOf(id)),
+                    Collections.singletonList(id),
                     "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
         }
     }
@@ -404,15 +414,15 @@
 //            approveNodeMapper.updateById(approveNode);
 //            i++;
 //        }
-        tempFileService.migrateTempFilesToFormal(approve.getId(), approveGetAndUpdateVo.getTempFileIds(), FileNameType.ApproveProcess.getValue());
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVE_PROCESS, approve.getId(), approveGetAndUpdateVo.getStorageBlobDTOS());
         /*娑堟伅閫氱煡*/
         String id = approve.getApproveUserIds().split(",")[0];
-        if (approve.getApproveType()==8){
+        if (approve.getApproveType() == 8) {
             sysNoticeService.simpleNoticeByUser(approveProcessType(approve.getApproveType()),
                     approve.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
                     Arrays.asList(Long.valueOf(id)),
                     "/safeProduction/safeWorkApproval?approveType=" + approve.getApproveType() + "&approveId=" + approve.getApproveId());
-        }else {
+        } else {
             sysNoticeService.simpleNoticeByUser(approveProcessType(approve.getApproveType()),
                     approve.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
                     Arrays.asList(Long.valueOf(id)),
@@ -441,6 +451,8 @@
                 return "鍙戣揣瀹℃壒";
             case 8:
                 return "鍗遍櫓浣滀笟瀹℃壒";
+            case 9:
+                return "鍔炲叕鐢ㄥ搧瀹℃壒";
         }
         return null;
     }
diff --git a/src/main/java/com/ruoyi/approve/service/impl/HolidaySettingsServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/HolidaySettingsServiceImpl.java
index a0cfe37..4345072 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/HolidaySettingsServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/HolidaySettingsServiceImpl.java
@@ -6,13 +6,13 @@
 import com.ruoyi.approve.mapper.HolidaySettingsMapper;
 import com.ruoyi.approve.pojo.HolidaySettings;
 import com.ruoyi.approve.service.HolidaySettingsService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class HolidaySettingsServiceImpl extends ServiceImpl<HolidaySettingsMapper, HolidaySettings> implements HolidaySettingsService {
-    @Autowired
-    private HolidaySettingsMapper holidaySettingsMapper;
+    private final HolidaySettingsMapper holidaySettingsMapper;
 
     @Override
     public IPage<HolidaySettings> listpage(Page page, HolidaySettings holidaySettings) {
diff --git a/src/main/java/com/ruoyi/approve/service/impl/KnowledgeBaseServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/KnowledgeBaseServiceImpl.java
index 57a3fa7..f9b2221 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/KnowledgeBaseServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/KnowledgeBaseServiceImpl.java
@@ -6,13 +6,13 @@
 import com.ruoyi.approve.mapper.KnowledgeBaseMapper;
 import com.ruoyi.approve.pojo.KnowledgeBase;
 import com.ruoyi.approve.service.KnowledgeBaseService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class KnowledgeBaseServiceImpl extends ServiceImpl<KnowledgeBaseMapper, KnowledgeBase> implements KnowledgeBaseService {
-    @Autowired
-    private KnowledgeBaseMapper knowledgeBaseMapper;
+    private final KnowledgeBaseMapper knowledgeBaseMapper;
 
     @Override
     public IPage<KnowledgeBase> listpage(Page page, KnowledgeBase knowledgeBase) {
diff --git a/src/main/java/com/ruoyi/approve/service/impl/NotificationManagementServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/NotificationManagementServiceImpl.java
index fa13fa9..b124d68 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/NotificationManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/NotificationManagementServiceImpl.java
@@ -2,18 +2,17 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.approve.mapper.NotificationManagementMapper;
 import com.ruoyi.approve.pojo.NotificationManagement;
 import com.ruoyi.approve.service.NotificationManagementService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class NotificationManagementServiceImpl extends ServiceImpl<NotificationManagementMapper, NotificationManagement> implements NotificationManagementService {
-    @Autowired
-    private NotificationManagementMapper notificationManagementMapper;
+    private final NotificationManagementMapper notificationManagementMapper;
 
     @Override
     public IPage<NotificationManagement> listpage(Page page, NotificationManagement notificationManagement) {
diff --git a/src/main/java/com/ruoyi/approve/service/impl/RpaProcessAutomationServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/RpaProcessAutomationServiceImpl.java
index ddb6083..930c952 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/RpaProcessAutomationServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/RpaProcessAutomationServiceImpl.java
@@ -1,19 +1,18 @@
 package com.ruoyi.approve.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.approve.mapper.RpaProcessAutomationMapper;
 import com.ruoyi.approve.pojo.RpaProcessAutomation;
 import com.ruoyi.approve.service.RpaProcessAutomationService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class RpaProcessAutomationServiceImpl extends ServiceImpl<RpaProcessAutomationMapper, RpaProcessAutomation> implements RpaProcessAutomationService {
-    @Autowired
-    private RpaProcessAutomationMapper rpaProcessAutomationMapper;
+    private final RpaProcessAutomationMapper rpaProcessAutomationMapper;
     @Override
     public IPage<RpaProcessAutomation> listpage(Page page, RpaProcessAutomation rpaProcessAutomation) {
         return rpaProcessAutomationMapper.listpage(page,rpaProcessAutomation);
diff --git a/src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java b/src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java
new file mode 100644
index 0000000..4ae03e6
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/utils/ApproveProcessConfigNodeUtils.java
@@ -0,0 +1,9 @@
+package com.ruoyi.approve.utils;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class ApproveProcessConfigNodeUtils {
+
+
+}
diff --git a/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java b/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java
index f1348db..1d1466a 100644
--- a/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java
+++ b/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java
@@ -3,12 +3,11 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.ruoyi.approve.mapper.ApproveProcessMapper;
 import com.ruoyi.approve.pojo.ApproveProcess;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
@@ -19,14 +18,11 @@
 
 //鍩轰簬redis鐨勪竴涓瘡鏃ヨ鏁板櫒
 @Component
+@RequiredArgsConstructor
 public class DailyRedisCounter {
     private static final String KEY_PREFIX = "daily_counter:";
     private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
     private final StringRedisTemplate redisTemplate;
-
-    public DailyRedisCounter(StringRedisTemplate redisTemplate) {
-        this.redisTemplate = redisTemplate;
-    }
 
     @Value("${ruoyi.approvalNumberPrefix}")
     private String approvalNumberPrefix;
@@ -49,8 +45,7 @@
         return count;
     }
 
-    @Autowired
-    private ApproveProcessMapper approveProcessMapper;
+    private final ApproveProcessMapper approveProcessMapper;
 
     /**
      * 鑾峰彇褰撳墠鏃堕棿鐨�  寮�濮嬫棩鏈�  锛岀粨鏉熸棩鏈�
diff --git a/src/main/java/com/ruoyi/approve/utils/StartAndEndDateDto.java b/src/main/java/com/ruoyi/approve/utils/StartAndEndDateDto.java
index 7913ffd..213743a 100644
--- a/src/main/java/com/ruoyi/approve/utils/StartAndEndDateDto.java
+++ b/src/main/java/com/ruoyi/approve/utils/StartAndEndDateDto.java
@@ -1,8 +1,7 @@
 package com.ruoyi.approve.utils;
 
 import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -10,26 +9,26 @@
  * @date : 2023/9/19 10:58
  */
 @Data
-@ApiModel
+@Schema
 public class StartAndEndDateDto {
 
-    @ApiModelProperty("寮�濮嬫椂闂�")
+    @Schema(description = "寮�濮嬫椂闂�")
     @TableField(exist = false)
     private String startDate;
 
-    @ApiModelProperty("缁撴潫鏃堕棿")
+    @Schema(description = "缁撴潫鏃堕棿")
     @TableField(exist = false)
     private String endDate;
 
-    @ApiModelProperty("寮�濮嬫湀浠�")
+    @Schema(description = "寮�濮嬫湀浠�")
     @TableField(exist = false)
     private Integer startMonth;
 
-    @ApiModelProperty("缁撴潫鏈堜唤")
+    @Schema(description = "缁撴潫鏈堜唤")
     @TableField(exist = false)
     private Integer endMonth;
 
-    @ApiModelProperty("骞翠唤")
+    @Schema(description = "骞翠唤")
     @TableField(exist = false)
     private Integer year;
 
diff --git a/src/main/java/com/ruoyi/approve/vo/ApproveGetAndUpdateVo.java b/src/main/java/com/ruoyi/approve/vo/ApproveGetAndUpdateVo.java
deleted file mode 100644
index db45394..0000000
--- a/src/main/java/com/ruoyi/approve/vo/ApproveGetAndUpdateVo.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.ruoyi.approve.vo;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.sales.pojo.CommonFile;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import javax.validation.constraints.NotBlank;
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-
-@Data
-public class ApproveGetAndUpdateVo {
-
-    private List<String> tempFileIds;
-    //瀹℃壒id
-    @NotBlank(message = "娴佺▼缂栧彿涓嶈兘涓虹┖")
-    private String id;
-    //鐢宠浜嬬敱
-    @NotBlank(message = "鐢宠浜嬬敱涓嶈兘涓虹┖")
-    private String approveReason;
-
-    private String approveUserIds;
-
-    private String approveDeptName;
-
-    private Long approveUser;
-
-    private String approveTime;
-
-    private Integer approveStatus;
-
-    @Excel(name = "寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd",width = 30)
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private Date startDate;
-
-    @Excel(name = "缁撴潫鏃堕棿", dateFormat = "yyyy-MM-dd",width = 30)
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private Date endDate;
-
-    private BigDecimal price;
-
-    private String location;
-    /**
-     * 瀹℃壒绫诲瀷
-     */
-    private Integer approveType;
-}
diff --git a/src/main/java/com/ruoyi/approve/vo/ApproveProcessVO.java b/src/main/java/com/ruoyi/approve/vo/ApproveProcessVO.java
deleted file mode 100644
index bf8edae..0000000
--- a/src/main/java/com/ruoyi/approve/vo/ApproveProcessVO.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.ruoyi.approve.vo;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.sales.pojo.CommonFile;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import javax.validation.constraints.NotBlank;
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-
-@Data
-public class ApproveProcessVO {
-    /**
-     * 涓存椂鏂囦欢id鍒楄〃
-     */
-    private List<String> tempFileIds;
-    /**
-     * 瀹℃壒娴佺▼id
-     */
-    private Long id;
-
-    private String approveId;
-    /**
-     * 瀹℃壒閮ㄩ棬id
-     */
-    private Long approveDeptId;
-    /**
-     * 瀹℃壒鏃堕棿
-     */
-    private String approveTime;
-    /**
-     * 鐢宠浜篿d
-     */
-    // 鐢宠浜�
-    private Long approveUser;
-    /**
-     * 瀹℃壒浜篿d鍒楄〃
-     */
-    // 瀹℃壒浜�
-    private String approveUserIds;
-    /**
-     * 瀹℃壒鐞嗙敱
-     */
-    private String approveReason;
-
-    @Excel(name = "寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd",width = 30)
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private Date startDate;
-
-    @Excel(name = "缁撴潫鏃堕棿", dateFormat = "yyyy-MM-dd",width = 30)
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private Date endDate;
-
-    private BigDecimal price;
-
-    private String location;
-
-    /**
-     * 瀹℃壒绫诲瀷
-     */
-    private Integer approveType;
-     /**
-     * 璁惧鎶ヤ慨id
-     */
-    private Long deviceRepairId;
-     /**
-     * 鎶ヤ慨閲戦
-     */
-    private BigDecimal maintenancePrice;
-}
diff --git a/src/main/java/com/ruoyi/approve/vo/ApproveProcessVo.java b/src/main/java/com/ruoyi/approve/vo/ApproveProcessVo.java
new file mode 100644
index 0000000..f3778b6
--- /dev/null
+++ b/src/main/java/com/ruoyi/approve/vo/ApproveProcessVo.java
@@ -0,0 +1,12 @@
+package com.ruoyi.approve.vo;
+
+import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ApproveProcessVo extends ApproveProcess {
+    private List<StorageBlobVO> storageBlobVOs;
+}
diff --git a/src/main/java/com/ruoyi/basic/controller/CustomerController.java b/src/main/java/com/ruoyi/basic/controller/CustomerController.java
index 94c4007..9090d34 100644
--- a/src/main/java/com/ruoyi/basic/controller/CustomerController.java
+++ b/src/main/java/com/ruoyi/basic/controller/CustomerController.java
@@ -2,18 +2,20 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.CustomerDto;
 import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.service.ICustomerService;
+import com.ruoyi.basic.vo.CustomerVo;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.domain.R;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -32,8 +34,9 @@
      * 鏌ヨ瀹㈡埛妗f鍒楄〃
      */
     @GetMapping("/list")
-    public IPage<Customer> list(Page<Customer> page, Customer customer) {
-        return customerService.selectCustomerList(page, customer);
+    public R list(Page<CustomerDto> page, CustomerDto customer) {
+        IPage<CustomerVo> customerDtoIPage = customerService.selectCustomerList(page, customer);
+        return R.ok(customerDtoIPage);
     }
 
     /**
@@ -41,16 +44,9 @@
      */
     @Log(title = "瀹㈡埛妗f", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    public void export(HttpServletResponse response, Customer customer) {
-        Long[] ids = customer.getIds();
-        List<Customer> list;
-        if (ids != null && ids.length > 0) {
-            list = customerService.selectCustomerListByIds(ids);
-        } else {
-            list = customerService.selectCustomerLists(customer);
-        }
-        ExcelUtil<Customer> util = new ExcelUtil<Customer>(Customer.class);
-        util.exportExcel(response, list, "瀹㈡埛妗f鏁版嵁");
+    public void export(HttpServletResponse response, CustomerDto customer) {
+        ExcelUtil<CustomerVo> util = new ExcelUtil<CustomerVo>(CustomerVo.class);
+        util.exportExcel(response, customerService.selectCustomerLists(customer), "瀹㈡埛妗f鏁版嵁");
     }
 
     @PostMapping("/downloadTemplate")
@@ -66,17 +62,17 @@
      */
     @Log(title = "瀹㈡埛妗f", businessType = BusinessType.IMPORT)
     @PostMapping("/importData")
-    public AjaxResult importData(MultipartFile file) throws Exception {
+    public R importData(MultipartFile file, Integer type) throws Exception {
 
-        return customerService.importData(file);
+        return customerService.importData(file, type);
     }
 
     /**
      * 鑾峰彇瀹㈡埛妗f璇︾粏淇℃伅
      */
     @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id) {
-        return success(customerService.selectCustomerDetailById(id));
+    public R getInfo(@PathVariable("id") Long id) {
+        return R.ok(customerService.selectCustomerDetailById(id));
     }
 
     /**
@@ -84,8 +80,8 @@
      */
     @Log(title = "瀹㈡埛妗f", businessType = BusinessType.INSERT)
     @PostMapping("/addCustomer")
-    public AjaxResult add(@RequestBody Customer customer) {
-        return toAjax(customerService.insertCustomer(customer));
+    public R add(@RequestBody Customer customer) {
+        return R.ok(customerService.insertCustomer(customer));
     }
 
     /**
@@ -93,8 +89,8 @@
      */
     @Log(title = "瀹㈡埛妗f", businessType = BusinessType.UPDATE)
     @PostMapping("/updateCustomer")
-    public AjaxResult edit(@RequestBody Customer customer) {
-        return toAjax(customerService.updateCustomer(customer));
+    public R edit(@RequestBody Customer customer) {
+        return R.ok(customerService.updateCustomer(customer));
     }
 
     /**
@@ -102,11 +98,11 @@
      */
     @Log(title = "瀹㈡埛妗f", businessType = BusinessType.DELETE)
     @DeleteMapping("/delCustomer")
-    public AjaxResult remove(@RequestBody Long[] ids) {
+    public R remove(@RequestBody Long[] ids) {
         if (ids == null || ids.length == 0) {
-            return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
+            return R.fail("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         }
-        return toAjax(customerService.deleteCustomerByIds(ids));
+        return R.ok(customerService.deleteCustomerByIds(ids));
     }
 
     /**
@@ -116,4 +112,44 @@
     public List customerList(Customer customer) {
         return customerService.customerList(customer);
     }
+
+
+    /**
+     * 鍒嗛厤瀹㈡埛
+     */
+    @Log(title = "瀹㈡埛妗f", businessType = BusinessType.OTHER)
+    @PostMapping("/assignCustomer")
+    public R assignCustomer(@RequestBody CustomerDto customer) {
+        customerService.assignCustomer(customer);
+        return R.ok();
+    }
+
+    /**
+     * 鍥炴敹瀹㈡埛
+     */
+    @Log(title = "瀹㈡埛妗f", businessType = BusinessType.OTHER)
+    @PostMapping("/recycleCustomer")
+    public R recycleCustomer(@RequestBody CustomerDto customer) {
+        customerService.recycleCustomer(customer);
+        return R.ok();
+    }
+
+    /**
+     * 鍏变韩瀹㈡埛
+     */
+    @Log(title = "瀹㈡埛妗f", businessType = BusinessType.OTHER)
+    @PostMapping("/together")
+    public R together(@RequestBody CustomerDto customer) {
+        customerService.together(customer);
+        return R.ok();
+    }
+
+    /**
+     * 绉佹捣瀹㈡埛娴佸洖鍏捣
+     */
+    @Log(title = "瀹㈡埛妗f", businessType = BusinessType.OTHER)
+    @PostMapping("/back")
+    public R back(Long id) {
+        return R.ok(customerService.back(id));
+    }
 }
diff --git a/src/main/java/com/ruoyi/basic/controller/CustomerFollowUpController.java b/src/main/java/com/ruoyi/basic/controller/CustomerFollowUpController.java
index 2b70438..a5dcc83 100644
--- a/src/main/java/com/ruoyi/basic/controller/CustomerFollowUpController.java
+++ b/src/main/java/com/ruoyi/basic/controller/CustomerFollowUpController.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.CustomerFollowUpFileDto;
 import com.ruoyi.basic.pojo.CustomerFollowUp;
 import com.ruoyi.basic.pojo.CustomerReturnVisit;
 import com.ruoyi.basic.service.CustomerFollowUpService;
@@ -11,12 +12,10 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.basic.dto.CustomerFollowUpFileDto;
-import com.ruoyi.common.utils.SecurityUtils;
 
 import java.util.List;
 
@@ -31,19 +30,18 @@
  */
 @RestController
 @RequestMapping("/basic/customer-follow")
+@AllArgsConstructor
 public class CustomerFollowUpController extends BaseController {
 
-    @Autowired
-    private CustomerFollowUpService customerFollowUpService;
+    private final CustomerFollowUpService customerFollowUpService;
 
-    @Autowired
-    private CustomerReturnVisitService customerReturnVisitService;
+    private final CustomerReturnVisitService customerReturnVisitService;
 
     /**
      * 鏌ヨ瀹㈡埛璺熻繘鍒楄〃
      */
     @GetMapping("/list")
-    @ApiOperation("鏌ヨ瀹㈡埛璺熻繘鍒楄〃")
+    @Operation(summary = "鏌ヨ瀹㈡埛璺熻繘鍒楄〃")
     public IPage<CustomerFollowUp> list(Page<CustomerFollowUp> page, CustomerFollowUp customerFollowUp) {
         LambdaQueryWrapper<CustomerFollowUp> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(customerFollowUp.getCustomerId() != null, CustomerFollowUp::getCustomerId, customerFollowUp.getCustomerId())
@@ -55,7 +53,7 @@
     /**
      * 鑾峰彇瀹㈡埛璺熻繘璇︾粏淇℃伅
      */
-    @ApiOperation("鑾峰彇瀹㈡埛璺熻繘璇︾粏淇℃伅")
+    @Operation(summary = "鑾峰彇瀹㈡埛璺熻繘璇︾粏淇℃伅")
     @GetMapping(value = "/{id}")
     public AjaxResult getInfo(@PathVariable("id") Integer id) {
         return AjaxResult.success(customerFollowUpService.getFollowUpWithFiles(id));
@@ -65,7 +63,7 @@
      * 鏂板瀹㈡埛璺熻繘
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板瀹㈡埛璺熻繘")
+    @Operation(summary = "鏂板瀹㈡埛璺熻繘")
     @Log(title = "瀹㈡埛璺熻繘-鏂板", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody CustomerFollowUp customerFollowUp) {
         return toAjax(customerFollowUpService.insertCustomerFollowUp(customerFollowUp));
@@ -75,7 +73,7 @@
      * 淇敼瀹㈡埛璺熻繘
      */
     @PutMapping("/edit")
-    @ApiOperation("淇敼瀹㈡埛璺熻繘")
+    @Operation(summary = "淇敼瀹㈡埛璺熻繘")
     @Log(title = "瀹㈡埛璺熻繘-淇敼", businessType = BusinessType.UPDATE)
     public AjaxResult edit(@RequestBody CustomerFollowUp customerFollowUp) {
         return toAjax(customerFollowUpService.updateCustomerFollowUp(customerFollowUp));
@@ -84,7 +82,7 @@
     /**
      * 涓婁紶璺熻繘闄勪欢
      */
-    @ApiOperation("涓婁紶璺熻繘闄勪欢")
+    @Operation(summary = "涓婁紶璺熻繘闄勪欢")
     @PostMapping("/upload/{followUpId}")
     @Log(title = "瀹㈡埛璺熻繘-涓婁紶闄勪欢", businessType = BusinessType.INSERT)
     public AjaxResult uploadFiles(@RequestParam("files") List<MultipartFile> files, @PathVariable Integer followUpId) {
@@ -94,7 +92,7 @@
     /**
      * 涓婁紶璺熻繘闄勪欢锛堝鐢紝鏃營D锛�
      */
-    @ApiOperation("涓婁紶闄勪欢(澶嶇敤)")
+    @Operation(summary = "涓婁紶闄勪欢(澶嶇敤)")
     @PostMapping("/upload")
     @Log(title = "涓婁紶闄勪欢(澶嶇敤)", businessType = BusinessType.INSERT)
     public AjaxResult uploadFiles(@RequestParam("files") List<MultipartFile> files, @RequestParam(required = false) String name) {
@@ -105,7 +103,7 @@
     /**
      * 鎵归噺鏌ヨ闄勪欢鍒楄〃
      */
-    @ApiOperation("鎵归噺鏌ヨ闄勪欢鍒楄〃")
+    @Operation(summary = "鎵归噺鏌ヨ闄勪欢鍒楄〃")
     @PostMapping("/file/list")
     public AjaxResult getFileList(@RequestBody List<Long> ids) {
         return AjaxResult.success(customerFollowUpService.getFollowUpFilesByIds(ids));
@@ -114,7 +112,7 @@
     /**
      * 鍒犻櫎璺熻繘闄勪欢
      */
-    @ApiOperation("鍒犻櫎璺熻繘闄勪欢")
+    @Operation(summary = "鍒犻櫎璺熻繘闄勪欢")
     @DeleteMapping("/file/{fileId}")
     @Log(title = "瀹㈡埛璺熻繘-鍒犻櫎闄勪欢", businessType = BusinessType.DELETE)
     public AjaxResult deleteFile(@PathVariable Integer fileId) {
@@ -125,7 +123,7 @@
     /**
      * 鍒犻櫎瀹㈡埛璺熻繘
      */
-    @ApiOperation("鍒犻櫎瀹㈡埛璺熻繘")
+    @Operation(summary = "鍒犻櫎瀹㈡埛璺熻繘")
     @DeleteMapping("/{id}")
     @Log(title = "瀹㈡埛璺熻繘-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult remove(@PathVariable Integer id) {
@@ -135,7 +133,7 @@
     /**
      * 鏂板/鏇存柊鍥炶鎻愰啋
      */
-    @ApiOperation("鏂板/鏇存柊鍥炶鎻愰啋")
+    @Operation(summary = "鏂板/鏇存柊鍥炶鎻愰啋")
     @PostMapping("/return-visit")
     @Log(title = "鍥炶鎻愰啋-鏂板/鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult saveReturnVisit(@RequestBody CustomerReturnVisit customerReturnVisit) {
@@ -145,7 +143,7 @@
     /**
      * 鑾峰彇鍥炶鎻愰啋璇︽儏
      */
-    @ApiOperation("鑾峰彇鍥炶鎻愰啋璇︽儏")
+    @Operation(summary = "鑾峰彇鍥炶鎻愰啋璇︽儏")
     @GetMapping("/return-visit/{customerId}")
     public AjaxResult getReturnVisit(@PathVariable Integer customerId) {
         return AjaxResult.success(customerReturnVisitService.getByCustomerId(customerId));
@@ -154,7 +152,7 @@
     /**
      * 鏍囪鍥炶鎻愰啋宸茶
      */
-    @ApiOperation("鏍囪鍥炶鎻愰啋宸茶")
+    @Operation(summary = "鏍囪鍥炶鎻愰啋宸茶")
     @PutMapping("/return-visit/read/{id}")
     @Log(title = "鍥炶鎻愰啋-鏍囪宸茶", businessType = BusinessType.UPDATE)
     public AjaxResult markAsRead(@PathVariable Long id) {
diff --git a/src/main/java/com/ruoyi/basic/controller/EnumController.java b/src/main/java/com/ruoyi/basic/controller/EnumController.java
index 235eb26..f4d172b 100644
--- a/src/main/java/com/ruoyi/basic/controller/EnumController.java
+++ b/src/main/java/com/ruoyi/basic/controller/EnumController.java
@@ -5,7 +5,7 @@
 import com.ruoyi.common.utils.EnumUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
 import com.ruoyi.framework.web.domain.R;
-import io.swagger.annotations.Api;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -15,7 +15,7 @@
 import java.util.Map;
 
 @RestController
-@Api(tags = "鏋氫妇鎺ュ彛")
+@Tag(name = "鏋氫妇鎺ュ彛")
 @RequestMapping("/basic/enum")
 public class EnumController {
 
diff --git a/src/main/java/com/ruoyi/basic/controller/ProductController.java b/src/main/java/com/ruoyi/basic/controller/ProductController.java
index 252ab4d..1c5224b 100644
--- a/src/main/java/com/ruoyi/basic/controller/ProductController.java
+++ b/src/main/java/com/ruoyi/basic/controller/ProductController.java
@@ -10,6 +10,7 @@
 import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.basic.service.IProductModelService;
 import com.ruoyi.basic.service.IProductService;
+import com.ruoyi.basic.vo.ProductModelVo;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -17,15 +18,12 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.service.ISalesLedgerProductService;
-import com.ruoyi.sales.service.ISalesLedgerService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
@@ -34,9 +32,7 @@
 public class ProductController extends BaseController {
 
     private IProductService productService;
-
     private IProductModelService productModelService;
-    @Autowired
     private ISalesLedgerProductService salesLedgerProductService;
     /**
      * 鏌ヨ浜у搧
@@ -118,9 +114,9 @@
         return productModelService.modelListPage(page, productDto);
     }
 
-    @ApiOperation("鍒嗛〉鏌ヨ鎵�鏈変骇鍝佸瀷鍙�")
+    @Operation(summary = "鍒嗛〉鏌ヨ鎵�鏈変骇鍝佸瀷鍙�")
     @GetMapping("/pageModel")
-    public IPage<ProductModel> listPageProductModel(Page<ProductModel> page, ProductModel productModel) {
+    public IPage<ProductModelVo> listPageProductModel(Page<ProductModelVo> page, ProductModel productModel) {
         return productService.listPageProductModel(page, productModel);
     }
 
@@ -137,7 +133,7 @@
      * 浜у搧瀵煎叆妯℃澘
      */
     @GetMapping("/export")
-    @ApiOperation("浜у搧瀵煎叆妯℃澘")
+    @Operation(summary = "浜у搧瀵煎叆妯℃澘")
     @Log(title = "浜у搧瀵煎叆妯℃澘", businessType = BusinessType.EXPORT)
     public void importProduct(HttpServletResponse response) {
         ExcelUtil<ProductModelExportDto> excelUtil = new ExcelUtil<>(ProductModelExportDto.class);
diff --git a/src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java b/src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java
new file mode 100644
index 0000000..79ae5d4
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/controller/StorageAttachmentController.java
@@ -0,0 +1,53 @@
+package com.ruoyi.basic.controller;
+
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
+import com.ruoyi.basic.service.StorageAttachmentService;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@AllArgsConstructor
+@Tag(name = "閫氱敤涓婁紶")
+@RequestMapping("/storageAttachment")
+public class StorageAttachmentController {
+    private StorageAttachmentService storageAttachmentService;
+
+    /**
+     * 鍒嗛〉鏌ヨ閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
+     *
+     * @param storageAttachmentDTO 鍏宠仈璁板綍淇℃伅
+     * @return 鍒嗛〉缁撴灉
+     */
+    @GetMapping("/list")
+    @Operation(summary = "鍒嗛〉鏌ヨ閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�")
+    public R list(StorageAttachmentDTO storageAttachmentDTO) {
+        return R.ok(storageAttachmentService.list(storageAttachmentDTO));
+    }
+
+    /**
+     * 鍒犻櫎閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
+     *
+     * @param ids 鏂囦欢id鍒楄〃
+     * @return 鍒犻櫎缁撴灉
+     */
+    @DeleteMapping("/delete")
+    @Operation(summary = "鍒犻櫎閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�")
+    public R batchDelete(@RequestBody List<Long> ids) {
+        return R.ok(storageAttachmentService.batchDeleteStorageAttachment(ids));
+    }
+
+    /**
+     * 淇濆瓨閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
+     */
+    @PostMapping("/add")
+    @Operation(summary = "淇濆瓨閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�")
+    public R add(@RequestBody StorageAttachmentDTO storageAttachmentDTO) {
+        storageAttachmentService.saveStorageAttachment(storageAttachmentDTO);
+        return R.ok();
+    }
+}
diff --git a/src/main/java/com/ruoyi/basic/controller/SupplierManageController.java b/src/main/java/com/ruoyi/basic/controller/SupplierManageController.java
index 32cad29..1a58500 100644
--- a/src/main/java/com/ruoyi/basic/controller/SupplierManageController.java
+++ b/src/main/java/com/ruoyi/basic/controller/SupplierManageController.java
@@ -2,26 +2,25 @@
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.basic.dto.SupplierManageDto;
-import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.pojo.SupplierManage;
 import com.ruoyi.basic.service.ISupplierService;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/system/supplier")
+@AllArgsConstructor
 public class SupplierManageController {
 
-    @Autowired
     private ISupplierService supplierService;
 
     /**
diff --git a/src/main/java/com/ruoyi/basic/controller/SupplierManageFileController.java b/src/main/java/com/ruoyi/basic/controller/SupplierManageFileController.java
index ff54830..2d43f65 100644
--- a/src/main/java/com/ruoyi/basic/controller/SupplierManageFileController.java
+++ b/src/main/java/com/ruoyi/basic/controller/SupplierManageFileController.java
@@ -7,7 +7,7 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/basic/dto/CustomerDto.java b/src/main/java/com/ruoyi/basic/dto/CustomerDto.java
index a8161da..d75de55 100644
--- a/src/main/java/com/ruoyi/basic/dto/CustomerDto.java
+++ b/src/main/java/com/ruoyi/basic/dto/CustomerDto.java
@@ -21,4 +21,12 @@
 
     private List<CustomerFollowUpDto> followUpList;
 
-}
+    private String usageUserName;
+
+    private String togetherUserNames;
+
+    /**
+     * 鍏变韩鐢ㄦ埛ID鍒楄〃
+     */
+    private List<Long> userIds;
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/dto/ProductModelDto.java b/src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
index 53b3b5d..4a88508 100644
--- a/src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
+++ b/src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
@@ -1,7 +1,7 @@
 package com.ruoyi.basic.dto;
 
 import com.ruoyi.basic.pojo.ProductModel;
-import com.ruoyi.production.dto.ProductStructureDto;
+import com.ruoyi.production.bean.dto.ProductStructureDto;
 import lombok.Data;
 
 import java.util.List;
diff --git a/src/main/java/com/ruoyi/basic/dto/StorageAttachmentDTO.java b/src/main/java/com/ruoyi/basic/dto/StorageAttachmentDTO.java
new file mode 100644
index 0000000..ef97145
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/dto/StorageAttachmentDTO.java
@@ -0,0 +1,14 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.StorageAttachment;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class StorageAttachmentDTO extends StorageAttachment {
+    /**
+     * 瀛樺偍鏂囦欢鍒楄〃
+     */
+    private List<StorageBlobDTO> storageBlobDTOs;
+}
diff --git a/src/main/java/com/ruoyi/basic/dto/StorageAttachmentVO.java b/src/main/java/com/ruoyi/basic/dto/StorageAttachmentVO.java
new file mode 100644
index 0000000..232ffe6
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/dto/StorageAttachmentVO.java
@@ -0,0 +1,14 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.StorageAttachment;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class StorageAttachmentVO extends StorageAttachment {
+    /**
+     * 瀛樺偍鏂囦欢鍒楄〃
+     */
+    private List<StorageBlobVO> storageBlobVOS;
+}
diff --git a/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java b/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java
index 17a7d71..52eaaa5 100644
--- a/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java
+++ b/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java
@@ -5,7 +5,18 @@
 
 @Data
 public class StorageBlobDTO extends StorageBlob {
-    private String url;
+    /**
+     * 棰勮鍦板潃
+     */
+    private String previewURL;
 
-    private String downloadUrl;
+    /**
+     * 涓嬭浇鍦板潃
+     */
+    private String downloadURL;
+
+    /**
+     * 鏂囦欢绫诲瀷
+     */
+    private String application;
 }
diff --git a/src/main/java/com/ruoyi/basic/dto/StorageBlobVO.java b/src/main/java/com/ruoyi/basic/dto/StorageBlobVO.java
new file mode 100644
index 0000000..75eed4f
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/dto/StorageBlobVO.java
@@ -0,0 +1,19 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.StorageBlob;
+import lombok.Data;
+
+@Data
+public class StorageBlobVO extends StorageBlob {
+    /**
+     * 棰勮鍦板潃
+     */
+    private String previewURL;
+
+    /**
+     * 涓嬭浇鍦板潃
+     */
+    private String downloadURL;
+
+    private Long storageAttachmentId;
+}
diff --git a/src/main/java/com/ruoyi/basic/dto/SupplierManageDto.java b/src/main/java/com/ruoyi/basic/dto/SupplierManageDto.java
index 30044ad..8e2de0b 100644
--- a/src/main/java/com/ruoyi/basic/dto/SupplierManageDto.java
+++ b/src/main/java/com/ruoyi/basic/dto/SupplierManageDto.java
@@ -1,12 +1,12 @@
 package com.ruoyi.basic.dto;
 
 import com.ruoyi.basic.pojo.SupplierManage;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 @Data
 public class SupplierManageDto extends SupplierManage {
 
-    @ApiModelProperty(value = "缁存姢浜哄憳鍚嶇О")
+    @Schema(description = "缁存姢浜哄憳鍚嶇О")
     private String maintainUserName;
 }
diff --git a/src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java b/src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java
new file mode 100644
index 0000000..8cdf321
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/enums/ApplicationTypeEnum.java
@@ -0,0 +1,29 @@
+package com.ruoyi.basic.enums;
+
+public enum ApplicationTypeEnum {
+    IMAGE("image"),
+    FILE("file"),
+    AFTER_FILE("after_file"),
+    BEFORE_FILE("before_file"),
+    APK("apk");
+
+
+    private final String type;
+    ApplicationTypeEnum(String type) { this.type = type; }
+    public String getType() { return type; }
+
+    /**
+     * 鏍规嵁 type 鍊艰幏鍙栧搴旂殑鏋氫妇瀹炰緥
+     * @param type 搴旂敤绫诲瀷瀛楃涓�
+     * @return 瀵瑰簲鐨� ApplicationTypeEnum 鏋氫妇瀹炰緥
+     * @throws RuntimeException 濡傛灉 type 鏃犳晥
+     */
+    public static ApplicationTypeEnum getByType(String type) {
+        for (ApplicationTypeEnum enumValue : ApplicationTypeEnum.values()) {
+            if (enumValue.getType().equals(type)) {
+                return enumValue;
+            }
+        }
+        throw new RuntimeException("鏃犳晥鐨勫簲鐢ㄧ被鍨�: " + type);
+    }
+}
diff --git a/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
new file mode 100644
index 0000000..d7d0649
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -0,0 +1,231 @@
+package com.ruoyi.basic.enums;
+
+public enum RecordTypeEnum {
+    SHIPPING_INFO("shipping_info"),
+    INSPECTION_TASK("inspection_task"),
+    PDA_VERSION("pda_version"),
+    SALES_LEDGER("sales_ledger"),
+    SUPPLIER_MANAGE("supplier_manage"),
+    APPROVAL_PROCESS("approval_process"),
+    QR_CODE_SCAN_RECORDS("qr_code_scan_records"),
+    // Water Record
+    WATER_RECORD("water_record"),
+    // Warehouse
+    WAREHOUSE_GOODS_SHELVES_ROWCOL("warehouse_goods_shelves_rowcol"),
+    WAREHOUSE_GOODS_SHELVES("warehouse_goods_shelves"),
+    DOCUMENTATION_FILE("documentation_file"),
+    DOCUMENTATION_RETURN_MANAGEMENT("documentation_return_management"),
+    DOCUMENTATION_BORROW_MANAGEMENT("documentation_borrow_management"),
+    DOCUMENTATION("documentation"),
+    WAREHOUSE("warehouse"),
+    DOCUMENT_CLASSIFICATION("document_classification"),
+    // Technology
+    TECHNOLOGY_ROUTING_OPERATION_PARAM("technology_routing_operation_param"),
+    TECHNOLOGY_ROUTING("technology_routing"),
+    TECHNOLOGY_ROUTING_OPERATION("technology_routing_operation"),
+    TECHNOLOGY_BOM("technology_bom"),
+    TECHNOLOGY_PARAM("technology_param"),
+    TECHNOLOGY_OPERATION_PARAM("technology_operation_param"),
+    TECHNOLOGY_OPERATION("technology_operation"),
+    TECHNOLOGY_BOM_STRUCTURE("technology_bom_structure"),
+    // Stock
+    STOCK_OUT_RECORD("stock_out_record"),
+    STOCK_UNINVENTORY("stock_uninventory"),
+    STOCK_INVENTORY("stock_inventory"),
+    STOCK_IN_RECORD("stock_in_record"),
+    // Staff
+    STAFF_WORK_EXPERIENCE("staff_work_experience"),
+    STAFF_SALARY_MAIN("staff_salary_main"),
+    STAFF_SCHEDULING("staff_scheduling"),
+    STAFF_SALARY_DETAIL("staff_salary_detail"),
+    STAFF_ON_JOB("staff_on_job"),
+    STAFF_LEAVE("staff_leave"),
+    STAFF_CONTRACT("staff_contract"),
+    STAFF_EMERGENCY_CONTACT("staff_emergency_contact"),
+    STAFF_EDUCATION("staff_education"),
+    SCHEME_APPLICABLE_STAFF("scheme_applicable_staff"),
+    PERSONAL_SHIFT("personal_shift"),
+    SCHEME_INSURANCE_DETAIL("scheme_insurance_detail"),
+    PERSONAL_ATTENDANCE_RECORDS("personal_attendance_records"),
+    PERSONAL_ATTENDANCE_LOCATION_CONFIG("personal_attendance_location_config"),
+    BANK("bank"),
+    HOLIDAY_APPLICATION("holiday_application"),
+    // Sales
+    SHIPMENT_APPROVAL("shipment_approval"),
+    SALESPERSON_MANAGEMENT("salesperson_management"),
+    SALES_QUOTATION_PRODUCT("sales_quotation_product"),
+    SALES_QUOTATION("sales_quotation"),
+    SALES_LEDGER_PRODUCT("sales_ledger_product"),
+    PURCHASE_LEDGER_FILE("purchase_ledger_file"),
+    RECEIPT_PAYMENT("receipt_payment"),
+    PAYMENT_SHIPPING("payment_shipping"),
+    INVOICE_REGISTRATION_PRODUCT("invoice_registration_product"),
+    LOSS("loss"),
+    INVOICE_REGISTRATION("invoice_registration"),
+    INVOICE_LEDGER_FILE("invoice_ledger_file"),
+    INVOICE_LEDGER("invoice_ledger"),
+    COMMON_FILE("common_file"),
+    // Safe
+    SAFE_TRAINING_FILE("safe_training_file"),
+    SAFE_TRAINING_DETAILS("safe_training_details"),
+    SAFE_TRAINING("safe_training"),
+    SAFE_HIDDEN_FILE("safe_hidden_file"),
+    SAFE_HAZARD_RECORD("safe_hazard_record"),
+    SAFE_HIDDEN("safe_hidden"),
+    SAFE_HAZARD("safe_hazard"),
+    SAFE_CONTINGENCY_PLAN("safe_contingency_plan"),
+    SAFE_CERTIFICATION_FILE("safe_certification_file"),
+    SAFE_CERTIFICATION("safe_certification"),
+    SAFE_ACCIDENT("safe_accident"),
+    // Quality
+    QUALITY_UNQUALIFIED("quality_unqualified"),
+    QUALITY_TEST_STANDARD_PARAM("quality_test_standard_param"),
+    QUALITY_TEST_STANDARD_BINDING("quality_test_standard_binding"),
+    QUALITY_TEST_STANDARD("quality_test_standard"),
+    QUALITY_INSPECT_FILE("quality_inspect_file"),
+    QUALITY_INSPECT_PARAM("quality_inspect_param"),
+    QUALITY_INSPECT("quality_inspect"),
+    // Purchase
+    TICKET_REGISTRATION("ticket_registration"),
+    PURCHASE_RETURN_ORDER_PRODUCTS("purchase_return_order_products"),
+    PURCHASE_RETURN_ORDERS("purchase_return_orders"),
+    SALES_LEDGER_PRODUCT_TEMPLATE("sales_ledger_product_template"),
+    PURCHASE_LEDGER("purchase_ledger"),
+    PURCHASE_LEDGER_TEMPLATE("purchase_ledger_template"),
+    PRODUCT_RECORD("product_record"),
+    PAYMENT_REGISTRATION("payment_registration"),
+    INVOICE_PURCHASE("invoice_purchase"),
+    // Project Management
+    SHIPPING_ADDRESS("shipping_address"),
+    ROLES("roles"),
+    PLAN("plan"),
+    PLAN_NODE("plan_node"),
+    INFO_STAGE("info_stage"),
+    CONTRACT_INFO("contract_info"),
+    INFO("info"),
+    // Production
+    PRODUCTION_PRODUCT_OUTPUT("production_product_output"),
+    PRODUCTION_ORDER_ROUTING_OPERATION("production_order_routing_operation"),
+    PRODUCTION_PRODUCT_INPUT("production_product_input"),
+    PRODUCTION_PRODUCT_MAIN("production_product_main"),
+    PRODUCTION_PLAN("production_plan"),
+    PRODUCTION_ORDER_ROUTING_OPERATION_PARAM("production_order_routing_operation_param"),
+    PRODUCTION_ORDER_ROUTING("production_order_routing"),
+    PRODUCTION_ORDER_PICK_RECORD("production_order_pick_record"),
+    PRODUCTION_ORDER_PICK("production_order_pick"),
+    PRODUCTION_ORDER_BOM("production_order_bom"),
+    PRODUCTION_OPERATION_TASK("production_operation_task"),
+    PRODUCTION_ORDER("production_order"),
+    PRODUCTION_ACCOUNT("production_account"),
+    PRODUCTION_BOM_STRUCTURE("production_bom_structure"),
+    PRODUCTION_OPERATION_MAIN_PARAM("production_operation_main_param"),
+    // Procurement Record
+    RETURN_SALE_PRODUCT("return_sale_product"),
+    PROCUREMENT_PLAN("procurement_plan"),
+    PROCUREMENT_RECORD_OUT("procurement_record_out"),
+    PROCUREMENT_RECORD_STORAGE("procurement_record_storage"),
+    RETURN_MANAGEMENT("return_management"),
+    PROCUREMENT_PRICE_MANAGEMENT("procurement_price_management"),
+    GAS_TANK_WARNING("gas_tank_warning"),
+    CUSTOM_STORAGE("custom_storage"),
+    PROCUREMENT_EXCEPTION_RECORD("procurement_exception_record"),
+    INBOUND_MANAGEMENT("inbound_management"),
+    // Office Supplies
+    OFFICE_SUPPLIES("office_supplies"),
+    // OA
+    OA_PROJECT_PHASE_TASK("oa_project_phase_task"),
+    OA_PROJECT("oa_project"),
+    OA_PROJECT_PHASE("oa_project_phase"),
+    // Measuring Instrument Ledger
+    SPARE_PARTS("spare_parts"),
+    MEASURING_INSTRUMENT_LEDGER_RECORD("measuring_instrument_ledger_record"),
+    MEASURING_INSTRUMENT_LEDGER("measuring_instrument_ledger"),
+    SPARE_PARTS_REQUISITION_RECORD("spare_parts_requisition_record"),
+    // Labor Issue
+    LABOR_ISSUE("labor_issue"),
+    // Inspection Task
+    TIMING_TASK("timing_task"),
+    QR_CODE("qr_code"),
+    // Equipment Energy Consumption
+    ENERGY_PERIOD("energy_period"),
+    EQUIPMENT_ENERGY_CONSUMPTION("equipment_energy_consumption"),
+    ELECTRICITY_CONSUMPTION_AREA("electricity_consumption_area"),
+    // Device
+    MAINTENANCE_TASK("maintenance_task"),
+    DEVICE_REPAIR("device_repair"),
+    DEVICE_MAINTENANCE_FILE("device_maintenance_file"),
+    DEVICE_DEFECT_RECORD("device_defect_record"),
+    DEVICE_MAINTENANCE("device_maintenance"),
+    DEVICE_LEDGER("device_ledger"),
+    // Customer Visits
+    CUSTOMER_VISITS("customer_visits"),
+    // Compensation Performance
+    COMPENSATION_PERFORMANCE("compensation_performance"),
+    // Collaborative Approval
+    STAFF_CONTACTS_PERSONAL("staff_contacts_personal"),
+    SEAL_APPLICATION_MANAGEMENT("seal_application_management"),
+    RULES_REGULATIONS_MANAGEMENT_FILE("rules_regulations_management_file"),
+    RULES_REGULATIONS_MANAGEMENT("rules_regulations_management"),
+    READING_STATUS("reading_status"),
+    NOTICE("notice"),
+    NOTICE_TYPE("notice_type"),
+    MEET_DRAFT("meet_draft"),
+    MEETING_ROOM("meeting_room"),
+    MEETING_MINUTES("meeting_minutes"),
+    MEET_APPLICATION("meet_application"),
+    DUTY_PLAN("duty_plan"),
+    // Basic
+    SUPPLIER_MANAGE_FILE("supplier_manage_file"),
+    PRODUCT_MODEL("product_model"),
+    CUSTOMER_RETURN_VISIT("customer_return_visit"),
+    PRODUCT("product"),
+    CUSTOMER("customer"),
+    CUSTOMER_PRIVATE_POOL("customer_private_pool"),
+    CUSTOMER_FOLLOW_UP_FILE("customer_follow_up_file"),
+    CUSTOMER_FOLLOW_UP("customer_follow_up"),
+    CUSTOMER_PRIVATE("customer_private"),
+    // Approve
+    WORKING_HOURS_SETTING("working_hours_setting"),
+    OVERTIME_SETTING("overtime_setting"),
+    RPA_PROCESS_AUTOMATION("rpa_process_automation"),
+    HOLIDAY_SETTINGS("holiday_settings"),
+    ONLINE_MEETING("online_meeting"),
+    KNOWLEDGE_BASE("knowledge_base"),
+    NOTIFICATION_MANAGEMENT("notification_management"),
+    APPROVE_NODE("approve_node"),
+    APPROVE_PROCESS("approve_process"),
+    APPROVE_PROCESS_CONFIG_NODE("approve_process_config_node"),
+    APPROVE_LOG("approve_log"),
+    ANNUAL_LEAVE_SETTING("annual_leave_setting"),
+    FILE_SHARING("file_sharing"),
+    // After Sales Service
+    AFTER_SALES_SERVICE("after_sales_service"),
+    AFTER_SALES_SERVICE_FILE("after_sales_service_file"),
+    AFTER_SALES_NEAR_EXPIRY("after_sales_near_expiry"),
+    // Account
+    ACCOUNT_INCOME("account_income"),
+    BORROW_INFO("borrow_info"),
+    SALES_REFUND_AMOUNT_ORDER("sales_refund_amount_order"),
+    SALES_RECEIPT_RETURN("sales_receipt_return"),
+    ACCOUNT_EXPENSE("account_expense"),
+    ACCOUNT_FILE("account_file");
+
+    private final String type;
+    RecordTypeEnum(String type) { this.type = type; }
+    public String getType() { return type; }
+
+    /**
+     * 鏍规嵁 type 鍊艰幏鍙栧搴旂殑鏋氫妇瀹炰緥
+     * @param type 璁板綍绫诲瀷瀛楃涓�
+     * @return 瀵瑰簲鐨� RecordTypeEnum 鏋氫妇瀹炰緥
+     * @throws RuntimeException 濡傛灉 type 鏃犳晥
+     */
+    public static RecordTypeEnum getByType(String type) {
+        for (RecordTypeEnum enumValue : RecordTypeEnum.values()) {
+            if (enumValue.getType().equals(type)) {
+                return enumValue;
+            }
+        }
+        throw new RuntimeException("鏃犳晥鐨勮褰曠被鍨�: " + type);
+    }
+}
diff --git a/src/main/java/com/ruoyi/basic/excel/SupplierManageExcelDto.java b/src/main/java/com/ruoyi/basic/excel/SupplierManageExcelDto.java
index 29e1af0..87b197f 100644
--- a/src/main/java/com/ruoyi/basic/excel/SupplierManageExcelDto.java
+++ b/src/main/java/com/ruoyi/basic/excel/SupplierManageExcelDto.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
diff --git a/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java b/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
index 1946f26..2605737 100644
--- a/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
+++ b/src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java
@@ -1,7 +1,13 @@
 package com.ruoyi.basic.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.CustomerDto;
 import com.ruoyi.basic.pojo.Customer;
+import com.ruoyi.basic.vo.CustomerVo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -11,6 +17,7 @@
  * @author ruoyi
  * @date 2025-05-07
  */
+@Mapper
 public interface CustomerMapper extends BaseMapper<Customer>
 {
     /**
@@ -60,4 +67,8 @@
      * @return 缁撴灉
      */
     int deleteCustomerByIds(Long[] ids);
-}
+
+    IPage<CustomerVo> listPage(Page<CustomerDto> page, @Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId);
+
+    List<CustomerVo> list(@Param("c") CustomerDto customer, @Param("loginUserId") Long loginUserId);
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/mapper/CustomerUserMapper.java b/src/main/java/com/ruoyi/basic/mapper/CustomerUserMapper.java
new file mode 100644
index 0000000..84aebac
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/mapper/CustomerUserMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.basic.pojo.CustomerUser;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 瀹㈡埛鍏变韩Mapper鎺ュ彛
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @date 2026-04-29
+ */
+@Mapper
+public interface CustomerUserMapper extends BaseMapper<CustomerUser> {
+}
diff --git a/src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java b/src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java
index bddcca4..36876d0 100644
--- a/src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java
+++ b/src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.basic.pojo.ProductModel;
+import com.ruoyi.basic.vo.ProductModelVo;
 import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
 import org.apache.ibatis.annotations.Param;
 
@@ -19,7 +20,7 @@
  */
 public interface ProductModelMapper extends BaseMapper<ProductModel> {
 
-    IPage<ProductModel> listPageProductModel(Page<ProductModel> page, @Param("c") ProductModel productModel);
+    IPage<ProductModelVo> listPageProductModel(Page<ProductModelVo> page, @Param("c") ProductModel productModel);
 
     IPage<ProductModel> listPageProductionStock(Page<ProductModel> page, @Param("req") ProcurementPageDto req);
 
diff --git a/src/main/java/com/ruoyi/basic/mapper/StorageBlobMapper.java b/src/main/java/com/ruoyi/basic/mapper/StorageBlobMapper.java
index 756b4b9..5f84cb7 100644
--- a/src/main/java/com/ruoyi/basic/mapper/StorageBlobMapper.java
+++ b/src/main/java/com/ruoyi/basic/mapper/StorageBlobMapper.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.basic.pojo.StorageBlob;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>
@@ -15,4 +16,9 @@
 @Mapper
 public interface StorageBlobMapper extends BaseMapper<StorageBlob> {
 
+    java.util.List<StorageBlob> selectOrphanBlobsByIdRange(@Param("lastId") long lastId, @Param("limit") int limit);
+
+    int deleteByIdList(@Param("ids") java.util.List<Long> ids);
+
+    java.util.List<String> selectExistingUidFilenames(@Param("fileNames") java.util.List<String> fileNames);
 }
diff --git a/src/main/java/com/ruoyi/basic/pojo/Customer.java b/src/main/java/com/ruoyi/basic/pojo/Customer.java
index 101d72a..6a8e302 100644
--- a/src/main/java/com/ruoyi/basic/pojo/Customer.java
+++ b/src/main/java/com/ruoyi/basic/pojo/Customer.java
@@ -7,9 +7,10 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import org.checkerframework.checker.units.qual.A;
 
 /**
  * 瀹㈡埛妗f瀵硅薄 customer
@@ -105,15 +106,32 @@
     @TableField(exist = false)
     private String addressPhone;
 
-    @ApiModelProperty(value = "閾惰鍩烘湰鎴�")
+    @Schema(description = "閾惰鍩烘湰鎴�")
     @Excel(name = "閾惰鍩烘湰鎴�")
     private String basicBankAccount;
 
-    @ApiModelProperty(value = "閾惰璐﹀彿")
+    @Schema(description = "閾惰璐﹀彿")
     @Excel(name = "閾惰璐﹀彿")
     private String bankAccount;
 
-    @ApiModelProperty(value = "寮�鎴疯鍙�")
+    @Schema(description = "寮�鎴疯鍙�")
     @Excel(name = "寮�鎴疯鍙�")
     private String bankCode;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "浣跨敤鐢ㄦ埛")
+    private Long usageUser;
+    @Schema(description = "浣跨敤鐘舵��")
+    private Long usageStatus;
+
+    @Schema(description = "绫诲瀷 0 绉佹捣瀹㈡埛 1 鍏捣瀹㈡埛")
+    private Integer type;
+
+    @Schema(description = "鏄惁琚垎閰嶏細0-鏈垎閰嶏紝1-宸插垎閰�")
+    private Integer isAssigned;
 }
diff --git a/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUp.java b/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUp.java
index a64bf66..5d9dfe3 100644
--- a/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUp.java
+++ b/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUp.java
@@ -1,10 +1,14 @@
 package com.ruoyi.basic.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
@@ -31,9 +35,9 @@
     private Integer id;
 
     /**
-     * 鍏宠仈鐨勫鎴稩D
+     * 鍏宠仈鐨勭娴穒d
      */
-    private Integer customerId;
+    private Long customerId;
 
     /**
      * 璺熻繘鏂瑰紡
@@ -49,6 +53,7 @@
      * 璺熻繘鏃堕棿
      */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime followUpTime;
 
     /**
@@ -82,4 +87,11 @@
      */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUpFile.java b/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUpFile.java
index 2e33d08..bf89dd4 100644
--- a/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUpFile.java
+++ b/src/main/java/com/ruoyi/basic/pojo/CustomerFollowUpFile.java
@@ -1,5 +1,7 @@
 package com.ruoyi.basic.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -78,4 +80,7 @@
      * 绉熸埛ID
      */
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/pojo/CustomerReturnVisit.java b/src/main/java/com/ruoyi/basic/pojo/CustomerReturnVisit.java
index 9ddfc42..ddd3d4b 100644
--- a/src/main/java/com/ruoyi/basic/pojo/CustomerReturnVisit.java
+++ b/src/main/java/com/ruoyi/basic/pojo/CustomerReturnVisit.java
@@ -1,5 +1,7 @@
 package com.ruoyi.basic.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
@@ -34,7 +36,7 @@
     /**
      * 鍏宠仈瀹㈡埛ID
      */
-    private Integer customerId;
+    private Long customerId;
 
     /**
      * 鎻愰啋寮�鍏� (0:鍏抽棴, 1:寮�鍚�)
@@ -89,4 +91,7 @@
      */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime updateTime;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/pojo/CustomerUser.java b/src/main/java/com/ruoyi/basic/pojo/CustomerUser.java
new file mode 100644
index 0000000..901b0ce
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/pojo/CustomerUser.java
@@ -0,0 +1,43 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@TableName(value = "customer_user")
+@Data
+public class CustomerUser implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 搴忓彿
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 瀹㈡埛id
+     */
+    private Long customerId;
+
+    /**
+     * 鐢ㄦ埛id
+     */
+    private Long userId;
+
+    /**
+     * 绉熸埛id
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Long tenantId;
+
+    /**
+     * 褰曞叆鏃堕棿
+     */
+    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+}
diff --git a/src/main/java/com/ruoyi/basic/pojo/Product.java b/src/main/java/com/ruoyi/basic/pojo/Product.java
index 6b4e14b..17f0fea 100644
--- a/src/main/java/com/ruoyi/basic/pojo/Product.java
+++ b/src/main/java/com/ruoyi/basic/pojo/Product.java
@@ -1,7 +1,7 @@
 package com.ruoyi.basic.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 @Data
@@ -26,7 +26,17 @@
      */
     private String productName;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(exist = false)
+    private Long[] deptIds;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
index 069b665..f0e9470 100644
--- a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
+++ b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -2,15 +2,16 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 @Data
 @TableName("product_model")
-public class ProductModel {
+public class ProductModel implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
@@ -36,6 +37,10 @@
     @Excel(name = "瑙勬牸鍨嬪彿")
     private String model;
 
+    @Excel(name = "浜у搧缂栫爜")
+    @TableField("product_code")
+    private String productCode;
+
     /**
      * 鍗曚綅
      */
@@ -48,7 +53,7 @@
     @Excel(name = "鐢熶骇鐐掓満")
     private String speculativeTradingName;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
     @TableField(exist = false)
@@ -63,4 +68,15 @@
 
     @TableField(exist = false)
     private LocalDateTime createTime;
+
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "椤堕儴鐖朵骇鍝乮d")
+    @TableField(exist = false)
+    private Long topProductParentId;
 }
diff --git a/src/main/java/com/ruoyi/basic/pojo/StorageAttachment.java b/src/main/java/com/ruoyi/basic/pojo/StorageAttachment.java
index 1dd7bc7..82d1d8f 100644
--- a/src/main/java/com/ruoyi/basic/pojo/StorageAttachment.java
+++ b/src/main/java/com/ruoyi/basic/pojo/StorageAttachment.java
@@ -2,17 +2,15 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.Date;
+import java.time.LocalDateTime;
 
 /**
  * 閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭� 瀹炰綋绫�
  *
- * @author ruoyi
- * @date 2025-05-29
  */
 @Data
 @TableName("storage_attachment")
@@ -20,24 +18,18 @@
 
     private static final long serialVersionUID = 1L;
 
-    /**
-     *
-     */
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
     /** 鍒涘缓鏃堕棿 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @TableField(fill = FieldFill.INSERT)
-    private Date createTime;
+    private LocalDateTime createTime;
 
     /** 鏇存柊鏃堕棿 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @TableField(fill = FieldFill.INSERT_UPDATE)
-    private Date updateTime;
-
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
+    private LocalDateTime updateTime;
 
     /**
      * 閫昏緫鍒犻櫎
@@ -48,29 +40,20 @@
      * 鍏宠仈鐨勮褰曠被鍨�
      */
     @TableField(value = "record_type")
-    private Long recordType;
+    private String  recordType;
     /**
      * 鍏宠仈鐨勮褰昳d
      */
     @TableField(value = "record_id")
     private Long recordId;
     /**
-     * 绫诲瀷鍚嶇О, 濡�: file, avatar (鍖哄垎鍚屼竴鏉¤褰曚笉鍚岀被鍨嬬殑闄勪欢)
+     * 鏂囦欢鐢ㄩ��, 濡�: file, avatar (鍖哄垎鍚屼竴鏉¤褰曚笉鍚岀被鍨嬬殑闄勪欢)
      */
-    @TableField(value = "name")
-    private String name;
+    @TableField(value = "application")
+    private String application;
     /**
      * 鍏宠仈storage_blob璁板綍id
      */
     @TableField(value = "storage_blob_id")
     private Long storageBlobId;
-
-    @TableField(exist = false)
-    private StorageBlobDTO storageBlobDTO;
-
-    public StorageAttachment(String fileType, Long recordType, Long recordId) {
-        this.name = fileType;
-        this.recordType = recordType;
-        this.recordId = recordId;
-    }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java b/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java
index 6bf6fc6..7f7e961 100644
--- a/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java
+++ b/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java
@@ -1,20 +1,13 @@
 package com.ruoyi.basic.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serializable;
-import java.time.LocalDateTime;
-import java.util.Date;
 
 /**
  * 閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭� 瀹炰綋绫�
  *
- * @author ruoyi
- * @date 2025-05-29
  */
 @Data
 @TableName("storage_blob")
@@ -22,9 +15,6 @@
 
     private static final long serialVersionUID = 1L;
 
-    /**
-     *
-     */
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
@@ -45,15 +35,11 @@
     private String originalFilename;
 
     /**
-     * 瀛樺偍妗朵腑
+     * 鍞竴鏂囦欢鍚嶇О
      */
-    @TableField(value = "bucket_filename")
-    private String bucketFilename;
-    /**
-     * 瀛樺偍妗跺悕
-     */
-    @TableField(value = "bucket_name")
-    private String bucketName;
+    @TableField(value = "uid_filename")
+    private String uidFilename;
+
     /**
      * 璧勬簮灏哄(瀛楄妭)
      */
@@ -61,32 +47,8 @@
     private Long byteSize;
 
     /**
-     * 0鐢熶骇鍓� 1鐢熶骇鍚� 2鐢熶骇闂
+     * 鏂囦欢璺緞
      */
-    @TableField(value = "type")
-    private Long type;
-
-    /**
-     * 绉熸埛ID
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-    @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
-    private Integer createUser;
-
-    @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime createTime;
-
-    @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
-    private Integer updateUser;
-
-    @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
+    @TableField(value = "path")
+    private String path;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/pojo/SupplierManage.java b/src/main/java/com/ruoyi/basic/pojo/SupplierManage.java
index ccc2d6f..fa10c92 100644
--- a/src/main/java/com/ruoyi/basic/pojo/SupplierManage.java
+++ b/src/main/java/com/ruoyi/basic/pojo/SupplierManage.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDate;
@@ -16,71 +16,74 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "渚涘簲鍟嗗悕绉�")
+    @Schema(description = "渚涘簲鍟嗗悕绉�")
     @Excel(name = "渚涘簲鍟嗗悕绉�")
     private String supplierName;
 
-    @ApiModelProperty(value = "绾崇◣浜鸿瘑鍒彿")
+    @Schema(description = "绾崇◣浜鸿瘑鍒彿")
     @Excel(name = "绾崇◣浜鸿瘑鍒彿")
     private String taxpayerIdentificationNum;
 
-    @ApiModelProperty(value = "鍏徃鍦板潃")
+    @Schema(description = "鍏徃鍦板潃")
     @Excel(name = "鍏徃鍦板潃")
     private String companyAddress;
 
-    @ApiModelProperty(value = "鍏徃鐢佃瘽")
+    @Schema(description = "鍏徃鐢佃瘽")
     @Excel(name = "鍏徃鐢佃瘽")
     private String companyPhone;
 
-    @ApiModelProperty(value = "寮�鎴疯")
+    @Schema(description = "寮�鎴疯")
     @Excel(name = "寮�鎴疯")
     private String bankAccountName;
 
-    @ApiModelProperty(value = "璐﹀彿")
+    @Schema(description = "璐﹀彿")
     @Excel(name = "璐﹀彿")
     private String bankAccountNum;
 
-    @ApiModelProperty(value = "鑱旂郴浜�")
+    @Schema(description = "鑱旂郴浜�")
     @Excel(name = "鑱旂郴浜�")
     private String contactUserName;
 
-    @ApiModelProperty(value = "鑱旂郴鐢佃瘽")
+    @Schema(description = "鑱旂郴鐢佃瘽")
     @Excel(name = "鑱旂郴鐢佃瘽")
     private String contactUserPhone;
 
-    @ApiModelProperty(value = "缁存姢浜篒D")
+    @Schema(description = "缁存姢浜篒D")
     @Excel(name = "缁存姢浜�")
     private Integer maintainUserId;
 
-    @ApiModelProperty(value = "缁存姢鏃堕棿")
+    @Schema(description = "缁存姢鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
 //    @Excel(name = "缁存姢鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
     private LocalDate maintainTime;
     @Excel(name = "鏄惁鐧藉悕鍗�")
-    @ApiModelProperty(value = "鏄惁鐧藉悕鍗曪紙0鏄� 1鍚︼級")
+    @Schema(description = "鏄惁鐧藉悕鍗曪紙0鏄� 1鍚︼級")
     private Integer isWhite;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty(value = "渚涘簲鍟嗙被鍨�")
+    @Schema(description = "渚涘簲鍟嗙被鍨�")
     @TableField(value = "supplier_type")
     private String supplierType;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/basic/pojo/SupplierManageFile.java b/src/main/java/com/ruoyi/basic/pojo/SupplierManageFile.java
index 31914fa..012352f 100644
--- a/src/main/java/com/ruoyi/basic/pojo/SupplierManageFile.java
+++ b/src/main/java/com/ruoyi/basic/pojo/SupplierManageFile.java
@@ -1,10 +1,10 @@
 package com.ruoyi.basic.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.time.LocalDateTime;
 
@@ -23,38 +23,41 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty(value = "鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private int fileSize;
 
-    @ApiModelProperty(value = "渚涘簲鍟咺D")
+    @Schema(description = "渚涘簲鍟咺D")
     @NotBlank(message = "渚涘簲鍟唅d涓嶈兘涓虹┖!")
     private Long supplierId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/basic/service/CustomerFollowUpFileService.java b/src/main/java/com/ruoyi/basic/service/CustomerFollowUpFileService.java
index 968ddba..60f3572 100644
--- a/src/main/java/com/ruoyi/basic/service/CustomerFollowUpFileService.java
+++ b/src/main/java/com/ruoyi/basic/service/CustomerFollowUpFileService.java
@@ -4,9 +4,9 @@
 import com.ruoyi.basic.pojo.CustomerFollowUpFile;
 import com.ruoyi.common.vo.SimpleFileVo;
 
-import javax.annotation.Nullable;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Null;
+import jakarta.annotation.Nullable;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Null;
 import java.util.List;
 import java.util.function.BiConsumer;
 import java.util.function.Function;
diff --git a/src/main/java/com/ruoyi/basic/service/CustomerUserService.java b/src/main/java/com/ruoyi/basic/service/CustomerUserService.java
new file mode 100644
index 0000000..eda5f8e
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/service/CustomerUserService.java
@@ -0,0 +1,13 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.CustomerUser;
+
+/**
+ * 瀹㈡埛鍏变韩Service鎺ュ彛
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @date 2026-04-29
+ */
+public interface CustomerUserService extends IService<CustomerUser> {
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/service/ICustomerService.java b/src/main/java/com/ruoyi/basic/service/ICustomerService.java
index 989e474..b725216 100644
--- a/src/main/java/com/ruoyi/basic/service/ICustomerService.java
+++ b/src/main/java/com/ruoyi/basic/service/ICustomerService.java
@@ -5,7 +5,8 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.basic.dto.CustomerDto;
 import com.ruoyi.basic.pojo.Customer;
-import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.basic.vo.CustomerVo;
+import com.ruoyi.framework.web.domain.R;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
@@ -32,7 +33,7 @@
      * @param id 瀹㈡埛妗f涓婚敭
      * @return 瀹㈡埛璇︽儏DTO
      */
-    CustomerDto selectCustomerDetailById(Long id);
+    CustomerVo selectCustomerDetailById(Long id);
 
     /**
      * 鏌ヨ瀹㈡埛妗f鍒楄〃
@@ -40,7 +41,6 @@
      * @param customer 瀹㈡埛妗f
      * @return 瀹㈡埛妗f闆嗗悎
      */
-    IPage<Customer> selectCustomerList(Page<Customer> page, Customer customer);
 
     /**
      * 鏂板瀹㈡埛妗f
@@ -75,7 +75,22 @@
      */
     List<Map<String, Object>> customerList(Customer customer);
 
-    List<Customer> selectCustomerLists(Customer customer);
+    List<CustomerVo> selectCustomerLists(CustomerDto customer);
 
-    AjaxResult importData(MultipartFile file);
+    R importData(MultipartFile file, Integer type);
+
+    IPage<CustomerVo> selectCustomerList(Page<CustomerDto> page, CustomerDto customer);
+
+    void assignCustomer(CustomerDto customer);
+
+    void recycleCustomer(CustomerDto customer);
+
+    /**
+     * 鍏变韩瀹㈡埛缁欏叾浠栫敤鎴�
+     *
+     * @param customerDto 瀹㈡埛DTO锛堝寘鍚鎴稩D鍜屽叡浜敤鎴稩D鍒楄〃锛�
+     */
+    void together(CustomerDto customerDto);
+
+    Boolean back(Long id);
 }
diff --git a/src/main/java/com/ruoyi/basic/service/IProductService.java b/src/main/java/com/ruoyi/basic/service/IProductService.java
index 7fba662..1abaad4 100644
--- a/src/main/java/com/ruoyi/basic/service/IProductService.java
+++ b/src/main/java/com/ruoyi/basic/service/IProductService.java
@@ -7,6 +7,7 @@
 import com.ruoyi.basic.dto.ProductTreeDto;
 import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.basic.pojo.ProductModel;
+import com.ruoyi.basic.vo.ProductModelVo;
 
 import java.util.List;
 
@@ -18,5 +19,5 @@
 
     List<ProductTreeDto> selectProductList(ProductDto productDto);
 
-    IPage<ProductModel> listPageProductModel(Page<ProductModel> page, ProductModel productModel);
+    IPage<ProductModelVo> listPageProductModel(Page<ProductModelVo> page, ProductModel productModel);
 }
diff --git a/src/main/java/com/ruoyi/basic/service/ISupplierService.java b/src/main/java/com/ruoyi/basic/service/ISupplierService.java
index f3e46c2..b54c2ad 100644
--- a/src/main/java/com/ruoyi/basic/service/ISupplierService.java
+++ b/src/main/java/com/ruoyi/basic/service/ISupplierService.java
@@ -8,7 +8,7 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 public interface ISupplierService extends IService<SupplierManage> {
diff --git a/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java b/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java
index 4db9fad..be7e0cb 100644
--- a/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java
+++ b/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java
@@ -1,6 +1,14 @@
 package com.ruoyi.basic.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
+import com.ruoyi.basic.dto.StorageAttachmentVO;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.basic.pojo.StorageAttachment;
 import com.ruoyi.common.constant.StorageAttachmentConstants;
 import com.ruoyi.common.enums.StorageAttachmentRecordType;
@@ -16,26 +24,18 @@
  * @since 2025-05-29
  */
 public interface StorageAttachmentService extends IService<StorageAttachment> {
-    /**
-     * 鏌ヨ閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
-     * @param recordId 鍏宠仈璁板綍id
-     * @param recordType 鍏宠仈璁板綍绫诲瀷
-     * @param fileType 鏂囦欢绫诲瀷
-     * @return 鏂囦欢淇℃伅鍒楄〃
-     */
-    List<StorageAttachment> selectStorageAttachments(Long recordId, StorageAttachmentRecordType recordType, String fileType);
 
     /**
      * 淇濆瓨閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
-     * @param attachments 鏂囦欢淇℃伅鍒楄〃
-     * @param recordId 绠$悊璁板綍id
-     * @param recordType 鍏宠仈璁板綍绫诲瀷
-     * @param fileType 鏂囦欢绫诲瀷
      */
-    public void saveStorageAttachment(List<StorageAttachment> attachments, Long recordId, StorageAttachmentRecordType recordType, StorageAttachmentConstants fileType);
+    public void saveStorageAttachment(StorageAttachmentDTO storageAttachmentDTO);
 
-    public void saveStorageAttachment(List<StorageAttachment> attachments, Long recordId, StorageAttachmentRecordType recordType, String fileType);
-
+    /**
+     * 鍒嗛〉鏌ヨ閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
+     * @param storageAttachmentDTO 鍏宠仈璁板綍淇℃伅
+     * @return 鍒嗛〉缁撴灉
+     */
+    public List<StorageBlobVO> list(StorageAttachmentDTO storageAttachmentDTO);
 
     /**
      * 鍒犻櫎閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
@@ -43,4 +43,11 @@
      * @return 鍒犻櫎缁撴灉
      */
     public int deleteStorageAttachment(StorageAttachment storageAttachment);
+
+    /**
+     * 鎵归噺鍒犻櫎閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
+     * @param ids 鏂囦欢id鍒楄〃
+     * @return 鍒犻櫎缁撴灉
+     */
+    public int batchDeleteStorageAttachment(List<Long> ids);
 }
diff --git a/src/main/java/com/ruoyi/basic/service/StorageBlobService.java b/src/main/java/com/ruoyi/basic/service/StorageBlobService.java
index 962437d..db9362e 100644
--- a/src/main/java/com/ruoyi/basic/service/StorageBlobService.java
+++ b/src/main/java/com/ruoyi/basic/service/StorageBlobService.java
@@ -1,11 +1,11 @@
 package com.ruoyi.basic.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.basic.dto.StorageBlobDTO;
-import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.basic.pojo.StorageBlob;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.File;
 import java.util.List;
 
 /**
@@ -19,20 +19,15 @@
 public interface StorageBlobService extends IService<StorageBlob> {
 
     /**
-     * 鏂囦欢涓婁紶鎺ュ彛
-     * @param files 鏂囦欢淇℃伅
-     * @param bucketName 瀛樺偍妗跺悕绉�
+     * 涓婁紶鏂囦欢
+     * @param files 鏂囦欢鍒楄〃
      * @return 涓婁紶缁撴灉
      */
-    List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName);
+    List<StorageBlobVO> upload(List<MultipartFile> files, Boolean isPublic);
 
-    List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName,Long type);
+    File getFileByToken(String fileName, String token);
 
+    File getPublicFile(String fileName, String publicKey);
 
-    /**
-     * 鎵归噺鍒犻櫎鏂囦欢
-     * @param attachment
-     * @return
-     */
-    public int deleteStorageBlobs(StorageAttachment attachment);
+    String getDownloadFileName(String fileName);
 }
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java
index 628dcb4..cb915c4 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpFileServiceImpl.java
@@ -1,18 +1,15 @@
 package com.ruoyi.basic.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.stream.CollectorUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.Lists;
 import com.ruoyi.basic.mapper.CustomerFollowUpFileMapper;
 import com.ruoyi.basic.pojo.CustomerFollowUpFile;
 import com.ruoyi.basic.service.CustomerFollowUpFileService;
-import com.ruoyi.basic.service.CustomerFollowUpService;
 import com.ruoyi.common.vo.SimpleFileVo;
 import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
@@ -30,12 +27,10 @@
  * @since 2026/03/04 14:53
  */
 @Service
+@RequiredArgsConstructor
 public class CustomerFollowUpFileServiceImpl extends ServiceImpl<CustomerFollowUpFileMapper, CustomerFollowUpFile> implements CustomerFollowUpFileService {
 
-    @Autowired
-    @Lazy
-    private CustomerFollowUpService customerFollowUpService;
-
+    private final CustomerFollowUpFileMapper customerFollowUpFileMapper;
 
     @Override
     public <T> void fillAttachment(List<T> list, Function<T, String> getAttachmentIds, BiConsumer<T, List<SimpleFileVo>> setAttachmentList) {
@@ -52,7 +47,7 @@
         List<CustomerFollowUpFile> followUpFilesByIds = new ArrayList<>();
         Lists.partition(Lists.newArrayList(ids), 999).forEach(it -> {
             followUpFilesByIds.addAll(
-                    customerFollowUpService.getFollowUpFilesByIds(it)
+                    getFollowUpFilesByIds(it)
             );
         });
         if (CollUtil.isEmpty(followUpFilesByIds)) {
@@ -74,4 +69,15 @@
             }
         });
     }
+
+    private List<CustomerFollowUpFile> getFollowUpFilesByIds(Collection<Long> fileIds) {
+        if (fileIds == null || fileIds.isEmpty()) {
+            return new ArrayList<>(0);
+        }
+
+        LambdaQueryWrapper<CustomerFollowUpFile> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.in(CustomerFollowUpFile::getId, fileIds)
+                .select(CustomerFollowUpFile::getId, CustomerFollowUpFile::getFileUrl, CustomerFollowUpFile::getFileName);
+        return customerFollowUpFileMapper.selectList(queryWrapper);
+    }
 }
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpServiceImpl.java
index 5637307..7946753 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerFollowUpServiceImpl.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.basic.dto.CustomerFollowUpDto;
+import com.ruoyi.basic.dto.CustomerFollowUpFileDto;
 import com.ruoyi.basic.mapper.CustomerFollowUpMapper;
 import com.ruoyi.basic.pojo.CustomerFollowUp;
 import com.ruoyi.basic.pojo.CustomerFollowUpFile;
@@ -11,13 +12,11 @@
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.basic.dto.CustomerFollowUpFileDto;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.service.ISysUserService;
-
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.io.FilenameUtils;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -44,16 +43,15 @@
  * @since 2026/03/04 14:48
  */
 @Service
+@RequiredArgsConstructor
 public class CustomerFollowUpServiceImpl extends ServiceImpl<CustomerFollowUpMapper, CustomerFollowUp> implements CustomerFollowUpService {
 
-    @Autowired
-    private CustomerFollowUpFileService customerFollowUpFileService;
+    private final CustomerFollowUpFileService customerFollowUpFileService;
 
     @Value("${file.upload-dir}")
     private String uploadDir;
 
-    @Autowired
-    private ISysUserService sysUserService;
+    private final ISysUserService sysUserService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerReturnVisitServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerReturnVisitServiceImpl.java
index 0186349..f2a1556 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerReturnVisitServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerReturnVisitServiceImpl.java
@@ -8,8 +8,8 @@
 import com.ruoyi.basic.service.CustomerReturnVisitService;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.SecurityUtils;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -26,10 +26,10 @@
  * @since 2026/03/04 17:58
  */
 @Service
+@RequiredArgsConstructor
 public class CustomerReturnVisitServiceImpl extends ServiceImpl<CustomerReturnVisitMapper, CustomerReturnVisit> implements CustomerReturnVisitService {
 
-    @Autowired
-    private ReturnVisitReminderService returnVisitReminderService;
+    private final ReturnVisitReminderService returnVisitReminderService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
index 58810c9..52d01ec 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -1,8 +1,6 @@
 package com.ruoyi.basic.service.impl;
 
 
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.date.LocalDateTimeUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -15,27 +13,25 @@
 import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.pojo.CustomerFollowUp;
 import com.ruoyi.basic.pojo.CustomerFollowUpFile;
-import com.ruoyi.basic.service.CustomerFollowUpFileService;
-import com.ruoyi.basic.service.CustomerFollowUpService;
-import com.ruoyi.basic.service.CustomerReturnVisitService;
-import com.ruoyi.basic.service.ICustomerService;
+import com.ruoyi.basic.pojo.CustomerUser;
+import com.ruoyi.basic.service.*;
+import com.ruoyi.basic.vo.CustomerVo;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.sales.mapper.SalesLedgerMapper;
 import com.ruoyi.sales.pojo.SalesLedger;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.time.LocalDate;
 import java.time.ZoneId;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -51,14 +47,19 @@
 @AllArgsConstructor
 @Slf4j
 public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements ICustomerService {
-    private final SalesLedgerMapper salesLedgerMapper;
+    @Autowired
+    private  SalesLedgerMapper salesLedgerMapper;
+    @Autowired
     private CustomerMapper customerMapper;
 
+    @Autowired
     private CustomerFollowUpService customerFollowUpService;
-
+    @Autowired
     private CustomerFollowUpFileService customerFollowUpFileService;
-
+    @Autowired
     private CustomerReturnVisitService customerReturnVisitService;
+    @Autowired
+    private CustomerUserService customerUserService;
 
     /**
      * 鏌ヨ瀹㈡埛妗f
@@ -78,14 +79,9 @@
      * @return 瀹㈡埛璇︽儏DTO
      */
     @Override
-    public CustomerDto selectCustomerDetailById(Long id) {
-        Customer customer = customerMapper.selectById(id);
-        if (customer == null) {
-            return null;
-        }
-
-        CustomerDto dto = new CustomerDto();
-        BeanUtils.copyProperties(customer, dto);
+    public CustomerVo selectCustomerDetailById(Long id) {
+        CustomerVo customerVo = new CustomerVo();
+        BeanUtils.copyProperties(this.getById(id), customerVo);
 
         // 鏌ヨ璺熻繘璁板綍
         List<CustomerFollowUp> followUpList = customerFollowUpService.list(
@@ -93,8 +89,7 @@
                         .eq(CustomerFollowUp::getCustomerId, id)
                         .orderByDesc(CustomerFollowUp::getFollowUpTime)
         );
-
-        if (!CollectionUtils.isEmpty(followUpList)) {
+        if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(followUpList)) {
             List<CustomerFollowUpDto> followUpDtoList = followUpList.stream().map(followUp -> {
                 CustomerFollowUpDto followUpDto = new CustomerFollowUpDto();
                 BeanUtils.copyProperties(followUp, followUpDto);
@@ -109,10 +104,10 @@
                 return followUpDto;
             }).collect(Collectors.toList());
 
-            dto.setFollowUpList(followUpDtoList);
+            customerVo.setFollowUpList(followUpDtoList);
         }
 
-        return dto;
+        return customerVo;
     }
 
     /**
@@ -122,62 +117,65 @@
      * @return 瀹㈡埛妗f
      */
     @Override
-    public IPage<Customer> selectCustomerList(Page<Customer> page, Customer customer) {
-        // 1. 澶勭悊绌哄�煎満鏅紙鍙傛暟鏍¢獙锛�
-        if (page == null) {
-            page = Page.of(1, 10); // 榛樿绗�1椤碉紝姣忛〉10鏉℃暟鎹�
-        }
-        if (customer == null) {
-            customer = new Customer(); // 閬垮厤绌哄璞″鑷寸殑NPE
+    public IPage<CustomerVo> selectCustomerList(Page<CustomerDto> page, CustomerDto customer) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        Long loginUserId = loginUser.getUserId();
+        IPage<CustomerVo> customerPage = customerMapper.listPage(page, customer, loginUserId);
+
+        List<CustomerVo> records = customerPage.getRecords();
+        if (CollectionUtils.isEmpty(records)) {
+            return customerPage;
         }
 
-        // 2. 鏋勫缓鏌ヨ鏉′欢锛堝寮虹┖鍊煎畨鍏級
-        LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
-        String customerName = customer.getCustomerName();
-        String customerType = customer.getCustomerType();
-        if (StringUtils.isNotBlank(customerName)) {
-            queryWrapper.like(Customer::getCustomerName, customerName);
-        }
-        if (StringUtils.isNotBlank(customerType)) {
-            queryWrapper.like(Customer::getCustomerType, customerType);
-        }
-
-        // 3. 鎵ц鍒嗛〉鏌ヨ锛堜繚鐣欏垎椤靛厓鏁版嵁锛�
-        IPage<Customer> customerPage = customerMapper.selectPage(page, queryWrapper);
-
-        // 4. 鏁版嵁澶勭悊锛堝寮虹┖鍊煎畨鍏� & 浠g爜鍙鎬э級
-        List<Customer> processedList = customerPage.getRecords().stream()
-                .filter(Objects::nonNull) // 杩囨护绌哄璞★紙閬垮厤鍚庣画鎿嶄綔NPE锛�
-                .peek(c -> {
-                    // 瀹夊叏鑾峰彇瀛楁锛岄伩鍏峮ull鍊兼嫾鎺�
-                    String address = StringUtils.defaultString(c.getCompanyAddress(), "");
-                    String phone = StringUtils.defaultString(c.getCompanyPhone(), "");
-                    c.setAddressPhone(address + "(" + phone + ")");
-
-                    // 鏌ヨ鏈�鏂扮殑璺熻繘璁板綍
-                    CustomerFollowUp followUp = customerFollowUpService.getOne(
-                            new LambdaQueryWrapper<CustomerFollowUp>()
-                                    .eq(CustomerFollowUp::getCustomerId, c.getId())
-                                    .orderByDesc(CustomerFollowUp::getFollowUpTime)
-                                    .last("LIMIT 1")
-                    );
-
-                    if (followUp != null) {
-                        c.setFollowUpLevel(followUp.getFollowUpLevel());
-                        c.setFollowUpTime(
-                                Date.from(
-                                        followUp.getFollowUpTime().atZone(ZoneId.systemDefault()).toInstant()
-                                )
-                        );
-                    }
-                })
+        List<Long> customerIds = records.stream()
+                .map(CustomerVo::getId)
+                .filter(Objects::nonNull)
                 .collect(Collectors.toList());
 
-        // 5. 鏇存柊鍒嗛〉缁撴灉涓殑鏁版嵁锛堜繚鎸佸垎椤典俊鎭畬鏁达級
-        IPage<Customer> resultPage = new Page<>(customerPage.getCurrent(), customerPage.getSize(), customerPage.getTotal());
-        resultPage.setRecords(processedList);
+        if (!CollectionUtils.isEmpty(customerIds)) {
+            Map<Long, CustomerFollowUp> latestFollowUpMap = getLatestFollowUpMap(customerIds);
 
-        return customerPage; // 杩斿洖鍖呭惈鍒嗛〉淇℃伅鐨処Page瀵硅薄
+            records.forEach(c -> {
+                String address = StringUtils.defaultString(c.getCompanyAddress(), "");
+                String phone = StringUtils.defaultString(c.getCompanyPhone(), "");
+                c.setAddressPhone(address + "(" + phone + ")");
+
+                CustomerFollowUp followUp = latestFollowUpMap.get(c.getId());
+                if (followUp != null) {
+                    c.setFollowUpLevel(followUp.getFollowUpLevel());
+                    c.setFollowUpTime(Date.from(
+                            followUp.getFollowUpTime().atZone(ZoneId.systemDefault()).toInstant()
+                    ));
+                }
+
+                // 杞崲鍏变韩鐢ㄦ埛ID瀛楃涓蹭负List<Long>
+                String userIdsStr = c.getUserIdsStr();
+                if (StringUtils.isNotEmpty(userIdsStr)) {
+                    List<Long> userIds = Arrays.stream(userIdsStr.split(","))
+                            .map(String::trim)
+                            .map(Long::parseLong)
+                            .collect(Collectors.toList());
+                    c.setUserIds(userIds);
+                }
+            });
+        }
+
+        return customerPage;
+    }
+
+    private Map<Long, CustomerFollowUp> getLatestFollowUpMap(List<Long> customerIds) {
+        List<CustomerFollowUp> followUps = customerFollowUpService.list(
+                new LambdaQueryWrapper<CustomerFollowUp>()
+                        .in(CustomerFollowUp::getCustomerId, customerIds)
+                        .orderByDesc(CustomerFollowUp::getFollowUpTime)
+        );
+
+        return followUps.stream()
+                .collect(Collectors.toMap(
+                        CustomerFollowUp::getCustomerId,
+                        followUp -> followUp,
+                        (existing, replacement) -> existing
+                ));
     }
 
     /**
@@ -222,12 +220,28 @@
         if (!salesLedgers.isEmpty()) {
             throw new RuntimeException("瀹㈡埛妗f涓嬫湁閿�鍞悎鍚岋紝璇峰厛鍒犻櫎閿�鍞悎鍚�");
         }
-        //  鍒犻櫎瀹㈡埛鐨勫悓鏃朵篃闇�瑕佸垹闄ゅ搴旂殑瀹㈡埛璺熼殢銆侀檮浠跺拰鍥炶鎻愰啋
+        // 鏌ヨ鏄惁鏈夊凡鍒嗛厤鐨勫叕娴峰鎴�
+        List<Customer> assignedPools = customerMapper.selectList(
+                new QueryWrapper<Customer>().lambda()
+                        .in(Customer::getId, idList)
+                        .eq(Customer::getType, 1).
+                        eq(Customer::getIsAssigned, 1)  // 鍏捣瀹㈡埛
+        );
+        if (!assignedPools.isEmpty()) {
+            throw new RuntimeException("瀹㈡埛妗f涓嬫湁宸插垎閰嶇殑鍏捣瀹㈡埛锛岃鍏堟敹鍥�");
+        }
+        // 鍒犻櫎瀹㈡埛鐨勫悓鏃朵篃闇�瑕佸垹闄ゅ搴旂殑瀹㈡埛璺熼殢銆侀檮浠跺拰鍥炶鎻愰啋
         for (Long id : ids) {
             customerFollowUpService.deleteByCustomerId(id);
             customerReturnVisitService.deleteByCustomerId(id);
+            // 鍒犻櫎瀹㈡埛鐨勫叡浜叧绯�
+            customerUserService.remove(
+                new QueryWrapper<CustomerUser>().lambda()
+                    .eq(CustomerUser::getCustomerId, id)
+            );
         }
 
+        // 鍒犻櫎瀹㈡埛涓昏〃鏁版嵁
         return customerMapper.deleteBatchIds(idList);
     }
 
@@ -239,23 +253,32 @@
     }
 
     @Override
-    public List<Customer> selectCustomerLists(Customer customer) {
-        return customerMapper.selectList(null);
+    public List<CustomerVo> selectCustomerLists(CustomerDto customer) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        Long loginUserId = loginUser.getUserId();
+        return customerMapper.list(customer, loginUserId);
     }
 
     @Override
-    public AjaxResult importData(MultipartFile file) {
+    public R importData(MultipartFile file, Integer type) {
         try {
             ExcelUtil<Customer> util = new ExcelUtil<Customer>(Customer.class);
             List<Customer> userList = util.importExcel(file.getInputStream());
             if (CollectionUtils.isEmpty(userList)) {
-                return AjaxResult.warn("妯℃澘閿欒鎴栧鍏ユ暟鎹负绌�");
+                return R.fail("妯℃澘閿欒鎴栧鍏ユ暟鎹负绌�");
+            }
+
+            // 鏍规嵁 type 鍙傛暟璁剧疆瀹㈡埛绫诲瀷锛堢娴�/鍏捣锛�
+            if (type != null) {
+                userList.forEach(customer -> {
+                    customer.setType(type);
+                });
             }
             this.saveOrUpdateBatch(userList);
-            return AjaxResult.success(true);
+            return R.ok(true);
         } catch (Exception e) {
             e.printStackTrace();
-            return AjaxResult.error("瀵煎叆澶辫触");
+            return R.fail("瀵煎叆澶辫触");
         }
 
     }
@@ -276,6 +299,86 @@
         ).collect(Collectors.toList());
     }
 
+    // 鍒嗛厤鍏捣瀹㈡埛缁欑娴�
+    @Override
+    public void assignCustomer(CustomerDto customerDto) {
+        Customer customer = customerMapper.selectById(customerDto.getId());
+        if (customer.getType() == 1 && customer.getIsAssigned() == 0) {  // 鍏捣涓斿彲鍒嗛厤
+            customer.setIsAssigned(1);
+            customer.setUsageStatus(1L);
+            customer.setUsageUser(customerDto.getUsageUser());
+            customerMapper.updateById(customer);
+        }
+    }
+
+    // 鍥炴敹绉佹捣瀹㈡埛鍒板叕娴�
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void recycleCustomer(CustomerDto customerDto) {
+        Customer customer = customerMapper.selectById(customerDto.getId());
+        if (customer.getType() == 1 && customer.getIsAssigned() == 1) {  // 鍏捣涓斿凡鍒嗛厤
+            customer.setIsAssigned(0);
+            customer.setUsageStatus(0L);
+            customer.setUsageUser(0L);
+            customerMapper.updateById(customer);
+
+            // 鍒犻櫎璇ュ鎴风殑鎵�鏈夊叡浜叧绯�
+            customerUserService.remove(
+                new QueryWrapper<CustomerUser>().lambda()
+                    .eq(CustomerUser::getCustomerId, customerDto.getId())
+            );
+        }
+    }
+
+    // 瀹㈡埛鍏变韩
+    @Override
+    public void together(CustomerDto customerDto) {
+        // 鏌ヨ鐜版湁鐨勫叡浜褰�
+        List<CustomerUser> existingUsers = customerUserService.list(
+                new QueryWrapper<CustomerUser>().lambda().eq(CustomerUser::getCustomerId, customerDto.getId())
+        );
+
+        // 鑾峰彇宸插瓨鍦ㄧ殑鐢ㄦ埛ID鍒楄〃
+        List<Long> existingUserIds = existingUsers.stream()
+                .map(CustomerUser::getUserId)
+                .collect(Collectors.toList());
+
+        // 杩囨护鎺夊凡瀛樺湪鐨勭敤鎴凤紝鍙繚鐣欐柊鐢ㄦ埛
+        List<Long> newUserIds = customerDto.getUserIds().stream()
+                .filter(userId -> !existingUserIds.contains(userId))
+                .collect(Collectors.toList());
+
+        if (CollectionUtils.isEmpty(newUserIds)) {
+            return;
+        }
+
+        // 鑾峰彇褰撳墠绉熸埛ID
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        Long tenantId = loginUser.getTenantId();
+
+        // 鎵归噺淇濆瓨鏂扮殑鍏变韩璁板綍
+        List<CustomerUser> customerUsers = newUserIds.stream()
+                .map(userId -> {
+                    CustomerUser customerUser = new CustomerUser();
+                    customerUser.setCustomerId(customerDto.getId());
+                    customerUser.setUserId(userId);
+                    customerUser.setTenantId(tenantId);
+                    return customerUser;
+                })
+                .collect(Collectors.toList());
+
+        customerUserService.saveBatch(customerUsers);
+    }
+
+    @Override
+    public Boolean back(Long id) {
+        //灏嗗鎴风殑type鏀逛负1 涓旂洿鎺ュ垎閰嶇粰褰撳墠鐢ㄦ埛
+        Customer customer = customerMapper.selectById(id);
+        customer.setType(1);
+        customer.setIsAssigned(1);
+        return this.updateById(customer);
+    }
+
     /**
      * 涓嬪垝绾垮懡鍚嶈浆椹煎嘲鍛藉悕
      */
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerUserServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerUserServiceImpl.java
new file mode 100644
index 0000000..5829e8a
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerUserServiceImpl.java
@@ -0,0 +1,19 @@
+package com.ruoyi.basic.service.impl;
+
+import com.ruoyi.basic.mapper.CustomerUserMapper;
+import com.ruoyi.basic.pojo.CustomerUser;
+import com.ruoyi.basic.service.CustomerUserService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 瀹㈡埛鍏变韩Service瀹炵幇绫�
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @date 2026-04-29
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class CustomerUserServiceImpl extends ServiceImpl<CustomerUserMapper, CustomerUser> implements CustomerUserService {
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
index 9382134..ce0ba64 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -25,7 +25,10 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
index fdf2dd3..5a7f679 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
@@ -2,6 +2,7 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.basic.dto.ProductDto;
@@ -11,6 +12,7 @@
 import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.basic.service.IProductService;
+import com.ruoyi.basic.vo.ProductModelVo;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.AjaxResult;
@@ -55,7 +57,7 @@
     }
 
     @Override
-    public IPage<ProductModel> listPageProductModel(Page<ProductModel> page, ProductModel productModel) {
+    public IPage<ProductModelVo> listPageProductModel(Page<ProductModelVo> page, ProductModel productModel) {
         return productModelMapper.listPageProductModel(page, productModel);
     }
 
@@ -89,6 +91,9 @@
 
     @Override
     public int addOrEditProduct(ProductDto productDto) {
+        if (ObjectUtils.isEmpty(productDto.getParentId())) {
+            throw new IllegalArgumentException("璇烽�夋嫨鐖惰妭鐐�");
+        }
         if (productDto.getId() == null) {
             // 鏂板浜у搧閫昏緫
             if (productDto.getParentId() == null) {
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ReturnVisitReminderService.java b/src/main/java/com/ruoyi/basic/service/impl/ReturnVisitReminderService.java
index 819a47d..6139b9b 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ReturnVisitReminderService.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ReturnVisitReminderService.java
@@ -1,10 +1,10 @@
 package com.ruoyi.basic.service.impl;
 
+import com.ruoyi.basic.mapper.CustomerReturnVisitMapper;
 import com.ruoyi.basic.pojo.CustomerReturnVisit;
-import com.ruoyi.basic.service.CustomerReturnVisitService;
 import com.ruoyi.framework.redis.RedisCache;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.ZoneId;
@@ -20,19 +20,18 @@
  */
 @Slf4j
 @Service
+@RequiredArgsConstructor
 public class ReturnVisitReminderService {
 
     private static final String REMINDER_QUEUE_KEY = "return_visit:reminder:queue";
 
-    @Autowired
-    private RedisCache redisCache;
+    private final RedisCache redisCache;
 
-    @Autowired
-    private CustomerReturnVisitService customerReturnVisitService;
+    private final CustomerReturnVisitMapper customerReturnVisitMapper;
 
     @SuppressWarnings("unchecked")
     public void scheduleReminder(Long returnVisitId) {
-        CustomerReturnVisit returnVisit = customerReturnVisitService.getById(returnVisitId);
+        CustomerReturnVisit returnVisit = customerReturnVisitMapper.selectById(returnVisitId);
         if (returnVisit == null || returnVisit.getIsEnabled() == 0) {
             return;
         }
diff --git a/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java
index 9b1980a..fda9f26 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java
@@ -1,21 +1,18 @@
 package com.ruoyi.basic.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.dto.StorageBlobDTO;
-import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.basic.mapper.StorageAttachmentMapper;
 import com.ruoyi.basic.mapper.StorageBlobMapper;
-import com.ruoyi.basic.pojo.StorageBlob;
+import com.ruoyi.basic.pojo.StorageAttachment;
 import com.ruoyi.basic.service.StorageAttachmentService;
 import com.ruoyi.basic.service.StorageBlobService;
-import com.ruoyi.common.constant.StorageAttachmentConstants;
-import com.ruoyi.common.enums.StorageAttachmentRecordType;
-import com.ruoyi.common.utils.MinioUtils;
+import com.ruoyi.basic.utils.FileUtil;
 import lombok.RequiredArgsConstructor;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 
@@ -30,78 +27,42 @@
 @Service
 @RequiredArgsConstructor
 public class StorageAttachmentServiceImpl extends ServiceImpl<StorageAttachmentMapper, StorageAttachment> implements StorageAttachmentService {
-    @Autowired
-    private StorageBlobMapper storageBlobMapper;
+    private final StorageBlobMapper storageBlobMapper;
 
-    @Autowired
-    private StorageAttachmentMapper storageAttachmentMapper;
+    private final StorageAttachmentMapper storageAttachmentMapper;
 
-    @Autowired
-    private StorageBlobService storageBlobService;
-
-    @Autowired
-    private MinioUtils minioUtils;
+    private final StorageBlobService storageBlobService;
+    private final FileUtil fileUtil;
 
     @Override
-    public List<StorageAttachment> selectStorageAttachments(Long recordId, StorageAttachmentRecordType recordType, String fileType) {
-        List<StorageAttachment> storageAttachments = storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>()
-                .eq(StorageAttachment::getRecordId, recordId)
-                .eq(StorageAttachment::getRecordType, recordType.ordinal())
-                .eq(StorageAttachment::getName, fileType));
-        if (storageAttachments != null) {
-            for (StorageAttachment storageAttachment : storageAttachments) {
-                StorageBlob storageBlob = storageBlobMapper.selectById(storageAttachment.getStorageBlobId());
-                StorageBlobDTO storageBlobDTO = new StorageBlobDTO();
-                BeanUtils.copyProperties(storageBlob, storageBlobDTO);
-                storageBlobDTO.setUrl(minioUtils.getPreviewUrl(storageBlob.getBucketName(), storageBlob.getBucketName(), true));
-                storageAttachment.setStorageBlobDTO(storageBlobDTO);
-            }
-        }
-
-        return storageAttachments;
+    @Transactional(rollbackFor = Exception.class)
+    public void saveStorageAttachment(StorageAttachmentDTO storageAttachmentDTO) {
+        fileUtil.saveStorageAttachmentByRecordTypeAndRecordId(storageAttachmentDTO.getApplication(), RecordTypeEnum.getByType(storageAttachmentDTO.getRecordType()), storageAttachmentDTO.getRecordId(), storageAttachmentDTO.getStorageBlobDTOs());
     }
 
     @Override
-    public void saveStorageAttachment(List<StorageAttachment> attachments, Long recordId, StorageAttachmentRecordType recordType, StorageAttachmentConstants fileType) {
-        // 鍒犻櫎鏃у浘
-        deleteStorageAttachment(new StorageAttachment(fileType.toString(), (long) recordType.ordinal(), recordId));
-        for (StorageAttachment attachment : attachments) {
-            // 鑾峰彇鍏宠仈璁板綍
-            StorageBlob storageBlob = attachment.getStorageBlobDTO();
-            attachment.setName(fileType.toString());
-            attachment.setRecordType((long) recordType.ordinal());
-            attachment.setRecordId(recordId);
-            attachment.setStorageBlobId(storageBlob.getId());
-            storageAttachmentMapper.insert(attachment);
-        }
-
-    }
-
-    @Override
-    public void saveStorageAttachment(List<StorageAttachment> attachments, Long recordId, StorageAttachmentRecordType recordType, String fileType) {
-        // 鍒犻櫎鏃у浘
-//        deleteStorageAttachment(new StorageAttachment(fileType, (long) recordType.ordinal(), recordId));
-        for (StorageAttachment attachment : attachments) {
-            // 鑾峰彇鍏宠仈璁板綍
-            StorageBlob storageBlob = attachment.getStorageBlobDTO();
-            attachment.setName(fileType);
-            attachment.setRecordType((long) recordType.ordinal());
-            attachment.setRecordId(recordId);
-            attachment.setStorageBlobId(storageBlob.getId());
-            storageAttachmentMapper.insert(attachment);
-        }
-
+    public List<StorageBlobVO> list(StorageAttachmentDTO storageAttachmentDTO) {
+        return fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(storageAttachmentDTO);
     }
 
     @Override
     public int deleteStorageAttachment(StorageAttachment storageAttachment) {
         // 鍏堝垹闄ゆ槑缁嗚〃
-        storageBlobService.deleteStorageBlobs(storageAttachment);
+        // todo fileChange
+//        storageBlobService.deleteStorageBlobs(storageAttachment);
+//
+//
+//        return storageAttachmentMapper.delete(new LambdaQueryWrapper<StorageAttachment>()
+//                .eq(StorageAttachment::getRecordId, storageAttachment.getRecordId())
+//                .eq(StorageAttachment::getRecordType, storageAttachment.getRecordType())
+//                .eq(StorageAttachment::getName, storageAttachment.getName()));
+//    }
+        return 0;
+    }
 
-
-        return storageAttachmentMapper.delete(new LambdaQueryWrapper<StorageAttachment>()
-                .eq(StorageAttachment::getRecordId, storageAttachment.getRecordId())
-                .eq(StorageAttachment::getRecordType, storageAttachment.getRecordType())
-                .eq(StorageAttachment::getName, storageAttachment.getName()));
+    @Override
+    public int batchDeleteStorageAttachment(List<Long> ids) {
+        fileUtil.deleteStorageAttachmentsByStorageAttachmentIds(ids);
+        return 1;
     }
 }
diff --git a/src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java
index d85a522..9ad80ae 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java
@@ -1,190 +1,171 @@
 package com.ruoyi.basic.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.dto.StorageBlobDTO;
-import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.basic.mapper.StorageBlobMapper;
-import com.ruoyi.basic.pojo.StorageAttachment;
 import com.ruoyi.basic.pojo.StorageBlob;
 import com.ruoyi.basic.service.StorageBlobService;
-import com.ruoyi.common.exception.base.BaseException;
-import com.ruoyi.common.exception.file.InvalidExtensionException;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.MinioUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.uuid.IdUtils;
-import com.ruoyi.framework.web.domain.MinioResult;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.common.config.FileProperties;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.security.Keys;
 import lombok.RequiredArgsConstructor;
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.time.LocalDateTime;
+import javax.crypto.SecretKey;
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
-import java.util.stream.Collectors;
+import java.util.UUID;
 
 /**
  * <p>
  * 閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭� 鏈嶅姟瀹炵幇绫�
  * </p>
  *
- * @author ruoyi
- * @since 2025-05-29
  */
 @Service
 @RequiredArgsConstructor
 public class StorageBlobServiceImpl extends ServiceImpl<StorageBlobMapper, StorageBlob> implements StorageBlobService {
-    @Autowired
-    private StorageAttachmentMapper storageAttachmentMapper;
-
-    @Autowired
-    private StorageBlobMapper storageBlobMapper;
-
-    @Autowired
-    private MinioUtils minioUtils;
+    private final FileProperties properties;
+    private final StorageBlobMapper storageBlobMapper;
+    private final FileUtil fileUtil;
 
     @Override
-    public List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName) {
-
-        // 鑻ユ病浼犲叆bucketName锛屽垯浣跨敤榛樿bucketName
-        if (StringUtils.isEmpty(bucketName)) {
-            bucketName  = minioUtils.getDefaultBucket();
+    public List<StorageBlobVO> upload(List<MultipartFile> files, Boolean isPublic) {
+        if (CollectionUtils.isEmpty(files)) {
+            throw new IllegalArgumentException("鏂囦欢涓嶈兘涓虹┖");
         }
 
-        List<StorageBlobDTO> storageBlobDTOs = new ArrayList<>();
+        List<StorageBlobVO> storageBlobVOS = new ArrayList<>();
+
         for (MultipartFile file : files) {
-            try {
-                MinioResult res = minioUtils.upload(bucketName, file, false);
-                StorageBlobDTO dto = new StorageBlobDTO();
-                dto.setContentType(file.getContentType());
-                dto.setBucketFilename(res.getBucketFileName());
-                dto.setOriginalFilename(res.getOriginalName());
-                dto.setByteSize(file.getSize());
-                dto.setResourceKey(IdUtils.simpleUUID());
-                dto.setBucketName(bucketName);
-                dto.setUrl(minioUtils.getPreviewUrl(res.getBucketFileName(), bucketName, false));
-                // 鎻掑叆鏁版嵁搴�
-                storageBlobMapper.insert(dto);
-
-                storageBlobDTOs.add(dto);
-            } catch (InvalidExtensionException e) {
-                throw new RuntimeException("minio鏂囦欢涓婁紶寮傚父锛�" +  e);
+            if (file == null || file.isEmpty()) {
+                throw new IllegalArgumentException("鏂囦欢涓嶈兘涓虹┖");
             }
+
+            String originalFileName = StringUtils.hasText(file.getOriginalFilename())
+                    ? StringUtils.cleanPath(file.getOriginalFilename())
+                    : UUID.randomUUID().toString();
+            String fileName = UUID.randomUUID() + "_" + originalFileName;
+            String relativePath = fileUtil.buildRelativePath();
+            File targetDirectory = new File(properties.getPath(), relativePath);
+            if (!targetDirectory.exists() && !targetDirectory.mkdirs()) {
+                throw new RuntimeException("鍒涘缓涓婁紶鐩綍澶辫触");
+            }
+            File dest = new File(targetDirectory, fileName);
+
+            StorageBlobVO storageBlob;
+            try {
+                file.transferTo(dest);
+                storageBlob = getStorageBlob(file, originalFileName, fileName, relativePath, isPublic);
+                if (storageBlob == null || storageBlob.getId() == null) {
+                    throw new RuntimeException("鏂囦欢鍏冩暟鎹繚瀛樺け璐�");
+                }
+            } catch (RuntimeException e) {
+                if (dest.exists()) {
+                    dest.delete();
+                }
+                throw e;
+            } catch (IOException e) {
+                throw new RuntimeException("鏂囦欢淇濆瓨澶辫触", e);
+            }
+
+            storageBlobVOS.add(storageBlob);
         }
-
-
-        return storageBlobDTOs;
+        return storageBlobVOS;
     }
 
     @Override
-    public List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName, Long type) {
-
-        // 鑻ユ病浼犲叆bucketName锛屽垯浣跨敤榛樿bucketName
-        if (StringUtils.isEmpty(bucketName)) {
-            bucketName = minioUtils.getDefaultBucket();
-        }
-        List<StorageBlobDTO> storageBlobDTOs = new ArrayList<>();
-        for (MultipartFile file : files) {
-            try {
-                validateFileExtension(file);
-
-                MinioResult res = minioUtils.upload(bucketName, file, false);
-
-                StorageBlobDTO dto = buildStorageBlobDTO(file, res, bucketName, type);
-
-                storageBlobMapper.insert(dto);
-                storageBlobDTOs.add(dto);
-
-            } catch (InvalidExtensionException e) {
-                throw new RuntimeException("涓嶆敮鎸佺殑鏂囦欢绫诲瀷锛�" + file.getOriginalFilename(), e);
-            } catch (Exception e) {
-                throw new RuntimeException("涓婁紶鏂囦欢澶辫触锛�" + file.getOriginalFilename(), e);
-            }
-        }
-        return storageBlobDTOs;
-    }
-
-    private StorageBlobDTO buildStorageBlobDTO(MultipartFile file, MinioResult res, String bucketName, Long type) {
-        StorageBlobDTO dto = new StorageBlobDTO();
-        dto.setContentType(file.getContentType());
-        dto.setBucketFilename(res.getBucketFileName());
-        dto.setOriginalFilename(res.getOriginalName());
-        dto.setByteSize(file.getSize());
-        dto.setResourceKey(IdUtils.simpleUUID());
-        dto.setBucketName(bucketName);
-        dto.setUrl(minioUtils.getPreviewUrl(res.getBucketFileName(), bucketName, false));
-        dto.setDownloadUrl(minioUtils.getDownloadUrl(res.getBucketFileName(), bucketName));
-
-        if (type != null) {
-            dto.setType(type);
+    public File getFileByToken(String fileName, String token) {
+        if (!StringUtils.hasText(token)) {
+            throw new IllegalArgumentException("token涓嶈兘涓虹┖");
         }
 
-        return dto;
-    }
+        String secretStr = properties.getJwtSecret();
 
-    private void validateFileExtension(MultipartFile file) throws InvalidExtensionException {
-        String filename = file.getOriginalFilename();
-        String extension = FilenameUtils.getExtension(filename).toLowerCase();
-        List<String> allowedExtensions = Arrays.asList(
-                // 鍥剧墖
-                "jpg", "jpeg", "png", "gif", "bmp", "webp", "tiff", "ico", "svg",
-
-                // 鏂囨。
-                "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "rtf", "md", "csv", "odt",
-
-                // 瑙嗛
-                "mp4", "mov", "avi", "wmv", "flv", "mkv", "webm", "mpeg", "3gp", "MOV",
-
-                // 闊抽
-                "mp3", "wav", "ogg", "aac", "flac", "m4a", "wma", "amr",
-
-                // 鍘嬬缉鍖�
-                "zip", "rar", "7z", "tar", "gz", "bz2", "xz",
-
-                // 缂栫▼浠g爜鏂囦欢
-                "java", "py", "js", "ts", "html", "css", "cpp", "c", "cs", "json", "xml", "sql", "yaml", "yml", "sh", "bat",
-
-                // 瀹夎绋嬪簭 & 浜岃繘鍒�
-                "exe", "apk", "dmg", "msi", "bin", "iso",
-
-                // 璁捐绫�
-                "psd", "ai", "xd", "sketch", "fig"
-        );
-
-        if (!allowedExtensions.contains(extension)) {
-            throw new BaseException("鏂囦欢绫诲瀷涓嶈鍏佽锛�" + extension);
+        SecretKey key = Keys.hmacShaKeyFor(secretStr.getBytes(StandardCharsets.UTF_8));
+        Claims claims = Jwts.parser()
+                .verifyWith(key)          // 浠f浛鏃х増鐨� setSigningKey
+                .build()                  // 蹇呴』鍏堟瀯寤鸿В鏋愬櫒
+                .parseSignedClaims(token) // 浠f浛鏃х増鐨� parseClaimsJws
+                .getPayload();            // 浠f浛鏃х増鐨� getBody()
+        if (!fileName.equals(claims.getSubject())) {
+            throw new IllegalArgumentException("token涓庢枃浠朵笉鍖归厤");
         }
+        fileUtil.validateTokenUsage(token);
+        StorageBlob storageBlob = findStorageBlob(fileName);
+        String path = storageBlob == null ? claims.get("path", String.class) : storageBlob.getPath();
+        if (!StringUtils.hasText(path)) {
+            return new File(properties.getPath(), fileName);
+        }
+        return new File(new File(properties.getPath(), path), fileName);
     }
 
     @Override
-    public int deleteStorageBlobs(StorageAttachment attachment) {
-        List<StorageAttachment> attachments = storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>()
-                .eq(StorageAttachment::getRecordId, attachment.getRecordId())
-                .eq(StorageAttachment::getRecordType, attachment.getRecordType())
-                .eq(StorageAttachment::getName, attachment.getName()));
-        List<Long> ids = attachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList());
-        if(CollectionUtils.isEmpty(ids)){
-            return 0;
+    public File getPublicFile(String fileName, String publicKey) {
+        if (!StringUtils.hasText(fileName)) {
+            throw new IllegalArgumentException("鏂囦欢鍚嶄笉鑳戒负绌�");
         }
-        List<StorageBlob> storageBlobs = storageBlobMapper.selectList(new LambdaQueryWrapper<StorageBlob>()
-                .in(StorageBlob::getId, ids));
-        if (!storageBlobs.isEmpty()) {
-            for (StorageBlob storageBlob : storageBlobs) {
-                // 绉婚櫎妗跺唴鏂囦欢
-                minioUtils.removeObjectsResult(storageBlob.getBucketName(), storageBlob.getBucketName());
-            }
+        if (!StringUtils.hasText(publicKey)) {
+            throw new IllegalArgumentException("publicKey涓嶈兘涓虹┖");
         }
+        StorageBlob storageBlob = storageBlobMapper.selectOne(new LambdaQueryWrapper<StorageBlob>()
+                .eq(StorageBlob::getUidFilename, fileName)
+                .eq(StorageBlob::getResourceKey, publicKey)
+                .last("limit 1"));
+        if (storageBlob == null) {
+            throw new IllegalArgumentException("鍏紑鏂囦欢涓嶅瓨鍦ㄦ垨publicKey涓嶅尮閰�");
+        }
+        String path = storageBlob.getPath();
+        if (!StringUtils.hasText(path)) {
+            return new File(properties.getPath(), fileName);
+        }
+        return new File(new File(properties.getPath(), path), fileName);
+    }
 
-        if (!ids.isEmpty()) {
-            return storageBlobMapper.delete(new QueryWrapper<StorageBlob>().lambda().in(StorageBlob::getId, ids));
-        }
+    private StorageBlob findStorageBlob(String fileName) {
+        return storageBlobMapper.selectOne(new LambdaQueryWrapper<StorageBlob>()
+                .eq(StorageBlob::getUidFilename, fileName)
+                .last("limit 1"));
+    }
 
-        return 0;
+    private StorageBlobVO getStorageBlob(MultipartFile file, String originalFileName, String fileName, String relativePath, Boolean isPublic) {
+        StorageBlobVO storageBlob = new StorageBlobVO();
+        storageBlob.setResourceKey(UUID.randomUUID().toString().replace("-", ""));
+        storageBlob.setContentType(file.getContentType());
+        storageBlob.setOriginalFilename(originalFileName);
+        storageBlob.setUidFilename(fileName);
+        storageBlob.setByteSize(file.getSize());
+        storageBlob.setPath(relativePath);
+        if (isPublic) {
+            storageBlob.setPreviewURL(fileUtil.buildSignedUrl(storageBlob, "/preview/", BigDecimal.valueOf(-1)));
+            storageBlob.setDownloadURL(fileUtil.buildSignedUrl(storageBlob, "/download/", BigDecimal.valueOf(-1)));
+        } else {
+            storageBlob.setPreviewURL(fileUtil.buildSignedPreviewUrl(storageBlob));
+            storageBlob.setDownloadURL(fileUtil.buildSignedDownloadUrl(storageBlob));
+        }
+        int affectedRows = storageBlobMapper.insert(storageBlob);
+        if (affectedRows <= 0) {
+            throw new RuntimeException("鏂囦欢鍏冩暟鎹繚瀛樺け璐�");
+        }
+        return storageBlob;
+    }
+
+    @Override
+    public String getDownloadFileName(String fileName) {
+        StorageBlob storageBlob = findStorageBlob(fileName);
+        if (storageBlob == null || !StringUtils.hasText(storageBlob.getOriginalFilename())) {
+            return fileName;
+        }
+        return storageBlob.getOriginalFilename();
     }
 }
diff --git a/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java
index 020a9cd..6adaf2a 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java
@@ -8,31 +8,28 @@
 import com.ruoyi.basic.dto.SupplierManageDto;
 import com.ruoyi.basic.excel.SupplierManageExcelDto;
 import com.ruoyi.basic.mapper.SupplierManageMapper;
-import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.pojo.SupplierManage;
 import com.ruoyi.basic.service.ISupplierService;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.List;
 
 @Service
+@RequiredArgsConstructor
 public class SupplierServiceImpl extends ServiceImpl<SupplierManageMapper,SupplierManage> implements ISupplierService {
 
-    @Autowired
-    private SupplierManageMapper supplierMapper;
-    @Autowired
-    private PurchaseLedgerMapper purchaseLedgerMapper;
+    private final SupplierManageMapper supplierMapper;
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
 
     /**
      * 渚涘簲鍟嗘柊澧�
diff --git a/src/main/java/com/ruoyi/basic/task/ReturnVisitReminderTask.java b/src/main/java/com/ruoyi/basic/task/ReturnVisitReminderTask.java
index 245acda..fbfb5b6 100644
--- a/src/main/java/com/ruoyi/basic/task/ReturnVisitReminderTask.java
+++ b/src/main/java/com/ruoyi/basic/task/ReturnVisitReminderTask.java
@@ -6,12 +6,11 @@
 import com.ruoyi.project.system.domain.SysUserClient;
 import com.ruoyi.project.system.service.SysUserClientService;
 import com.ruoyi.project.system.service.impl.UnipushService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
-import java.time.LocalDateTime;
 import java.util.Set;
 
 /**
@@ -25,21 +24,18 @@
  */
 @Slf4j
 @Component
+@RequiredArgsConstructor
 public class ReturnVisitReminderTask {
 
     private static final String REMINDER_QUEUE_KEY = "return_visit:reminder:queue";
 
-    @Autowired
-    private RedisCache redisCache;
+    private final RedisCache redisCache;
 
-    @Autowired
-    private CustomerReturnVisitService customerReturnVisitService;
+    private final CustomerReturnVisitService customerReturnVisitService;
 
-    @Autowired
-    private UnipushService unipushService;
+    private final UnipushService unipushService;
 
-    @Autowired
-    private SysUserClientService userClientService;
+    private final SysUserClientService userClientService;
 
     @SuppressWarnings("unchecked")
     @Scheduled(fixedDelay = 60000)
diff --git a/src/main/java/com/ruoyi/basic/task/StorageBlobCleanupTask.java b/src/main/java/com/ruoyi/basic/task/StorageBlobCleanupTask.java
new file mode 100644
index 0000000..d5ac456
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/task/StorageBlobCleanupTask.java
@@ -0,0 +1,184 @@
+package com.ruoyi.basic.task;
+
+import com.ruoyi.basic.mapper.StorageBlobMapper;
+import com.ruoyi.basic.pojo.StorageBlob;
+import com.ruoyi.common.config.FileProperties;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.io.File;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 娓呯悊鏃犳晥鏂囦欢瀹氭椂浠诲姟銆�
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class StorageBlobCleanupTask {
+
+    private static final int DB_BATCH_SIZE = 500;
+    private static final int FILE_NAME_BATCH_SIZE = 1000;
+
+    private final StorageBlobMapper storageBlobMapper;
+    private final FileProperties fileProperties;
+
+    private final AtomicBoolean running = new AtomicBoolean(false);
+
+    /**
+     * 姣忔湀 1 鍙峰噷鏅� 2 鐐规墽琛屼竴娆★細
+     * 1. 鍒犻櫎 storage_blob 涓湭琚� storage_attachment 鍏宠仈鐨勮褰曞強鍏舵枃浠�
+     * 2. 鍒犻櫎纾佺洏涓婁笉瀛樺湪浜� storage_blob.uid_filename 鐨勬枃浠�
+     */
+    @Scheduled(cron = "0 0 2 1 * ?")
+    public void cleanupUnusedStorageFiles() {
+        if (!running.compareAndSet(false, true)) {
+            log.warn("鏂囦欢娓呯悊浠诲姟姝e湪鎵ц锛屾湰娆¤烦杩�");
+            return;
+        }
+
+        long start = System.currentTimeMillis();
+        log.info("鏂囦欢娓呯悊浠诲姟寮�濮嬫墽琛岋紝鏍圭洰褰曪細{}", fileProperties.getPath());
+        try {
+            int removedBlobCount = cleanupOrphanStorageBlobs();
+            int removedDiskFileCount = cleanupOrphanDiskFiles();
+            long cost = System.currentTimeMillis() - start;
+            log.info("鏂囦欢娓呯悊浠诲姟鎵ц瀹屾垚锛屽垹闄ゅ鍎� blob 璁板綍锛歿}锛屽垹闄ょ鐩樻棤鏁堟枃浠讹細{}锛岃�楁椂锛歿} ms",
+                    removedBlobCount, removedDiskFileCount, cost);
+        } catch (Exception e) {
+            log.error("鏂囦欢娓呯悊浠诲姟鎵ц澶辫触", e);
+        } finally {
+            running.set(false);
+        }
+    }
+
+    private int cleanupOrphanStorageBlobs() {
+        long lastId = 0L;
+        int removedCount = 0;
+
+        while (true) {
+            List<StorageBlob> orphanBlobs = storageBlobMapper.selectOrphanBlobsByIdRange(lastId, DB_BATCH_SIZE);
+            if (CollectionUtils.isEmpty(orphanBlobs)) {
+                break;
+            }
+
+            List<Long> ids = new ArrayList<>(orphanBlobs.size());
+            for (StorageBlob storageBlob : orphanBlobs) {
+                ids.add(storageBlob.getId());
+                deleteBlobFiles(storageBlob);
+            }
+            storageBlobMapper.deleteByIdList(ids);
+            removedCount += ids.size();
+            lastId = orphanBlobs.get(orphanBlobs.size() - 1).getId();
+
+            log.info("宸插垹闄や竴鎵瑰鍎� blob锛宐atchSize={}锛宭astId={}", ids.size(), lastId);
+        }
+
+        return removedCount;
+    }
+
+    private int cleanupOrphanDiskFiles() {
+        File rootDirectory = new File(fileProperties.getPath());
+        if (!rootDirectory.exists() || !rootDirectory.isDirectory()) {
+            log.warn("鏂囦欢鏍圭洰褰曚笉瀛樺湪鎴栦笉鏄洰褰曪紝璺宠繃纾佺洏娓呯悊锛歿}", fileProperties.getPath());
+            return 0;
+        }
+
+        int deletedCount = 0;
+        Deque<File> directories = new ArrayDeque<>();
+        directories.push(rootDirectory);
+
+        while (!directories.isEmpty()) {
+            File currentDirectory = directories.pop();
+            File[] children = currentDirectory.listFiles();
+            if (children == null || children.length == 0) {
+                continue;
+            }
+
+            List<File> filesInDirectory = new ArrayList<>();
+            for (File child : children) {
+                if (child.isDirectory()) {
+                    directories.push(child);
+                } else if (child.isFile()) {
+                    filesInDirectory.add(child);
+                }
+            }
+
+            deletedCount += cleanupFilesInDirectory(filesInDirectory);
+        }
+
+        return deletedCount;
+    }
+
+    private int cleanupFilesInDirectory(List<File> filesInDirectory) {
+        if (CollectionUtils.isEmpty(filesInDirectory)) {
+            return 0;
+        }
+
+        int deletedCount = 0;
+        for (int start = 0; start < filesInDirectory.size(); start += FILE_NAME_BATCH_SIZE) {
+            int end = Math.min(start + FILE_NAME_BATCH_SIZE, filesInDirectory.size());
+            List<File> batchFiles = filesInDirectory.subList(start, end);
+            List<String> fileNames = new ArrayList<>(batchFiles.size());
+            for (File file : batchFiles) {
+                fileNames.add(file.getName());
+            }
+
+            Set<String> existingFileNames = new HashSet<>(storageBlobMapper.selectExistingUidFilenames(fileNames));
+            for (File file : batchFiles) {
+                if (!existingFileNames.contains(file.getName()) && safeDelete(file)) {
+                    deletedCount++;
+                }
+            }
+        }
+        return deletedCount;
+    }
+
+    private void deleteBlobFiles(StorageBlob storageBlob) {
+        File originalFile = resolveBlobFile(storageBlob);
+        safeDelete(originalFile);
+
+        File compressedFile = resolveCompressedFile(originalFile);
+        safeDelete(compressedFile);
+    }
+
+    private File resolveBlobFile(StorageBlob storageBlob) {
+        String basePath = fileProperties.getPath();
+        if (!StringUtils.hasText(storageBlob.getPath())) {
+            return new File(basePath, storageBlob.getUidFilename());
+        }
+        return new File(new File(basePath, storageBlob.getPath()), storageBlob.getUidFilename());
+    }
+
+    private File resolveCompressedFile(File originalFile) {
+        if (originalFile == null) {
+            return null;
+        }
+        File parent = originalFile.getParentFile();
+        if (parent == null) {
+            return null;
+        }
+        return new File(parent, "thumb_" + originalFile.getName());
+    }
+
+    private boolean safeDelete(File file) {
+        if (file == null || !file.exists() || !file.isFile()) {
+            return false;
+        }
+        if (file.delete()) {
+            return true;
+        }
+        log.warn("鍒犻櫎鏂囦欢澶辫触锛歿}", file.getAbsolutePath());
+        return false;
+    }
+}
diff --git a/src/main/java/com/ruoyi/basic/utils/FileUtil.java b/src/main/java/com/ruoyi/basic/utils/FileUtil.java
new file mode 100644
index 0000000..c57468a
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/utils/FileUtil.java
@@ -0,0 +1,847 @@
+package com.ruoyi.basic.utils;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
+import com.ruoyi.basic.dto.StorageAttachmentVO;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.basic.mapper.StorageBlobMapper;
+import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.basic.pojo.StorageBlob;
+import com.ruoyi.common.config.FileProperties;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.security.Keys;
+import lombok.RequiredArgsConstructor;
+import net.coobird.thumbnailator.Thumbnails;
+import org.springframework.beans.BeanUtils;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.crypto.SecretKey;
+import java.io.File;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Component
+@RequiredArgsConstructor
+public class FileUtil {
+    private final FileProperties properties;
+    private final StorageAttachmentMapper storageAttachmentMapper;
+    private final StringRedisTemplate stringRedisTemplate;
+    private final StorageBlobMapper storageBlobMapper;
+
+    private static final String TOKEN_USAGE_KEY_PREFIX = "file:token:usage:";
+    private static final DateTimeFormatter YEAR_PATH_FORMATTER = DateTimeFormatter.ofPattern("yyyy");
+    private static final DateTimeFormatter MONTH_DAY_PATH_FORMATTER = DateTimeFormatter.ofPattern("MMdd");
+
+    /**
+     * 淇濆瓨闄勪欢淇℃伅
+     *
+     * @param application     鏂囦欢鐢ㄩ��
+     * @param recordType      鍏宠仈璁板綍绫诲瀷
+     * @param recordId        鍏宠仈璁板綍id
+     * @param storageBlobDTOS 鏂囦欢淇℃伅
+     */
+    public void saveStorageAttachment(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, List<StorageBlobDTO> storageBlobDTOS) {
+        if (application == null) {
+            throw new RuntimeException("鏂囦欢鐢ㄩ�斾笉鑳戒负绌�");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        if (recordId == null || recordId <= 0) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+        // 鍒犻櫎鏃ч檮浠朵俊鎭�
+        deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageBlobDTOS)) {
+            return;
+        }
+        List<StorageAttachment> storageAttachments = new ArrayList<>();
+        for (StorageBlobDTO storageBlobDTO : storageBlobDTOS) {
+            StorageAttachment storageAttachment = new StorageAttachment();
+            storageAttachment.setApplication(application.getType());
+            storageAttachment.setRecordType(recordType.getType());
+            storageAttachment.setRecordId(recordId);
+            storageAttachment.setStorageBlobId(storageBlobDTO.getId());
+            storageAttachment.setDeleted(0L);
+            storageAttachments.add(storageAttachment);
+        }
+        storageAttachmentMapper.insert(storageAttachments);
+    }
+
+    /**
+     * 淇濆瓨闄勪欢淇℃伅
+     *
+     * @param recordType      鍏宠仈璁板綍绫诲瀷
+     * @param recordId        鍏宠仈璁板綍id
+     * @param storageBlobDTOS 鏂囦欢淇℃伅
+     */
+    public void saveStorageAttachmentByRecordTypeAndRecordId(String application,RecordTypeEnum recordType, Long recordId, List<StorageBlobDTO> storageBlobDTOS) {
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        if (recordId == null) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+
+        // 鍒犻櫎鏃ч檮浠朵俊鎭�
+        if (application == null) {
+            for (StorageBlobDTO storageBlobDTO : storageBlobDTOS) {
+                deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.getByType(storageBlobDTO.getApplication()), recordType, recordId);
+            }
+        } else {
+            deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.getByType(application), recordType, recordId);
+        }
+
+        if (CollectionUtils.isEmpty(storageBlobDTOS)) {
+            deleteStorageAttachmentsByRecordTypeAndRecordId(recordType, recordId);
+        }
+
+        List<StorageAttachment> storageAttachments = new ArrayList<>();
+        for (StorageBlobDTO storageBlobDTO : storageBlobDTOS) {
+            StorageAttachment storageAttachment = new StorageAttachment();
+            storageAttachment.setApplication(Objects.requireNonNullElseGet(application, () -> ApplicationTypeEnum.getByType(storageBlobDTO.getApplication()).getType()));
+            storageAttachment.setRecordType(recordType.getType());
+            storageAttachment.setRecordId(recordId);
+            storageAttachment.setStorageBlobId(storageBlobDTO.getId());
+            storageAttachment.setDeleted(0L);
+            storageAttachments.add(storageAttachment);
+        }
+        storageAttachmentMapper.insert(storageAttachments);
+    }
+
+    /**
+     * 鍒犻櫎鏂囦欢淇℃伅
+     *
+     * @param storageBlobIds 鏂囦欢id
+     */
+    public void deleteStorageBlobs(List<Long> storageBlobIds) {
+        storageBlobMapper.deleteByIds(storageBlobIds);
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鍒犻櫎鏂囦欢淇℃伅
+     *
+     * @param storageAttachmentIds 鏂囦欢id
+     */
+    public void deleteStorageBlobsByStorageAttachmentIds(List<Long> storageAttachmentIds) {
+        List<StorageAttachment> storageAttachments = storageAttachmentMapper.selectByIds(storageAttachmentIds);
+        List<Long> storageBlobIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList());
+        deleteStorageBlobs(storageBlobIds);
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鐢ㄩ�斻�佸叧鑱旇褰曠被鍨嬨�佸叧鑱旇褰昳d鍒犻櫎鏂囦欢淇℃伅
+     *
+     * @param application 鏂囦欢鐢ㄩ��
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordIds    鍏宠仈璁板綍id
+     */
+    public void deleteStorageBlobsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum application, RecordTypeEnum recordType, List<Long> recordIds) {
+        if (recordIds == null || recordIds.isEmpty()) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+        if (application == null) {
+            throw new RuntimeException("鏂囦欢鐢ㄩ�斾笉鑳戒负绌�");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        List<StorageAttachment> storageAttachments = storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, recordType.getType())
+                .in(StorageAttachment::getRecordId, recordIds)
+                .eq(StorageAttachment::getApplication, application.getType()));
+        if (CollectionUtils.isNotEmpty(storageAttachments)) {
+            List<Long> storageAttachmentIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId)
+                    .collect(Collectors.toList());
+            deleteStorageBlobsByStorageAttachmentIds(storageAttachmentIds);
+        }
+    }
+
+    /**
+     * 閫氳繃鍏宠仈璁板綍绫诲瀷銆佸叧鑱旇褰昳d鍒犻櫎鏂囦欢淇℃伅
+     *
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     */
+    public void deleteStorageBlobsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId) {
+        if (recordId == null || recordId <= 0) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        List<StorageAttachment> storageAttachments = storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, recordType.getType())
+                .eq(StorageAttachment::getRecordId, recordId));
+        if (CollectionUtils.isNotEmpty(storageAttachments)) {
+            List<Long> storageAttachmentIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId)
+                    .collect(Collectors.toList());
+            deleteStorageBlobsByStorageAttachmentIds(storageAttachmentIds);
+        }
+    }
+
+    /**
+     * 鍒犻櫎鏂囦欢鍏宠仈淇℃伅
+     *
+     * @param storageAttachmentIds 鏂囦欢鍏宠仈id
+     */
+    public void deleteStorageAttachmentsByStorageAttachmentIds(List<Long> storageAttachmentIds) {
+        deleteStorageBlobsByStorageAttachmentIds(storageAttachmentIds);
+        storageAttachmentMapper.deleteByIds(storageAttachmentIds);
+    }
+
+    /**
+     * 鍒犻櫎鏂囦欢鍏宠仈淇℃伅
+     *
+     * @param application 鏂囦欢鐢ㄩ��
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     */
+    public void deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId) {
+        if (recordId == null || recordId <= 0) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+        if (application == null) {
+            throw new RuntimeException("鏂囦欢鐢ㄩ�斾笉鑳戒负绌�");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        deleteStorageBlobsByApplicationAndRecordTypeAndRecordIds(application, recordType, Arrays.asList(recordId));
+        storageAttachmentMapper.delete(new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, recordType.getType())
+                .eq(StorageAttachment::getRecordId, recordId)
+                .eq(StorageAttachment::getApplication, application.getType()));
+    }
+
+    /**
+     * 鍒犻櫎鏂囦欢鍏宠仈淇℃伅
+     *
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     */
+    public void deleteStorageAttachmentsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId) {
+        if (recordId == null || recordId <= 0) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        deleteStorageBlobsByRecordTypeAndRecordId(recordType, recordId);
+        storageAttachmentMapper.delete(new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, recordType.getType())
+                .eq(StorageAttachment::getRecordId, recordId));
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鏂囦欢鍏宠仈淇℃伅 attachment
+     *
+     * @param application 鏂囦欢鐢ㄩ��
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordIds   鍏宠仈璁板綍id
+     */
+    public void deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum application, RecordTypeEnum recordType, List<Long> recordIds) {
+        if (recordIds == null || recordIds.isEmpty()) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+        if (application == null) {
+            throw new RuntimeException("鏂囦欢鐢ㄩ�斾笉鑳戒负绌�");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        deleteStorageBlobsByApplicationAndRecordTypeAndRecordIds(application, recordType, recordIds);
+        storageAttachmentMapper.delete(new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, recordType.getType())
+                .in(StorageAttachment::getRecordId, recordIds)
+                .eq(StorageAttachment::getApplication, application.getType()));
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢淇℃伅 attachment
+     *
+     * @param storageAttachmentIds 鏂囦欢id
+     */
+    public List<StorageAttachment> getStorageAttachmentsByStorageAttachmentIds(List<Long> storageAttachmentIds) {
+        if (CollectionUtils.isEmpty(storageAttachmentIds)) {
+            throw new RuntimeException("鏂囦欢id涓嶈兘涓虹┖");
+        }
+        return storageAttachmentMapper.selectByIds(storageAttachmentIds);
+    }
+
+    /**
+     * 閫氳繃璁板綍绫诲瀷鑾峰彇鏂囦欢淇℃伅 attachment锛堝垎椤碉級
+     *
+     * @param storageAttachmentDTO 鍏宠仈璁板綍淇℃伅
+     */
+    public List<StorageBlobVO> getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(StorageAttachmentDTO storageAttachmentDTO) {
+        LambdaQueryWrapper<StorageAttachment> queryWrapper = new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, storageAttachmentDTO.getRecordType())
+                .eq(StorageAttachment::getRecordId, storageAttachmentDTO.getRecordId());
+        if (storageAttachmentDTO.getApplication() != null) {
+            queryWrapper.eq(StorageAttachment::getApplication, storageAttachmentDTO.getApplication());
+        }
+        List<StorageAttachment> storageAttachments = storageAttachmentMapper.selectList(queryWrapper);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return null;
+        }
+        return getStorageBlobVOsByStorageAttachmentIds(storageAttachments.stream().map(StorageAttachment::getId).collect(Collectors.toList()));
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鐢ㄩ�斻�佸叧鑱旇褰曠被鍨嬨�佸叧鑱旇褰昳d鑾峰彇鏂囦欢鍏宠仈淇℃伅 attachment
+     *
+     * @param application 鏂囦欢鐢ㄩ��
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     */
+    public List<StorageAttachment> getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId) {
+        if (recordId == null || recordId <= 0) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }        if (application == null) {
+            throw new RuntimeException("鏂囦欢鐢ㄩ�斾笉鑳戒负绌�");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        return storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, recordType.getType())
+                .eq(StorageAttachment::getRecordId, recordId)
+                .eq(StorageAttachment::getApplication, application.getType()));
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢淇℃伅 blob
+     *
+     * @param storageAttachmentIds 鏂囦欢id
+     */
+    public List<StorageBlobVO> getStorageBlobVOsByStorageAttachmentIds(List<Long> storageAttachmentIds) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByStorageAttachmentIds(storageAttachmentIds);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return null;
+        }
+        Map<Long, Long> blobIdToAttachmentIdMap = storageAttachments.stream()
+                .collect(Collectors.toMap(StorageAttachment::getStorageBlobId, StorageAttachment::getId));
+
+        List<Long> storageBlobIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList());
+        List<StorageBlob> storageBlobs = storageBlobMapper.selectByIds(storageBlobIds);
+        List<StorageBlobVO> storageBlobDTOS = new ArrayList<>();
+        for (StorageBlob storageBlob : storageBlobs) {
+            StorageBlobVO storageBlobVO = new StorageBlobVO();
+            BeanUtils.copyProperties(storageBlob, storageBlobVO);
+            storageBlobVO.setPreviewURL(buildSignedPreviewUrl(storageBlobVO));
+            storageBlobVO.setDownloadURL(buildSignedDownloadUrl(storageBlobVO));
+            storageBlobVO.setStorageAttachmentId(blobIdToAttachmentIdMap.get(storageBlob.getId()));
+            storageBlobDTOS.add(storageBlobVO);
+        }
+        return storageBlobDTOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鐢ㄩ�斻�佸叧鑱旇褰曠被鍨嬨�佸叧鑱旇褰昳d鑾峰彇鏂囦欢鍏宠仈淇℃伅 attachment
+     *
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     */
+    public List<StorageAttachment> getStorageAttachmentsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId) {
+        if (recordId == null || recordId <= 0) {
+            throw new RuntimeException("鍏宠仈璁板綍id涓嶈兘涓虹┖");
+        }
+        if (recordType == null) {
+            throw new RuntimeException("鍏宠仈璁板綍绫诲瀷涓嶈兘涓虹┖");
+        }
+        return storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>()
+                .eq(StorageAttachment::getRecordType, recordType.getType())
+                .eq(StorageAttachment::getRecordId, recordId));
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鐢ㄩ�斻�佸叧鑱旇褰曠被鍨嬨�佸叧鑱旇褰昳d鑾峰彇鏂囦欢淇℃伅 blob
+     *
+     * @param application 鏂囦欢鐢ㄩ��
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     */
+    public List<StorageBlobVO> getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return null;
+        }
+        // 鏋勫缓 storageBlobId -> storageAttachmentId 鐨勬槧灏�
+        Map<Long, Long> blobIdToAttachmentIdMap = storageAttachments.stream()
+                .collect(Collectors.toMap(StorageAttachment::getStorageBlobId, StorageAttachment::getId));
+
+        List<Long> storageBlobIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList());
+        List<StorageBlob> storageBlobs = storageBlobMapper.selectByIds(storageBlobIds);
+        List<StorageBlobVO> storageBlobDTOS = new ArrayList<>();
+        for (StorageBlob storageBlob : storageBlobs) {
+            StorageBlobVO storageBlobVO = new StorageBlobVO();
+            BeanUtils.copyProperties(storageBlob, storageBlobVO);
+            storageBlobVO.setPreviewURL(buildSignedPreviewUrl(storageBlobVO));
+            storageBlobVO.setDownloadURL(buildSignedDownloadUrl(storageBlobVO));
+            storageBlobVO.setStorageAttachmentId(blobIdToAttachmentIdMap.get(storageBlob.getId()));
+            storageBlobDTOS.add(storageBlobVO);
+        }
+        return storageBlobDTOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鐢ㄩ�斻�佸叧鑱旇褰曠被鍨嬨�佸叧鑱旇褰昳d鑾峰彇鏂囦欢淇℃伅 blob
+     *
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     */
+    public List<StorageBlobVO> getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum recordType, Long recordId) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByRecordTypeAndRecordId(recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return null;
+        }
+        List<Long> storageBlobIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList());
+        List<StorageBlob> storageBlobs = storageBlobMapper.selectByIds(storageBlobIds);
+        List<StorageBlobVO> storageBlobDTOS = new ArrayList<>();
+        for (StorageBlob storageBlob : storageBlobs) {
+            StorageBlobVO storageBlobVO = new StorageBlobVO();
+            BeanUtils.copyProperties(storageBlob, storageBlobVO);
+            storageBlobVO.setPreviewURL(buildSignedPreviewUrl(storageBlobVO));
+            storageBlobVO.setDownloadURL(buildSignedDownloadUrl(storageBlobVO));
+            storageBlobDTOS.add(storageBlobVO);
+        }
+        return storageBlobDTOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鐢ㄩ�斻�佸叧鑱旇褰曠被鍨嬨�佸叧鑱旇褰昳d鑾峰彇鏂囦欢淇℃伅 鑷畾涔夎繃鏈熸椂闂达紙鍒嗛挓锛� blob
+     *
+     * @param application 鏂囦欢鐢ㄩ��
+     * @param recordType  鍏宠仈璁板綍绫诲瀷
+     * @param recordId    鍏宠仈璁板綍id
+     * @param expired     杩囨湡鏃堕棿
+     */
+    public List<StorageBlobVO> getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return null;
+        }
+        // 鏋勫缓 storageBlobId -> storageAttachmentId 鐨勬槧灏�
+        Map<Long, Long> blobIdToAttachmentIdMap = storageAttachments.stream()
+                .collect(Collectors.toMap(StorageAttachment::getStorageBlobId, StorageAttachment::getId));
+
+        List<Long> storageBlobIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList());
+        List<StorageBlob> storageBlobs = storageBlobMapper.selectByIds(storageBlobIds);
+        List<StorageBlobVO> storageBlobDTOS = new ArrayList<>();
+        for (StorageBlob storageBlob : storageBlobs) {
+            StorageBlobVO storageBlobVO = new StorageBlobVO();
+            BeanUtils.copyProperties(storageBlob, storageBlobVO);
+            storageBlobVO.setPreviewURL(buildSignedUrl(storageBlobVO, "/preview/", expired));
+            storageBlobVO.setDownloadURL(buildSignedUrl(storageBlobVO, "/download/", expired));
+            storageBlobVO.setStorageAttachmentId(blobIdToAttachmentIdMap.get(storageBlob.getId()));
+            storageBlobDTOS.add(storageBlobVO);
+        }
+        return storageBlobDTOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢淇℃伅瀛樺湪杩囨湡鏃堕棿 鑷畾涔夎繃鏈熸椂闂达紙鍒嗛挓锛� blob
+     *
+     * @param storageAttachmentIds 鏂囦欢id
+     * @param expired              杩囨湡鏃堕棿
+     */
+    public List<StorageBlobVO> getStorageBlobVOsByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByStorageAttachmentIds(storageAttachmentIds);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return null;
+        }
+        List<Long> storageBlobIds = storageAttachments.stream().map(StorageAttachment::getStorageBlobId).collect(Collectors.toList());
+        List<StorageBlob> storageBlobs = storageBlobMapper.selectByIds(storageBlobIds);
+        List<StorageBlobVO> storageBlobDTOS = new ArrayList<>();
+        for (StorageBlob storageBlob : storageBlobs) {
+            StorageBlobVO storageBlobVO = new StorageBlobVO();
+            BeanUtils.copyProperties(storageBlob, storageBlobVO);
+            storageBlobVO.setPreviewURL(buildSignedUrl(storageBlobVO, "/preview/", expired));
+            storageBlobVO.setDownloadURL(buildSignedUrl(storageBlobVO, "/download/", expired));
+            storageBlobDTOS.add(storageBlobVO);
+        }
+        return storageBlobDTOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢淇℃伅 attachment
+     *
+     * @param storageAttachmentIds 鏂囦欢id
+     */
+    public List<StorageAttachmentVO> getStorageAttachmentVOSByStorageAttachmentIds(List<Long> storageAttachmentIds) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByStorageAttachmentIds(storageAttachmentIds);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        List<StorageAttachmentVO> storageAttachmentVOS = new ArrayList<>();
+        for (StorageAttachment storageAttachment : storageAttachments) {
+            StorageAttachmentVO storageAttachmentVO = new StorageAttachmentVO();
+            BeanUtils.copyProperties(storageAttachment, storageAttachmentVO);
+            List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(Collections.singletonList(storageAttachment.getId()));
+            if (CollectionUtils.isEmpty(storageBlobVOS)) {
+                storageAttachmentVO.setStorageBlobVOS(new ArrayList<>());
+            } else {
+                storageAttachmentVO.setStorageBlobVOS(storageBlobVOS);
+            }
+            storageAttachmentVOS.add(storageAttachmentVO);
+        }
+        return storageAttachmentVOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢淇℃伅瀛樺湪杩囨湡鏃堕棿 鑷畾涔夎繃鏈熸椂闂达紙鍒嗛挓锛� attachment
+     *
+     * @param storageAttachmentIds 鏂囦欢id
+     * @param expired              杩囨湡鏃堕棿
+     */
+    public List<StorageAttachmentVO> getStorageAttachmentVOSByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByStorageAttachmentIds(storageAttachmentIds);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        List<StorageAttachmentVO> storageAttachmentVOS = new ArrayList<>();
+        for (StorageAttachment storageAttachment : storageAttachments) {
+            StorageAttachmentVO storageAttachmentVO = new StorageAttachmentVO();
+            BeanUtils.copyProperties(storageAttachment, storageAttachmentVO);
+            List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(Collections.singletonList(storageAttachment.getId()), expired);
+            if (CollectionUtils.isEmpty(storageBlobVOS)) {
+                storageAttachmentVO.setStorageBlobVOS(new ArrayList<>());
+            } else {
+                storageAttachmentVO.setStorageBlobVOS(storageBlobVOS);
+            }
+            storageAttachmentVOS.add(storageAttachmentVO);
+        }
+        return storageAttachmentVOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢淇℃伅 attachment
+     *
+     * @param application 搴旂敤
+     * @param recordType  璁板綍绫诲瀷
+     * @param recordId    璁板綍id
+     */
+    public List<StorageAttachmentVO> getStorageAttachmentVOSByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        List<StorageAttachmentVO> storageAttachmentVOS = new ArrayList<>();
+        for (StorageAttachment storageAttachment : storageAttachments) {
+            StorageAttachmentVO storageAttachmentVO = new StorageAttachmentVO();
+            BeanUtils.copyProperties(storageAttachment, storageAttachmentVO);
+            List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(Collections.singletonList(storageAttachment.getId()));
+            if (CollectionUtils.isEmpty(storageBlobVOS)) {
+                storageAttachmentVO.setStorageBlobVOS(new ArrayList<>());
+            } else {
+                storageAttachmentVO.setStorageBlobVOS(storageBlobVOS);
+            }
+            storageAttachmentVOS.add(storageAttachmentVO);
+        }
+        return storageAttachmentVOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢淇℃伅瀛樺湪杩囨湡鏃堕棿 鑷畾涔夎繃鏈熸椂闂达紙鍒嗛挓锛� attachment
+     *
+     * @param application 搴旂敤
+     * @param recordType  璁板綍绫诲瀷
+     * @param recordId    璁板綍id
+     * @param expired     杩囨湡鏃堕棿
+     */
+    public List<StorageAttachmentVO> getStorageAttachmentVOSByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        List<StorageAttachmentVO> storageAttachmentVOS = new ArrayList<>();
+        for (StorageAttachment storageAttachment : storageAttachments) {
+            StorageAttachmentVO storageAttachmentVO = new StorageAttachmentVO();
+            BeanUtils.copyProperties(storageAttachment, storageAttachmentVO);
+            List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(Collections.singletonList(storageAttachment.getId()), expired);
+            if (CollectionUtils.isEmpty(storageBlobVOS)) {
+                storageAttachmentVO.setStorageBlobVOS(new ArrayList<>());
+            } else {
+                storageAttachmentVO.setStorageBlobVOS(storageBlobVOS);
+            }
+            storageAttachmentVOS.add(storageAttachmentVO);
+        }
+        return storageAttachmentVOS;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢棰勮鍦板潃
+     *
+     * @param storageAttachmentIds 鏂囦欢鍏宠仈id
+     */
+    public List<String> getFilePreviewURLByStorageAttachmentIds(List<Long> storageAttachmentIds) {
+        List<String> res = new ArrayList<>();
+        List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(storageAttachmentIds);
+        for (StorageBlobVO storageBlobVO : storageBlobVOS) {
+            res.add(buildSignedPreviewUrl(storageBlobVO));
+        }
+        return res;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢棰勮鍦板潃瀛樺湪杩囨湡鏃堕棿 鑷畾涔夎繃鏈熸椂闂达紙鍒嗛挓锛�
+     *
+     * @param storageAttachmentIds 鏂囦欢鍏宠仈id
+     * @param expired              杩囨湡鏃堕棿
+     */
+    public List<String> getFilePreviewURLByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired) {
+        List<String> res = new ArrayList<>();
+        List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(storageAttachmentIds);
+        for (StorageBlobVO storageBlobVO : storageBlobVOS) {
+            res.add(buildSignedUrl(storageBlobVO, "/preview/", expired));
+        }
+        return res;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢涓嬭浇鍦板潃
+     *
+     * @param storageAttachmentIds 鏂囦欢鍏宠仈id
+     */
+    public List<String> getFileDownloadURLByStorageAttachmentIds(List<Long> storageAttachmentIds) {
+        List<String> res = new ArrayList<>();
+        List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(storageAttachmentIds);
+        for (StorageBlobVO storageBlobVO : storageBlobVOS) {
+            res.add(buildSignedDownloadUrl(storageBlobVO));
+        }
+        return res;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢涓嬭浇鍦板潃瀛樺湪杩囨湡鏃堕棿 鑷畾涔夎繃鏈熸椂闂达紙鍒嗛挓锛�
+     *
+     * @param storageAttachmentIds 鏂囦欢鍏宠仈id
+     * @param expired              杩囨湡鏃堕棿
+     */
+    public List<String> getFileDownloadURLByStorageAttachmentIds(List<Long> storageAttachmentIds, BigDecimal expired) {
+        List<String> res = new ArrayList<>();
+        List<StorageBlobVO> storageBlobVOS = getStorageBlobVOsByStorageAttachmentIds(storageAttachmentIds);
+        for (StorageBlobVO storageBlobVO : storageBlobVOS) {
+            res.add(buildSignedUrl(storageBlobVO, "/download/", expired));
+        }
+        return res;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢棰勮鍦板潃
+     *
+     * @param application 搴旂敤
+     * @param recordType  璁板綍绫诲瀷
+     * @param recordId    璁板綍id
+     */
+    public List<String> getFilePreviewURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        return getFilePreviewURLByStorageAttachmentIds(storageAttachments.stream().map(StorageAttachment::getId).collect(Collectors.toList()));
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢棰勮鍦板潃瀛樺湪杩囨湡鏃堕棿
+     *
+     * @param application 搴旂敤
+     * @param recordType  璁板綍绫诲瀷
+     * @param recordId    璁板綍id
+     * @param expired     杩囨湡鏃堕棿锛堝垎閽燂級
+     */
+    public List<String> getFilePreviewURLByApplicationAndRecordTypeAndRecordIdAndExpired(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        return getFilePreviewURLByStorageAttachmentIds(storageAttachments.stream().map(StorageAttachment::getId).collect(Collectors.toList()), expired);
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢涓嬭浇鍦板潃
+     *
+     * @param application 搴旂敤
+     * @param recordType  璁板綍绫诲瀷
+     * @param recordId    璁板綍id
+     */
+    public List<String> getFileDownloadURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        return getFileDownloadURLByStorageAttachmentIds(storageAttachments.stream().map(StorageAttachment::getId).collect(Collectors.toList()));
+    }
+
+    /**
+     * 閫氳繃鏂囦欢鍏宠仈id鑾峰彇鏂囦欢涓嬭浇鍦板潃瀛樺湪杩囨湡鏃堕棿
+     *
+     * @param application 搴旂敤
+     * @param recordType  璁板綍绫诲瀷
+     * @param recordId    璁板綍id
+     * @param expired     杩囨湡鏃堕棿锛堝垎閽燂級
+     */
+    public List<String> getFileDownloadURLByApplicationAndRecordTypeAndRecordIdAndExpired(ApplicationTypeEnum application, RecordTypeEnum recordType, Long recordId, BigDecimal expired) {
+        List<StorageAttachment> storageAttachments = getStorageAttachmentsByApplicationAndRecordTypeAndRecordId(application, recordType, recordId);
+        if (CollectionUtils.isEmpty(storageAttachments)) {
+            return new ArrayList<>();
+        }
+        return getFileDownloadURLByStorageAttachmentIds(storageAttachments.stream().map(StorageAttachment::getId).collect(Collectors.toList()), expired);
+    }
+
+    public String buildSignedPreviewUrl(StorageBlobVO storageBlob) {
+        return buildSignedUrl(storageBlob, "/preview/", properties.getExpired());
+    }
+    public String buildSignedDownloadUrl(StorageBlobVO storageBlob) {
+        return buildSignedUrl(storageBlob, "/download/", properties.getExpired());
+    }
+
+    /**
+     * 鏋勫缓甯︾鍚嶇殑URL
+     *
+     * @param storageBlob 鏂囦欢鍏冩暟鎹�
+     * @param actionPath  鎿嶄綔璺緞 "/preview/" or "/download/"
+     * @param expired     杩囨湡鏃堕棿 濡傛灉涓嶉厤缃紝涓嶄紶鍙傦紝灏嗕娇鐢ㄩ粯璁ゅ��120鍒嗛挓
+     * @return 甯︾鍚嶇殑URL
+     */
+    public String buildSignedUrl(StorageBlobVO storageBlob, String actionPath, BigDecimal expired) {
+        if (!Arrays.asList("/preview/", "/download/").contains(actionPath)) {
+            throw new IllegalArgumentException("鎿嶄綔璺緞鍙傛暟閿欒");
+        }
+        if (storageBlob == null || !StringUtils.hasText(storageBlob.getUidFilename())) {
+            throw new IllegalArgumentException("鏂囦欢淇℃伅涓嶅畬鏁�");
+        }
+        String domain = StringUtils.trimTrailingCharacter(properties.getDomain(), '/');
+        String prefix = properties.getUrlPrefix().startsWith("/") ? properties.getUrlPrefix() : "/" + properties.getUrlPrefix();
+        String normalizedActionPath = StringUtils.hasText(actionPath) ? actionPath : "/preview/";
+        if (!normalizedActionPath.startsWith("/")) {
+            normalizedActionPath = "/" + normalizedActionPath;
+        }
+        if (!normalizedActionPath.endsWith("/")) {
+            normalizedActionPath = normalizedActionPath + "/";
+        }
+        String baseUrl = domain + prefix + normalizedActionPath + storageBlob.getUidFilename();
+
+        // -1 琛ㄧず姘镐箙鏈夋晥锛屼笉鐢熸垚 token锛屾敼涓� publicKey 缁勫悎鏍¢獙
+        if (expired != null && BigDecimal.valueOf(-1L).compareTo(expired) == 0) {
+            if (!StringUtils.hasText(storageBlob.getResourceKey())) {
+                throw new IllegalArgumentException("鍏紑閾炬帴缂哄皯publicKey");
+            }
+            return baseUrl + "?publicKey=" + storageBlob.getResourceKey();
+        }
+
+        long now = System.currentTimeMillis();
+        BigDecimal expiredValue = expired == null ? new BigDecimal("120") : expired;
+        long expiredMillis = expiredValue.multiply(new BigDecimal("60000")).longValue();
+        if (expiredMillis <= 0L) {
+            expiredMillis = 2L * 60L * 60L * 1000L;
+        }
+        Date issuedAt = new Date(now);
+        Date expiration = new Date(now + expiredMillis);
+        SecretKey key = Keys.hmacShaKeyFor(properties.getJwtSecret().getBytes(StandardCharsets.UTF_8));
+
+        String token = Jwts.builder()
+                .subject(storageBlob.getUidFilename())
+                .issuedAt(issuedAt)       // 鏂扮増寤鸿鐩存帴璋冪敤 .issuedAt()
+                .expiration(expiration)   // 鏂扮増寤鸿鐩存帴璋冪敤 .expiration()
+                .claim("path", storageBlob.getPath())
+                .claim("resourceKey", storageBlob.getResourceKey())
+                .signWith(key)            // 閲嶇偣锛氫紶鍏ヤ笂闈㈢敓鎴愮殑 key 瀵硅薄锛岃�屼笉鏄� String
+                .compact();
+        cacheTokenUsage(token, expiredMillis);
+        return baseUrl + "?token=" + token;
+    }
+
+    private void cacheTokenUsage(String token, long expiredMillis) {
+        if (!StringUtils.hasText(token)) {
+            return;
+        }
+        long ttl = expiredMillis > 0L ? expiredMillis : 2L * 60L * 60L * 1000L;
+        stringRedisTemplate.opsForValue().set(buildTokenUsageKey(token), "0", ttl, TimeUnit.MILLISECONDS);
+    }
+
+    private String buildTokenUsageKey(String token) {
+        return TOKEN_USAGE_KEY_PREFIX + token;
+    }
+
+    public String buildRelativePath() {
+        LocalDate now = LocalDate.now();
+        return now.format(YEAR_PATH_FORMATTER) + "/" + now.format(MONTH_DAY_PATH_FORMATTER);
+    }
+
+    public void validateTokenUsage(String token) {
+        String redisKey = buildTokenUsageKey(token);
+        String currentCountValue = stringRedisTemplate.opsForValue().get(redisKey);
+        if (!StringUtils.hasText(currentCountValue)) {
+            throw new IllegalArgumentException("閾炬帴宸茶繃鏈熸垨杈惧埌浣跨敤娆℃暟澶辨晥");
+        }
+        long currentCount = Long.parseLong(currentCountValue);
+        int limit = resolveLimit();
+        if (currentCount >= limit) {
+            stringRedisTemplate.delete(redisKey);
+            throw new IllegalArgumentException("閾炬帴杈惧埌浣跨敤娆℃暟澶辨晥");
+        }
+        Long updatedCount = stringRedisTemplate.opsForValue().increment(redisKey);
+        if (updatedCount != null && updatedCount >= limit) {
+            stringRedisTemplate.delete(redisKey);
+        }
+    }
+
+    private int resolveLimit() {
+        return properties.getUseLimit() == null || properties.getUseLimit() <= 0 ? 10 : properties.getUseLimit();
+    }
+
+    /**
+     * 鍘嬬缉鏂囦欢 鍥剧墖
+     *
+     * @param file 鏂囦欢
+     * @return 鍘嬬缉鍚庣殑鏂囦欢
+     */
+    public File compressFile(File file) {
+        if (properties.getCompress() && isImage(file.getName()) && (file.length() > properties.getNeedCompressSize().toBytes())) {
+            try {
+                // 鍒涘缓涓�涓复鏃舵枃浠跺瓨鏀惧帇缂╁悗鐨勫浘鐗囷紝閬垮厤鐮村潖鍘熷浘
+                File compressedFile = new File(file.getParent(), "thumb_" + file.getName());
+
+                // 1. 濡傛灉宸茬粡瀛樺湪鍘嬬缉杩囩殑鏂囦欢锛岀洿鎺ヨ繑鍥烇紝涓嶅啀娑堣�� CPU 鍘嬬缉
+                if (compressedFile.exists()) {
+                    return compressedFile;
+                }
+
+                // 浣跨敤 Thumbnailator 杩涜鍘嬬缉
+                Thumbnails.of(file)
+                        .scale(1.0f)                // 淇濇寔鍘熷昂瀵�
+                        .outputQuality(properties.getCompressQuality())        // 鏍稿績锛氳缃敾璐� (0.0~1.0)
+                        .toFile(compressedFile);
+
+                return compressedFile;
+            } catch (Exception e) {
+                // 濡傛灉鍘嬬缉澶辫触锛岄檷绾у鐞嗭細杩斿洖鍘熷浘
+                return file;
+            }
+        }
+        return file;
+    }
+    // 绠�鍗曠殑鍚庣紑鍒ゆ柇
+    private boolean isImage(String fileName) {
+        String ext = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
+        return "jpg".equals(ext) || "jpeg".equals(ext) || "png".equals(ext);
+    }
+
+
+}
diff --git a/src/main/java/com/ruoyi/basic/vo/CustomerVo.java b/src/main/java/com/ruoyi/basic/vo/CustomerVo.java
new file mode 100644
index 0000000..3d4c8cb
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/vo/CustomerVo.java
@@ -0,0 +1,28 @@
+package com.ruoyi.basic.vo;
+
+import com.ruoyi.basic.dto.CustomerFollowUpDto;
+import com.ruoyi.basic.pojo.Customer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CustomerVo extends Customer {
+    @ApiModelProperty(value = "璺熻繘璁板綍")
+    private List<CustomerFollowUpDto> followUpList;
+
+    private String usageUserName;
+
+    private String togetherUserNames;
+
+    /**
+     * 鍏变韩鐢ㄦ埛ID鍒楄〃
+     */
+    private List<Long> userIds;
+
+    /**
+     * 鍏变韩鐢ㄦ埛ID瀛楃涓诧紙SQL鏌ヨ杩斿洖锛岀敤浜庤浆鎹负List锛�
+     */
+    private String userIdsStr;
+}
diff --git a/src/main/java/com/ruoyi/basic/vo/ProductModelVo.java b/src/main/java/com/ruoyi/basic/vo/ProductModelVo.java
new file mode 100644
index 0000000..cdcd893
--- /dev/null
+++ b/src/main/java/com/ruoyi/basic/vo/ProductModelVo.java
@@ -0,0 +1,14 @@
+package com.ruoyi.basic.vo;
+
+import com.ruoyi.basic.pojo.ProductModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ProductModelVo extends ProductModel {
+
+    private List<String> batchNoList;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/DutyPlanController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/DutyPlanController.java
index 9ad69ee..d622e99 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/DutyPlanController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/DutyPlanController.java
@@ -8,47 +8,46 @@
 import com.ruoyi.collaborativeApproval.service.DutyPlanService;
 import com.ruoyi.common.utils.excel.ExcelUtils;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/dutyPlan")
 @AllArgsConstructor
 public class DutyPlanController {
-    @Autowired
     private DutyPlanService dutyPlanService;
 
     @GetMapping("/getList")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, DutyPlanDTO dutyPlanDTO){
         return AjaxResult.success(dutyPlanService.listPage(page, dutyPlanDTO));
     }
     @GetMapping("/getNum")
-    @ApiOperation("鑾峰彇绛夌骇鏁版嵁")
+    @Operation(summary = "鑾峰彇绛夌骇鏁版嵁")
     public AjaxResult getNum(){
         return AjaxResult.success(dutyPlanService.getNum());
     }
 
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody DutyPlan dutyPlan){
         return AjaxResult.success(dutyPlanService.save(dutyPlan));
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼")
+    @Operation(summary = "淇敼")
     public AjaxResult update(@RequestBody DutyPlan dutyPlan){
         return AjaxResult.success(dutyPlanService.updateById(dutyPlan));
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delete(@RequestBody List<Long> ids){
         if (CollectionUtils.isEmpty(ids)) {
             throw new RuntimeException("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
@@ -56,7 +55,7 @@
         return AjaxResult.success(dutyPlanService.removeBatchByIds(ids));
     }
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭")
+    @Operation(summary = "瀵煎嚭")
     public void exportData(HttpServletResponse response, DutyPlanDTO dutyPlanDTO){
         dutyPlanService.exportData(response, dutyPlanDTO);
     }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/MeetingController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/MeetingController.java
index 956c8bc..917bda6 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/MeetingController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/MeetingController.java
@@ -14,12 +14,12 @@
 import com.ruoyi.collaborativeApproval.vo.SearchMeetingUseVo;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.R;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -32,7 +32,7 @@
 @RestController
 @RequestMapping("/meeting")
 @RequiredArgsConstructor
-@Api(tags = "浼氳")
+@Tag(name = "浼氳")
 public class MeetingController {
     private final MeetingService meetingService;
 
@@ -126,7 +126,7 @@
         return R.ok(meetingService.getMeetSummaryItems());
     }
 
-    @ApiOperation(value = "浼氳瀹よ缃鍑�")
+    @Operation(summary = "浼氳瀹よ缃鍑�")
     @PostMapping("/export")
     public void export(HttpServletResponse response) {
         List<MeetingRoom> accountExpenses = meetingService.list();
@@ -136,7 +136,7 @@
 
     private final MeetDraftMapper meetDraftMapper;
 
-    @ApiOperation(value = "浼氳鑽夌瀵煎嚭")
+    @Operation(summary = "浼氳鑽夌瀵煎嚭")
     @PostMapping("/exportOne")
     public void exportOne(HttpServletResponse response) {
         List<MeetDraft> accountExpenses = meetDraftMapper.selectList(new LambdaQueryWrapper<MeetDraft>());
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java
index 8fe67d0..ba1df00 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java
@@ -11,8 +11,8 @@
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.service.ISysNoticeService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
@@ -22,7 +22,7 @@
 
 @RestController
 @AllArgsConstructor
-@Api(tags = "閫氱煡鍏憡")
+@Tag(name = "閫氱煡鍏憡")
 @RequestMapping("/collaborativeApproval/notice")
 public class NoticeController extends BaseController {
 
@@ -31,14 +31,14 @@
 
     @GetMapping("/page")
     @Log(title = "鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, NoticeDTO noticeDTO){
         return AjaxResult.success(noticeService.listPage(page, noticeDTO));
     }
 
     @PostMapping("/add")
     @Log(title = "鏂板", businessType = BusinessType.INSERT)
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody NoticeDTO noticeDTO){
         if (noticeDTO.getStatus()==1){
             //姝e紡鍙戝竷閫氱煡鎵�鏈変汉鐨勬秷鎭�氱煡
@@ -51,7 +51,7 @@
 
     @PutMapping("/update")
     @Log(title = "淇敼", businessType = BusinessType.UPDATE)
-    @ApiOperation("淇敼")
+    @Operation(summary = "淇敼")
     public AjaxResult update(@RequestBody NoticeDTO noticeDTO){
         if (ObjectUtils.isNotNull(noticeDTO.getStatus()) && noticeDTO.getStatus()==1){
             Notice notice = noticeService.getById(noticeDTO.getId());
@@ -65,7 +65,7 @@
 
     @DeleteMapping("/{ids}")
     @Log(title = "鍒犻櫎", businessType = BusinessType.DELETE)
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delete(@PathVariable("ids") List<Long> ids){
         if (CollectionUtils.isEmpty(ids)) {
             throw new RuntimeException("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
@@ -75,7 +75,7 @@
 
     @GetMapping("/count")
     @Log(title = "鑾峰彇鍏憡鏁伴噺", businessType = BusinessType.OTHER)
-    @ApiOperation("鑾峰彇鍏憡鏁伴噺")
+    @Operation(summary = "鑾峰彇鍏憡鏁伴噺")
     public AjaxResult count(){
         return AjaxResult.success(noticeService.selectCount());
     }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeTypeController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeTypeController.java
index 53ae816..dba3e77 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeTypeController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeTypeController.java
@@ -6,6 +6,7 @@
 import com.ruoyi.collaborativeApproval.pojo.NoticeType;
 import com.ruoyi.collaborativeApproval.service.NoticeTypeService;
 import com.ruoyi.framework.web.domain.AjaxResult;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
@@ -22,9 +23,9 @@
  */
 @RestController
 @RequestMapping("/noticeType")
+@AllArgsConstructor
 public class NoticeTypeController {
 
-    @Autowired
     private NoticeTypeService noticeTypeService;
 
     /**
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementController.java
index cf4c2fe..5e59117 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementController.java
@@ -9,47 +9,45 @@
 import com.ruoyi.collaborativeApproval.service.RulesRegulationsManagementService;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/rulesRegulationsManagement")
 @AllArgsConstructor
-@Api(tags = "鍒跺害绠$悊")
+@Tag(name = "鍒跺害绠$悊")
 public class RulesRegulationsManagementController {
-    @Autowired
     private RulesRegulationsManagementService rulesRegulationsManagementService;
-    @Autowired
     private ReadingStatusMapper readingStatusMapper;
 
     @GetMapping("/getList")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, RulesRegulationsManagement rulesRegulationsManagement){
         return AjaxResult.success(rulesRegulationsManagementService.listPage(page, rulesRegulationsManagement));
     }
 
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody RulesRegulationsManagement rulesRegulationsManagement){
         rulesRegulationsManagementService.save(rulesRegulationsManagement);
         return AjaxResult.success(rulesRegulationsManagement.getId());
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼")
+    @Operation(summary = "淇敼")
     public AjaxResult update(@RequestBody RulesRegulationsManagement rulesRegulationsManagement){
         return AjaxResult.success(rulesRegulationsManagementService.updateById(rulesRegulationsManagement));
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delete(@PathVariable("ids") List<Long> ids){
         if (CollectionUtils.isEmpty(ids)) {
             throw new RuntimeException("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
@@ -58,27 +56,27 @@
     }
     //瑙勫垯鏌ョ湅鏃舵柊澧為槄璇荤姸鎬�
     @PostMapping("/addReadingStatus")
-    @ApiOperation("鏂板闃呰鐘舵��")
+    @Operation(summary = "鏂板闃呰鐘舵��")
     public AjaxResult addReadingStatus(@RequestBody ReadingStatus readingStatus){
         return AjaxResult.success(readingStatusMapper.insert(readingStatus));
     }
     @PostMapping("/updateReadingStatus")
-    @ApiOperation("淇敼闃呰鐘舵��")
+    @Operation(summary = "淇敼闃呰鐘舵��")
     public AjaxResult updateReadingStatus(@RequestBody ReadingStatus readingStatus){
         return AjaxResult.success(readingStatusMapper.updateById(readingStatus));
     }
     @GetMapping("/getReadingStatusList")
-    @ApiOperation("鍒嗛〉鏌ヨ闃呰鐘舵��")
+    @Operation(summary = "鍒嗛〉鏌ヨ闃呰鐘舵��")
     public AjaxResult listPage(Page page, ReadingStatus readingStatus){
         return AjaxResult.success(readingStatusMapper.selectPage(page,new QueryWrapper<ReadingStatus>(readingStatus)));
     }
     @GetMapping("/getReadingStatusByRuleId/{ruleId}")
-    @ApiOperation("鏍规嵁鍒跺害id鏌ヨ闃呰鐘舵��")
+    @Operation(summary = "鏍规嵁鍒跺害id鏌ヨ闃呰鐘舵��")
     public AjaxResult getReadingStatusByRuleId(@PathVariable Long ruleId){
         return AjaxResult.success(readingStatusMapper.selectList(new QueryWrapper<ReadingStatus>().eq("rule_id", ruleId)));
     }
 
-    @ApiOperation(value = "瑙勭珷鍒跺害绠$悊瀵煎嚭")
+    @Operation(summary = "瑙勭珷鍒跺害绠$悊瀵煎嚭")
     @PostMapping("/export")
     public void export(HttpServletResponse response) {
         List<RulesRegulationsManagement> accountExpenses = rulesRegulationsManagementService.list();
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementFileController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementFileController.java
index 8f9ced9..3f770f8 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementFileController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementFileController.java
@@ -9,7 +9,7 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java
index bcfc20d..6a3824d 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java
@@ -9,36 +9,33 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.service.ISysNoticeService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.Arrays;
 import java.util.List;
 
 @AllArgsConstructor
 @RestController
 @RequestMapping("/sealApplicationManagement")
-@Api(tags = "鐢ㄥ嵃鐢宠绠$悊")
+@Tag(name = "鐢ㄥ嵃鐢宠绠$悊")
 public class SealApplicationManagementController {
-    @Autowired
     private SealApplicationManagementService sealApplicationManagementService;
-
-    @Autowired
     private ISysNoticeService sysNoticeService;
 
     @GetMapping("/getList")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, SealApplicationManagement sealApplicationManagement){
         return AjaxResult.success(sealApplicationManagementService.listPage(page,sealApplicationManagement));
     }
 
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody SealApplicationManagement sealApplicationManagement){
         sealApplicationManagementService.save(sealApplicationManagement);
         //娑堟伅閫氱煡
@@ -51,13 +48,13 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼")
+    @Operation(summary = "淇敼")
     public AjaxResult update(@RequestBody SealApplicationManagement sealApplicationManagement){
         return AjaxResult.success(sealApplicationManagementService.updateById(sealApplicationManagement));
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delete(@PathVariable("ids") List<Long> ids){
         if (CollectionUtils.isEmpty(ids)) {
             throw new RuntimeException("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
@@ -65,7 +62,7 @@
         return AjaxResult.success(sealApplicationManagementService.removeBatchByIds(ids));
     }
 
-    @ApiOperation(value = "鐢ㄥ嵃鐢宠绠$悊瀵煎嚭")
+    @Operation(summary = "鐢ㄥ嵃鐢宠绠$悊瀵煎嚭")
     @PostMapping("/export")
     public void export(HttpServletResponse response) {
         List<SealApplicationManagement> accountExpenses = sealApplicationManagementService.list();
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/controller/StaffContactsPersonalController.java b/src/main/java/com/ruoyi/collaborativeApproval/controller/StaffContactsPersonalController.java
index f189872..3673208 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/controller/StaffContactsPersonalController.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/controller/StaffContactsPersonalController.java
@@ -5,35 +5,31 @@
 import com.ruoyi.collaborativeApproval.pojo.StaffContactsPersonal;
 import com.ruoyi.collaborativeApproval.service.StaffContactsPersonalService;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
 
 @RestController
 @RequestMapping("/staffContactsPersonal")
 @AllArgsConstructor
 public class StaffContactsPersonalController {
-    @Autowired
     private StaffContactsPersonalService staffContactsPersonalService;
+
     @GetMapping("/getList")
-    @ApiOperation("鍒嗛〉鏌ヨ")
-    public AjaxResult listPage(Page page, StaffContactsPersonalDTO staffContactsPersonalDTO ){
+    @Operation(summary = "鍒嗛〉鏌ヨ")
+    public AjaxResult listPage(Page page, StaffContactsPersonalDTO staffContactsPersonalDTO) {
         return AjaxResult.success(staffContactsPersonalService.listPage(page, staffContactsPersonalDTO));
     }
 
     @PostMapping("/add")
-    @ApiOperation("鏂板")
-    public AjaxResult add(@RequestBody StaffContactsPersonal staffContactsPersonal){
+    @Operation(summary = "鏂板")
+    public AjaxResult add(@RequestBody StaffContactsPersonal staffContactsPersonal) {
         return AjaxResult.success(staffContactsPersonalService.save(staffContactsPersonal));
     }
 
     @DeleteMapping("/delete/{id}")
-    @ApiOperation("鍒犻櫎")
-    public AjaxResult delete(@PathVariable("id") Long id){
+    @Operation(summary = "鍒犻櫎")
+    public AjaxResult delete(@PathVariable("id") Long id) {
 //        if (CollectionUtils.isEmpty(id)) {
 //            throw new RuntimeException("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
 //        }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/dto/MeetSummaryDto.java b/src/main/java/com/ruoyi/collaborativeApproval/dto/MeetSummaryDto.java
index 1c43eeb..d62c8ad 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/dto/MeetSummaryDto.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/dto/MeetSummaryDto.java
@@ -1,6 +1,5 @@
 package com.ruoyi.collaborativeApproval.dto;
 
-import io.swagger.models.auth.In;
 import lombok.Data;
 
 import java.io.Serializable;
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/DutyPlan.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/DutyPlan.java
index 1a55190..ef8fc01 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/DutyPlan.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/DutyPlan.java
@@ -4,7 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.approve.utils.ListToStringTypeHandler;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.apache.ibatis.type.JdbcType;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -22,13 +22,13 @@
      * 璁″垝鏍囬
      */
     @Excel(name = "璁″垝鏍囬")
-    @ApiModelProperty("璁″垝鏍囬")
+    @Schema(description = "璁″垝鏍囬")
     private String title;
     /**
      * 璁″垝鎻忚堪
      */
     @Excel(name = "璁″垝鎻忚堪")
-    @ApiModelProperty("璁″垝鎻忚堪")
+    @Schema(description = "璁″垝鎻忚堪")
     private String description;
 
 
@@ -36,13 +36,13 @@
      * 璁″垝绾у埆
      */
     @Excel(name = "璁″垝绾у埆")
-    @ApiModelProperty("璁″垝绾у埆")
+    @Schema(description = "璁″垝绾у埆")
     private String level;
     /**
      * 鏃堕棿鍛ㄦ湡
      */
     @Excel(name = "鏃堕棿鍛ㄦ湡")
-    @ApiModelProperty("鏃堕棿鍛ㄦ湡")
+    @Schema(description = "鏃堕棿鍛ㄦ湡")
     private String period;
     /**
      * 寮�濮嬫椂闂�
@@ -63,31 +63,31 @@
      * 璐熻矗浜�
      */
     @Excel(name = "璐熻矗浜�")
-    @ApiModelProperty("璐熻矗浜�")
+    @Schema(description = "璐熻矗浜�")
     private String assignee;
     /**
      * 鐘舵��
      */
     @Excel(name = "鐘舵��")
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     private String status;
     /**
      * 浼樺厛绾�
      */
     @Excel(name = "浼樺厛绾�")
-    @ApiModelProperty("浼樺厛绾�")
+    @Schema(description = "浼樺厛绾�")
     private String priority;
     /**
      * 瀹屾垚搴�
      */
     @Excel(name = "瀹屾垚搴�")
-    @ApiModelProperty("瀹屾垚搴�")
+    @Schema(description = "瀹屾垚搴�")
     private Integer progress;
     /**
      * 鏍囩
      */
     @Excel(name = "鏍囩")
-    @ApiModelProperty("鏍囩")
+    @Schema(description = "鏍囩")
     @TableField(value = "tags",typeHandler = ListToStringTypeHandler.class,jdbcType = JdbcType.VARCHAR)
     private List<String> tags;
     /**
@@ -122,4 +122,7 @@
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetApplication.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetApplication.java
index 5f9ad1d..5c9d9c0 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetApplication.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetApplication.java
@@ -7,7 +7,6 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.models.auth.In;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -137,4 +136,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
-}
\ No newline at end of file
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetDraft.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetDraft.java
index 7df4b0a..e8d83d9 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetDraft.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetDraft.java
@@ -129,4 +129,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingMinutes.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingMinutes.java
index bd80254..b072f87 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingMinutes.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingMinutes.java
@@ -76,4 +76,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingRoom.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingRoom.java
index 9742071..cbfb421 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingRoom.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingRoom.java
@@ -95,4 +95,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/Notice.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/Notice.java
index 5ca6e4b..7d688b4 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/Notice.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/Notice.java
@@ -2,8 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -15,7 +14,7 @@
  */
 @Data
 @TableName("notice")
-@ApiModel
+@Schema
 public class Notice {
     private static final long serialVersionUID = 1L;
 
@@ -26,31 +25,31 @@
     /**
      * 鍏憡鏍囬
      */
-    @ApiModelProperty("鍏憡鏍囬")
+    @Schema(description = "鍏憡鏍囬")
     private String title;
 
     /**
      * 鍏憡绫诲瀷
      */
-    @ApiModelProperty("鍏憡绫诲瀷")
+    @Schema(description = "鍏憡绫诲瀷")
     private String type;
 
     /**
      * 鐘舵�侊紙0鑽夌 1鍙戝竷 2宸蹭笅绾匡級
      */
-    @ApiModelProperty("鐘舵�侊紙0鑽夌 1鍙戝竷 2宸蹭笅绾匡級")
+    @Schema(description = "鐘舵�侊紙0鑽夌 1鍙戝竷 2宸蹭笅绾匡級")
     private Integer status;
 
     /**
      * 鍏憡鍐呭
      */
-    @ApiModelProperty("鍏憡鍐呭")
+    @Schema(description = "鍏憡鍐呭")
     private String content;
 
     /**
      * 浼樺厛绾�(1鏅�� 2閲嶈 3绱ф��)
      */
-    @ApiModelProperty("浼樺厛绾�(1鏅�� 2閲嶈 3绱ф��)")
+    @Schema(description = "浼樺厛绾�(1鏅�� 2閲嶈 3绱ф��)")
     private Integer priority;
 
 
@@ -83,7 +82,10 @@
     /**
      * 澶囨敞
      */
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/NoticeType.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/NoticeType.java
index 840c338..8faf9d9 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/NoticeType.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/NoticeType.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 
 import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -19,7 +18,7 @@
 @Getter
 @Setter
 @TableName("notice_type")
-@ApiModel(value = "NoticeType瀵硅薄", description = "閫氱煡鍏憡鐨勫叕鍛婄被鍨嬬淮鎶�")
+@Schema(name = "NoticeType瀵硅薄", description = "閫氱煡鍏憡鐨勫叕鍛婄被鍨嬬淮鎶�")
 public class NoticeType implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -27,9 +26,16 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("閫氱煡鍏憡鐨勫叕鍛婄被鍨�")
+    @Schema(description = "閫氱煡鍏憡鐨勫叕鍛婄被鍨�")
     private String noticeType;
 
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/ReadingStatus.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/ReadingStatus.java
index 1aa4892..67143c2 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/ReadingStatus.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/ReadingStatus.java
@@ -67,4 +67,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagement.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagement.java
index cc32e10..f1abf11 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagement.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagement.java
@@ -4,7 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.approve.utils.ListToStringTypeHandler;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.apache.ibatis.type.JdbcType;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -20,26 +20,26 @@
     /**
      * 鍒跺害缂栧彿
      */
-    @ApiModelProperty("鍒跺害缂栧彿")
+    @Schema(description = "鍒跺害缂栧彿")
     @Excel(name = "鍒跺害缂栧彿")
     private String regulationNum;
 
     /**
      * 鏍囬
      */
-    @ApiModelProperty("鏍囬")
+    @Schema(description = "鏍囬")
     @Excel(name = "鏍囬")
     private String title;
     /**
      * 鍒跺害鍒嗙被
      */
-    @ApiModelProperty("鍒跺害鍒嗙被")
+    @Schema(description = "鍒跺害鍒嗙被")
     @Excel(name = "鍒跺害鍒嗙被", readConverterExp = "finance=璐㈠姟鍒跺害,hr=浜轰簨鍒跺害,safety=瀹夊叏鍒跺害,tech=鎶�鏈埗搴�")
     private String category;
     /**
      * 鍒跺害鍐呭
      */
-    @ApiModelProperty("鍒跺害鍐呭")
+    @Schema(description = "鍒跺害鍐呭")
     private String content;
     /**
      * 鐢熸晥鏃堕棿
@@ -51,30 +51,30 @@
     /**
      * 閫傜敤鑼冨洿
      */
-    @ApiModelProperty("閫傜敤鑼冨洿")
+    @Schema(description = "閫傜敤鑼冨洿")
     @TableField(value = "scope",typeHandler = ListToStringTypeHandler.class,jdbcType = JdbcType.VARCHAR)
     private List<String> scope;
     /**
      * 鏄惁闇�瑕佺‘璁�
      */
-    @ApiModelProperty("鏄惁闇�瑕佺‘璁�")
+    @Schema(description = "鏄惁闇�瑕佺‘璁�")
     private Boolean requireConfirm;
     /**
      * 鐗堟湰
      */
-    @ApiModelProperty("鐗堟湰")
+    @Schema(description = "鐗堟湰")
     @Excel(name = "鐗堟湰")
     private String version;
     /**
      * 鐘舵��
      */
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     @Excel(name = "鐘舵��", readConverterExp = "repealed=宸插簾姝�,active=鐢熸晥涓�")
     private String status;
     /**
      * 宸茶浜烘暟
      */
-    @ApiModelProperty("宸茶浜烘暟")
+    @Schema(description = "宸茶浜烘暟")
     @Excel(name = "宸茶浜烘暟")
     private Integer readCount;
     /**
@@ -108,4 +108,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagementFile.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagementFile.java
index fa43d0e..b2c287d 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagementFile.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagementFile.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,7 +22,7 @@
 @Getter
 @Setter
 @TableName("rules_regulations_management_file")
-@ApiModel(value = "RulesRegulationsManagementFile瀵硅薄", description = "瑙勭珷鍒跺害绠$悊--闄勪欢")
+@Schema(name = "RulesRegulationsManagementFile瀵硅薄", description = "瑙勭珷鍒跺害绠$悊--闄勪欢")
 public class RulesRegulationsManagementFile implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -31,35 +30,38 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty("鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty("鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private Integer fileSize;
 
-    @ApiModelProperty("瑙勭珷鍒跺害ID")
+    @Schema(description = "瑙勭珷鍒跺害ID")
     private Integer rulesRegulationsManagementId;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
 
-    @ApiModelProperty("绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/SealApplicationManagement.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/SealApplicationManagement.java
index 4055f21..d655683 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/SealApplicationManagement.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/SealApplicationManagement.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,37 +18,37 @@
     /**
      * 鐢宠缂栧彿
      */
-    @ApiModelProperty("鐢宠缂栧彿")
+    @Schema(description = "鐢宠缂栧彿")
     @Excel(name = "鐢宠缂栧彿")
     private String applicationNum;
 
     /**
      * 鍏憡鏍囬
      */
-    @ApiModelProperty("鍏憡鏍囬")
+    @Schema(description = "鍏憡鏍囬")
     @Excel(name = "鐢宠鏍囬")
     private String title;
     /**
      * 鐢ㄥ嵃绫诲瀷
      */
-    @ApiModelProperty("鐢ㄥ嵃绫诲瀷")
+    @Schema(description = "鐢ㄥ嵃绫诲瀷")
     @Excel(name = "鐢ㄥ嵃绫诲瀷", readConverterExp = "official=鍏珷,contract=鍚堝悓涓撶敤绔�,finance=璐㈠姟涓撶敤绔�,legal=娉曚汉绔�")
     private String sealType;
     /**
      * 鐢宠鐢ㄥ嵃鍘熷洜
      */
-    @ApiModelProperty("鐢宠鐢ㄥ嵃鍘熷洜")
+    @Schema(description = "鐢宠鐢ㄥ嵃鍘熷洜")
     private String reason;
 
     /**
      * 绱ф�ョ▼搴�
      */
-    @ApiModelProperty("绱ф�ョ▼搴�")
+    @Schema(description = "绱ф�ョ▼搴�")
     private String urgency;
     /**
      * 鐘舵��
      */
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     @Excel(name = "鐘舵��", readConverterExp = "pending=寰呭鎵�,approved=宸查�氳繃,rejected=宸叉嫆缁�")
     private String status;
 
@@ -74,4 +74,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/pojo/StaffContactsPersonal.java b/src/main/java/com/ruoyi/collaborativeApproval/pojo/StaffContactsPersonal.java
index 967769e..ae11cff 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/pojo/StaffContactsPersonal.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/pojo/StaffContactsPersonal.java
@@ -1,7 +1,7 @@
 package com.ruoyi.collaborativeApproval.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -15,13 +15,13 @@
 //    /**
 //     * 鐢ㄦ埛ID锛堟墍灞炶�咃級
 //     */
-//    @ApiModelProperty("鐢ㄦ埛ID锛堟墍灞炶�咃級")
+//    @Schema(description = "鐢ㄦ埛ID锛堟墍灞炶�咃級")
 //    private Integer userId;
 
     /**
      * 鍛樺伐ID
      */
-    @ApiModelProperty("鍛樺伐ID")
+    @Schema(description = "鍛樺伐ID")
     private Integer contactId;
     /**
      * 鍒涘缓鑰�
@@ -40,4 +40,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/DutyPlanService.java b/src/main/java/com/ruoyi/collaborativeApproval/service/DutyPlanService.java
index 67bff22..b3cbcec 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/DutyPlanService.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/DutyPlanService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.collaborativeApproval.dto.DutyPlanDTO;
 import com.ruoyi.collaborativeApproval.pojo.DutyPlan;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/DutyPlanServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/DutyPlanServiceImpl.java
index b70f67a..8940162 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/DutyPlanServiceImpl.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/DutyPlanServiceImpl.java
@@ -8,17 +8,17 @@
 import com.ruoyi.collaborativeApproval.pojo.DutyPlan;
 import com.ruoyi.collaborativeApproval.service.DutyPlanService;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 
 @Service
+@RequiredArgsConstructor
 public class DutyPlanServiceImpl extends ServiceImpl<DutyPlanMapper, DutyPlan> implements DutyPlanService {
-    @Autowired
-    private DutyPlanMapper dutyPlanMapper;
+    private final DutyPlanMapper dutyPlanMapper;
 
     @Override
     public IPage listPage(Page page, DutyPlanDTO dutyPlanDTO) {
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java
index e5c05ed..636130a 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java
@@ -3,7 +3,6 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementFileServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementFileServiceImpl.java
index ff59f8c..44ba04a 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementFileServiceImpl.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementFileServiceImpl.java
@@ -1,16 +1,14 @@
 package com.ruoyi.collaborativeApproval.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.collaborativeApproval.pojo.RulesRegulationsManagementFile;
-import com.ruoyi.collaborativeApproval.mapper.RulesRegulationsManagementFileMapper;
-import com.ruoyi.collaborativeApproval.service.RulesRegulationsManagementFileService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.collaborativeApproval.mapper.RulesRegulationsManagementFileMapper;
+import com.ruoyi.collaborativeApproval.pojo.RulesRegulationsManagementFile;
+import com.ruoyi.collaborativeApproval.service.RulesRegulationsManagementFileService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.management.Query;
 
 /**
  * <p>
@@ -21,10 +19,10 @@
  * @since 2026-01-13 01:06:41
  */
 @Service
+@RequiredArgsConstructor
 public class RulesRegulationsManagementFileServiceImpl extends ServiceImpl<RulesRegulationsManagementFileMapper, RulesRegulationsManagementFile> implements RulesRegulationsManagementFileService {
 
-    @Autowired
-    private RulesRegulationsManagementFileMapper rulesRegulationsManagementFileMapper;
+    private final RulesRegulationsManagementFileMapper rulesRegulationsManagementFileMapper;
 
     @Override
     public IPage<RulesRegulationsManagementFile> listPage(Page page, RulesRegulationsManagementFile rulesRegulationsManagementFile) {
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementServiceImpl.java
index a4f912e..c40f817 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementServiceImpl.java
@@ -7,13 +7,14 @@
 import com.ruoyi.collaborativeApproval.mapper.RulesRegulationsManagementMapper;
 import com.ruoyi.collaborativeApproval.pojo.RulesRegulationsManagement;
 import com.ruoyi.collaborativeApproval.service.RulesRegulationsManagementService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class RulesRegulationsManagementServiceImpl extends ServiceImpl<RulesRegulationsManagementMapper, RulesRegulationsManagement> implements RulesRegulationsManagementService {
-    @Autowired
-    private RulesRegulationsManagementMapper rulesRegulationsManagementMapper;
+    private final RulesRegulationsManagementMapper rulesRegulationsManagementMapper;
+
     @Override
     public IPage<RulesRegulationsManagementDTO> listPage(Page page, RulesRegulationsManagement rulesRegulationsManagement) {
         return rulesRegulationsManagementMapper.listPage(page, rulesRegulationsManagement);
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/SealApplicationManagementServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/SealApplicationManagementServiceImpl.java
index 6cb8a2b..d63f2d2 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/SealApplicationManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/SealApplicationManagementServiceImpl.java
@@ -7,13 +7,13 @@
 import com.ruoyi.collaborativeApproval.mapper.SealApplicationManagementMapper;
 import com.ruoyi.collaborativeApproval.pojo.SealApplicationManagement;
 import com.ruoyi.collaborativeApproval.service.SealApplicationManagementService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class SealApplicationManagementServiceImpl extends ServiceImpl<SealApplicationManagementMapper, SealApplicationManagement> implements SealApplicationManagementService {
-    @Autowired
-    private SealApplicationManagementMapper sealApplicationManagementMapper;
+    private final SealApplicationManagementMapper sealApplicationManagementMapper;
 
     @Override
     public IPage<SealApplicationManagementDTO> listPage(Page page, SealApplicationManagement sealApplicationManagement) {
diff --git a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/StaffContactsPersonalServiceImpl.java b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/StaffContactsPersonalServiceImpl.java
index 1a77996..98ec12f 100644
--- a/src/main/java/com/ruoyi/collaborativeApproval/service/impl/StaffContactsPersonalServiceImpl.java
+++ b/src/main/java/com/ruoyi/collaborativeApproval/service/impl/StaffContactsPersonalServiceImpl.java
@@ -1,6 +1,5 @@
 package com.ruoyi.collaborativeApproval.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -8,13 +7,14 @@
 import com.ruoyi.collaborativeApproval.mapper.StaffContactsPersonalMapper;
 import com.ruoyi.collaborativeApproval.pojo.StaffContactsPersonal;
 import com.ruoyi.collaborativeApproval.service.StaffContactsPersonalService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class StaffContactsPersonalServiceImpl extends ServiceImpl<StaffContactsPersonalMapper, StaffContactsPersonal> implements StaffContactsPersonalService {
-    @Autowired
-    private StaffContactsPersonalMapper staffContactsPersonalMapper;
+    private final StaffContactsPersonalMapper staffContactsPersonalMapper;
+
     @Override
     public IPage listPage(Page page, StaffContactsPersonalDTO staffContactsPersonalDTO) {
         return staffContactsPersonalMapper.listPage(page, staffContactsPersonalDTO);
diff --git a/src/main/java/com/ruoyi/common/aop/DataScopeAop.java b/src/main/java/com/ruoyi/common/aop/DataScopeAop.java
new file mode 100644
index 0000000..1c73e9b
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/aop/DataScopeAop.java
@@ -0,0 +1,158 @@
+package com.ruoyi.common.aop;
+
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.Map;
+
+@Aspect
+@Component
+public class DataScopeAop {
+
+    private static final String DATA_SCOPE_ALL = "1";
+    private static final String DATA_SCOPE_CUSTOM = "2";
+    private static final String DATA_SCOPE_DEPT = "3";
+    private static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
+    private static final String DATA_SCOPE_SELF = "5";
+
+    @Before("@within(restController)")
+    public void fillDataScopeCondition(JoinPoint joinPoint, RestController restController) {
+        System.out.println("[DataScopeAop] enter: " + joinPoint.getSignature().toShortString());
+        fillDataScopeCondition(joinPoint);
+    }
+
+    public void fillDataScopeCondition(JoinPoint joinPoint) {
+        LoginUser loginUser;
+        try {
+            loginUser = SecurityUtils.getLoginUser();
+        } catch (Exception ignored) {
+            System.out.println("[DataScopeAop] skip: loginUser unavailable");
+            return;
+        }
+        if (loginUser == null || loginUser.getUser() == null || loginUser.getUser().isAdmin()) {
+            System.out.println("[DataScopeAop] skip: loginUser null or admin");
+            return;
+        }
+        String dataScope = loginUser.getDataScope();
+        if (dataScope == null || DATA_SCOPE_ALL.equals(dataScope)) {
+            System.out.println("[DataScopeAop] skip: dataScope=" + dataScope);
+            return;
+        }
+        for (Object arg : joinPoint.getArgs()) {
+            bindScope(arg, loginUser, dataScope);
+        }
+    }
+
+
+
+    private void bindScope(Object arg, LoginUser loginUser, String dataScope) {
+        if (arg == null || isIgnoredType(arg.getClass())) {
+            return;
+        }
+        if (arg instanceof Collection<?>) {
+            for (Object item : (Collection<?>) arg) {
+                bindScope(item, loginUser, dataScope);
+            }
+            return;
+        }
+        if (arg instanceof Map<?, ?>) {
+            for (Object value : ((Map<?, ?>) arg).values()) {
+                bindScope(value, loginUser, dataScope);
+            }
+            return;
+        }
+        if (arg.getClass().isArray()) {
+            int length = Array.getLength(arg);
+            for (int i = 0; i < length; i++) {
+                bindScope(Array.get(arg, i), loginUser, dataScope);
+            }
+            return;
+        }
+
+        if (DATA_SCOPE_SELF.equals(dataScope)) {
+            setFieldValue(arg, "createUser", Integer.class, loginUser.getUserId() == null ? null : loginUser.getUserId().intValue());
+            return;
+        }
+
+        if (DATA_SCOPE_DEPT.equals(dataScope)) {
+            setFieldValue(arg, "deptId", Long.class, resolveDeptId(loginUser));
+            return;
+        }
+
+        if (DATA_SCOPE_CUSTOM.equals(dataScope) || DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
+            Long[] deptIds = loginUser.getDeptIds();
+            setFieldValue(arg, "deptIds", Long[].class, deptIds);
+            if (deptIds != null && deptIds.length == 1) {
+                setFieldValue(arg, "deptId", Long.class, deptIds[0]);
+            }
+        }
+    }
+
+    private Long resolveDeptId(LoginUser loginUser) {
+        if (loginUser.getCurrentDeptId() != null) {
+            return loginUser.getCurrentDeptId();
+        }
+        Long[] deptIds = loginUser.getDeptIds();
+        return deptIds != null && deptIds.length > 0 ? deptIds[0] : null;
+    }
+
+    private void setFieldValue(Object target, String fieldName, Class<?> fieldType, Object value) {
+        if (value == null) {
+            return;
+        }
+        Field field = findField(target.getClass(), fieldName);
+        if (field == null || !fieldType.isAssignableFrom(field.getType())) {
+            return;
+        }
+        try {
+            field.setAccessible(true);
+            field.set(target, value);
+            System.out.println("[DataScopeAop] inject: class=" + target.getClass().getSimpleName() + ", field=" + fieldName + ", value=" + value);
+        } catch (IllegalAccessException ignored) {
+        }
+    }
+
+    private Field findField(Class<?> type, String fieldName) {
+        Class<?> current = type;
+        while (current != null && current != Object.class) {
+            try {
+                return current.getDeclaredField(fieldName);
+            } catch (NoSuchFieldException ignored) {
+                current = current.getSuperclass();
+            }
+        }
+        return null;
+    }
+
+    private boolean isIgnoredType(Class<?> type) {
+        Package targetPackage = type.getPackage();
+        String packageName = targetPackage == null ? "" : targetPackage.getName();
+        return type.isPrimitive()
+                || Number.class.isAssignableFrom(type)
+                || CharSequence.class.isAssignableFrom(type)
+                || Boolean.class == type
+                || Character.class == type
+                || type.isEnum()
+                || Page.class.isAssignableFrom(type)
+                || MultipartFile.class.isAssignableFrom(type)
+                || ServletRequest.class.isAssignableFrom(type)
+                || ServletResponse.class.isAssignableFrom(type)
+                || packageName.startsWith("java.")
+                || packageName.startsWith("jakarta.")
+                || packageName.startsWith("jakarta.")
+                || packageName.startsWith("org.springframework.")
+                || packageName.startsWith("com.baomidou.");
+    }
+}
diff --git a/src/main/java/com/ruoyi/common/config/FileProperties.java b/src/main/java/com/ruoyi/common/config/FileProperties.java
new file mode 100644
index 0000000..f7ef613
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/config/FileProperties.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+import org.springframework.util.unit.DataSize;
+
+import java.math.BigDecimal;
+
+@Configuration
+@Component
+@ConfigurationProperties(prefix = "file", ignoreUnknownFields = true)
+@Data
+public class FileProperties {
+    private String path = "D:/upload";
+    private String urlPrefix = "/file";
+    private String domain = "http://localhost:8080";
+    private BigDecimal expired = new BigDecimal("120");
+    private Integer useLimit = 10;
+    // 浠ょ墝绉橀挜
+    @Value("${token.secret}")
+    private String jwtSecret;
+    private Boolean compress;
+    private DataSize needCompressSize;
+    private float compressQuality;
+}
diff --git a/src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java b/src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java
index 66f674a..9f6a258 100644
--- a/src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java
+++ b/src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java
@@ -34,6 +34,11 @@
         IGNORE_TABLES.add("sys_user_dept");
         IGNORE_TABLES.add("sys_job_log");
         IGNORE_TABLES.add("gen_table");
-        IGNORE_TABLES.add("gen_table_column");
+        IGNORE_TABLES.add("sys_notice");
+        IGNORE_TABLES.add("sys_user_client");
+        IGNORE_TABLES.add("product_model");
+        IGNORE_TABLES.add("ai_chat_session");
+        IGNORE_TABLES.add("product");
+
     }
 }
diff --git a/src/main/java/com/ruoyi/common/config/MinioConfig.java b/src/main/java/com/ruoyi/common/config/MinioConfig.java
deleted file mode 100644
index 28f489f..0000000
--- a/src/main/java/com/ruoyi/common/config/MinioConfig.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.ruoyi.common.config;
-
-import io.minio.MinioClient;
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.stereotype.Component;
-
-@Configuration
-@Component
-@ConfigurationProperties(prefix = "minio")
-@Data
-public class MinioConfig {
-    private String endpoint;
-    private int port;
-    private String accessKey;
-    private String secretKey;
-    private Boolean secure;
-
-    @Bean
-    public MinioClient getMinioClient() {
-        return MinioClient.builder().endpoint(endpoint, port, secure)
-                .credentials(accessKey, secretKey)
-                .build();
-    }
-}
diff --git a/src/main/java/com/ruoyi/common/config/MybatisHandler.java b/src/main/java/com/ruoyi/common/config/MybatisHandler.java
index 891410f..8125a35 100644
--- a/src/main/java/com/ruoyi/common/config/MybatisHandler.java
+++ b/src/main/java/com/ruoyi/common/config/MybatisHandler.java
@@ -15,10 +15,12 @@
         Integer userId = null;
         Long tenantId = null;
         String userName = null;
+        Long deptId = null;
         try {
             userId = SecurityUtils.getUserId().intValue();
             tenantId = SecurityUtils.getLoginUser().getTenantId();
             userName = SecurityUtils.getUsername();
+            deptId = SecurityUtils.getLoginUser().getCurrentDeptId();
         } catch (Exception ignored) {
         }
         this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
@@ -29,7 +31,7 @@
         this.strictInsertFill(metaObject, "updateUser", Long.class, userId == null ? 0 : userId.longValue());
         this.strictInsertFill(metaObject, "createUserName", String.class, userName);
         this.strictInsertFill(metaObject, "updateUserName", String.class, userName);
-
+        this.strictInsertFill(metaObject, "deptId", Long.class, deptId);
         this.strictInsertFill(metaObject, "tenantId", Long.class, tenantId);
     }
 
diff --git a/src/main/java/com/ruoyi/common/constant/Constants.java b/src/main/java/com/ruoyi/common/constant/Constants.java
index d12c995..1c87b19 100644
--- a/src/main/java/com/ruoyi/common/constant/Constants.java
+++ b/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -168,6 +168,6 @@
     /**
      * 瀹氭椂浠诲姟杩濊鐨勫瓧绗�
      */
-    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+    public static final String[] JOB_ERROR_STR = { "java.net.URL", "jakarta.naming.InitialContext", "org.yaml.snakeyaml",
             "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.framework.config", "com.ruoyi.project.tool" };
 }
diff --git a/src/main/java/com/ruoyi/common/enums/FileNameType.java b/src/main/java/com/ruoyi/common/enums/FileNameType.java
index 7afc045..2deb5d6 100644
--- a/src/main/java/com/ruoyi/common/enums/FileNameType.java
+++ b/src/main/java/com/ruoyi/common/enums/FileNameType.java
@@ -1,6 +1,8 @@
 package com.ruoyi.common.enums;
 
+import lombok.Getter;
 
+@Getter
 public enum FileNameType {
 
     SALE(1),      // 閿�鍞�
@@ -14,17 +16,13 @@
     SHIP(9),//鍙戣揣鍙拌处
     INSPECTION_PRODUCTION_BEFORE(10),
     INSPECTION_PRODUCTION_AFTER(11),
-    INSPECTION(12);//宸℃ 鐢熶骇鍓�
+    INSPECTION(12),//宸℃ 鐢熶骇鍓�
+    APP(13);
 
     private final int value;
 
     FileNameType(int value) {
         this.value = value;
-    }
-
-    public int getValue() {
-        return value;
-
     }
 
     // 鏍规嵁鏁存暟鍊艰幏鍙栧搴旂殑鏋氫妇鍊�
diff --git a/src/main/java/com/ruoyi/common/enums/SparePartsRequisitionRecordSourceTypeEnum.java b/src/main/java/com/ruoyi/common/enums/SparePartsRequisitionRecordSourceTypeEnum.java
new file mode 100644
index 0000000..b9acc40
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/enums/SparePartsRequisitionRecordSourceTypeEnum.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum SparePartsRequisitionRecordSourceTypeEnum implements BaseEnum<Integer> {
+    SparePartsRequisitionRecordSourceTypeRepair(0, "缁翠慨"),
+    SparePartsRequisitionRecordSourceTypeMaintenance(1, "淇濆吇");
+
+    private final Integer code;
+    private final String value;
+
+    SparePartsRequisitionRecordSourceTypeEnum(Integer code, String value) {
+        this.code = code;
+        this.value = value;
+    }
+
+    public static SparePartsRequisitionRecordSourceTypeEnum getByCode(Integer code) {
+        for (SparePartsRequisitionRecordSourceTypeEnum type : SparePartsRequisitionRecordSourceTypeEnum.values()) {
+            if (type.getCode().equals(code)) {
+                return type;
+            }
+        }
+        return null;
+    }
+}
+
diff --git a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
index df0d011..367710b 100644
--- a/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
@@ -8,11 +8,25 @@
 
 
     CUSTOMIZATION_STOCK_IN("0", "鍚堟牸鑷畾涔夊叆搴�"),
+    CUSTOMIZATION_STOCK_OUT("1", "鍚堟牸鑷畾涔夊嚭搴�"),
     PRODUCTION_REPORT_STOCK_IN("2", "鐢熶骇鎶ュ伐-鍏ュ簱"),
-    PURCHASE_STOCK_IN("7", "閲囪喘-鍏ュ簱"),
+    PRODUCTION_REPORT_STOCK_OUT("3", "鐢熶骇鎶ュ伐-鍑哄簱"),
+    DEFECTIVE_SCRAP("4", "涓嶅悎鏍煎鐞�-鎶ュ簾"),
+    PRODUCTION_SCRAP("5", "鐢熶骇鎶ュ伐-鎶ュ簾"),
     QUALITYINSPECT_STOCK_IN("6", "璐ㄦ-鍚堟牸鍏ュ簱"),
+    PURCHASE_STOCK_IN("7", "閲囪喘-鍏ュ簱"),
+    SALE_STOCK_OUT("8", "閿�鍞�-鍑哄簱"),
+    CUSTOMIZATION_UNSTOCK_IN("9", "涓嶅悎鏍艰嚜瀹氫箟鍏ュ簱"),
+    CUSTOMIZATION_UNSTOCK_OUT("10", "涓嶅悎鏍艰嚜瀹氫箟鍑哄簱"),
     DEFECTIVE_PASS("11", "涓嶅悎鏍�-璁╂鏀捐"),
-    RETURN_HE_IN("14", "閿�鍞��璐�-鍚堟牸鍏ュ簱");
+    QUALITYINSPECT_UNSTOCK_IN("12", "璐ㄦ-涓嶅悎鏍煎叆搴�"),
+    SALE_SHIP_STOCK_OUT("13", "閿�鍞�-鍙戣揣鍑哄簱"),
+    RETURN_HE_IN("14", "閿�鍞��璐�-鍚堟牸鍏ュ簱"),
+    RETURN_UNSTOCK_IN("15", "閿�鍞��璐�-涓嶅悎鏍煎叆搴�"),
+    PICK_RETURN_IN("20", "閿�鍞��璐�-鍚堟牸鍏ュ簱"),
+    PURCHASE_RETURN_STOCK_OUT("21", "閲囪喘閫�璐�");
+
+
 
 
     private final String code;
diff --git a/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java b/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java
index 37ee471..5e8fe53 100644
--- a/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java
+++ b/src/main/java/com/ruoyi/common/enums/StockOutQualifiedRecordTypeEnum.java
@@ -8,6 +8,7 @@
     CUSTOMIZATION_STOCK_OUT("1", "鍚堟牸鑷畾涔夊嚭搴�"),
     PRODUCTION_REPORT_STOCK_OUT("3", "鐢熶骇鎶ュ伐-鍑哄簱"),
     SALE_STOCK_OUT("8", "閿�鍞�-鍑哄簱"),
+    PURCHASE_RETURN_STOCK_OUT("9", "閲囪喘閫�璐�"),
     SALE_SHIP_STOCK_OUT("13", "閿�鍞�-鍙戣揣鍑哄簱");
 
     private final String code;
diff --git a/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
index 3946d48..722e52e 100644
--- a/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
+++ b/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
@@ -1,13 +1,13 @@
 package com.ruoyi.common.filter;
 
 import java.io.IOException;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
 import org.springframework.http.MediaType;
 import com.ruoyi.common.utils.StringUtils;
 
diff --git a/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
index ca822ed..53416da 100644
--- a/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
+++ b/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
@@ -4,11 +4,11 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import javax.servlet.ReadListener;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
 import com.ruoyi.common.utils.http.HttpHelper;
 import com.ruoyi.common.constant.Constants;
 
diff --git a/src/main/java/com/ruoyi/common/filter/XssFilter.java b/src/main/java/com/ruoyi/common/filter/XssFilter.java
index b4eaabc..db6e9b3 100644
--- a/src/main/java/com/ruoyi/common/filter/XssFilter.java
+++ b/src/main/java/com/ruoyi/common/filter/XssFilter.java
@@ -3,14 +3,14 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.enums.HttpMethod;
 
diff --git a/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
index e0cc40a..9f89bdd 100644
--- a/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
+++ b/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
@@ -2,10 +2,10 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import javax.servlet.ReadListener;
-import javax.servlet.ServletInputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
 import org.apache.commons.io.IOUtils;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
diff --git a/src/main/java/com/ruoyi/common/interceptor/DataScopeSqlInterceptor.java b/src/main/java/com/ruoyi/common/interceptor/DataScopeSqlInterceptor.java
new file mode 100644
index 0000000..0129c5a
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/interceptor/DataScopeSqlInterceptor.java
@@ -0,0 +1,257 @@
+package com.ruoyi.common.interceptor;
+
+import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
+import com.ruoyi.common.config.IgnoreTableConfig;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.stereotype.Component;
+
+import java.sql.SQLException;
+import java.util.Locale;
+import java.util.Set;
+
+@Component
+public class DataScopeSqlInterceptor implements InnerInterceptor {
+
+    private static final String DATA_SCOPE_ALL = "1";
+    private static final String DATA_SCOPE_CUSTOM = "2";
+    private static final String DATA_SCOPE_DEPT = "3";
+    private static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
+    private static final String DATA_SCOPE_SELF = "5";
+    private static final String DATA_SCOPE_MARKER = "/*data_scope*/";
+
+    @Override
+    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
+                            ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
+        LoginUser loginUser;
+        try {
+            loginUser = SecurityUtils.getLoginUser();
+        } catch (Exception ignored) {
+            return;
+        }
+        if (shouldSkip(loginUser, boundSql.getSql())) {
+            return;
+        }
+        // 鑾峰彇涓昏〃
+        TableSegment tableSegment = resolveMainTable(boundSql.getSql());
+        // ====================== 銆愯〃鐧藉悕鍗曘�戠洿鎺ユ斁琛� ======================
+        if (tableSegment == null || ignoreTable(tableSegment.tableName)) {
+            return;
+        }
+        String condition = buildCondition(tableSegment.qualifier, loginUser);
+        if (condition == null) {
+            return;
+        }
+        String newSql = appendCondition(boundSql.getSql(), condition);
+        if (newSql.equals(boundSql.getSql())) {
+            return;
+        }
+        MetaObject metaObject = SystemMetaObject.forObject(boundSql);
+        metaObject.setValue("sql", newSql);
+        System.out.println("[DataScopeSqlInterceptor] rewrite: " + ms.getId());
+        System.out.println("[DataScopeSqlInterceptor] sql: " + newSql);
+    }
+
+    private boolean shouldSkip(LoginUser loginUser, String sql) {
+        if (loginUser == null || loginUser.getUser() == null || loginUser.getUser().isAdmin()) {
+            return true;
+        }
+        if (sql == null || sql.trim().isEmpty()) {
+            return true;
+        }
+        String normalizedSql = sql.toLowerCase(Locale.ROOT);
+        if (!normalizedSql.startsWith("select")) {
+            return true;
+        }
+        if (normalizedSql.contains(DATA_SCOPE_MARKER)) {
+            return true;
+        }
+        return DATA_SCOPE_ALL.equals(loginUser.getDataScope());
+    }
+
+    private boolean ignoreTable(String tableName) {
+        Set<String> ignoreTables = IgnoreTableConfig.IGNORE_TABLES;
+        return ignoreTables.contains(tableName);
+    }
+
+    private String buildCondition(String qualifier, LoginUser loginUser) {
+        String prefix = qualifier + ".";
+        String dataScope = loginUser.getDataScope();
+        if (DATA_SCOPE_SELF.equals(dataScope)) {
+            return prefix + "create_user = " + loginUser.getUserId();
+        }
+        if (DATA_SCOPE_DEPT.equals(dataScope)) {
+            Long deptId = resolveDeptId(loginUser);
+            return deptId == null ? null : prefix + "dept_id = " + deptId;
+        }
+        if (DATA_SCOPE_CUSTOM.equals(dataScope) || DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
+            Long[] deptIds = loginUser.getDeptIds();
+            if (deptIds == null || deptIds.length == 0) {
+                return null;
+            }
+            StringBuilder builder = new StringBuilder(prefix).append("dept_id in (");
+            for (int i = 0; i < deptIds.length; i++) {
+                if (i > 0) {
+                    builder.append(", ");
+                }
+                builder.append(deptIds[i]);
+            }
+            return builder.append(')').toString();
+        }
+        return null;
+    }
+
+    private Long resolveDeptId(LoginUser loginUser) {
+        if (loginUser.getCurrentDeptId() != null) {
+            return loginUser.getCurrentDeptId();
+        }
+        Long[] deptIds = loginUser.getDeptIds();
+        return deptIds != null && deptIds.length > 0 ? deptIds[0] : null;
+    }
+
+    private String appendCondition(String sql, String condition) {
+        int insertPos = findInsertPosition(sql);
+        String prefixSql = sql.substring(0, insertPos);
+        String suffixSql = sql.substring(insertPos);
+        if (hasTopLevelKeyword(prefixSql, "where")) {
+            return prefixSql + " AND " + DATA_SCOPE_MARKER + " " + condition + " " + suffixSql;
+        }
+        return prefixSql + " WHERE " + DATA_SCOPE_MARKER + " " + condition + " " + suffixSql;
+    }
+
+    private int findInsertPosition(String sql) {
+        int orderBy = findTopLevelKeyword(sql, "order by");
+        int groupBy = findTopLevelKeyword(sql, "group by");
+        int having = findTopLevelKeyword(sql, "having");
+        int limit = findTopLevelKeyword(sql, "limit");
+        int union = findTopLevelKeyword(sql, "union");
+        int insertPos = sql.length();
+        insertPos = minPositive(insertPos, orderBy);
+        insertPos = minPositive(insertPos, groupBy);
+        insertPos = minPositive(insertPos, having);
+        insertPos = minPositive(insertPos, limit);
+        insertPos = minPositive(insertPos, union);
+        return insertPos;
+    }
+
+    private int minPositive(int current, int candidate) {
+        return candidate >= 0 && candidate < current ? candidate : current;
+    }
+
+    private boolean hasTopLevelKeyword(String sql, String keyword) {
+        return findTopLevelKeyword(sql, keyword) >= 0;
+    }
+
+    private int findTopLevelKeyword(String sql, String keyword) {
+        String normalizedSql = sql.toLowerCase(Locale.ROOT);
+        String normalizedKeyword = keyword.toLowerCase(Locale.ROOT);
+        int depth = 0;
+        for (int i = 0; i <= normalizedSql.length() - normalizedKeyword.length(); i++) {
+            char current = normalizedSql.charAt(i);
+            if (current == '(') {
+                depth++;
+                continue;
+            }
+            if (current == ')') {
+                depth = Math.max(0, depth - 1);
+                continue;
+            }
+            if (depth > 0) {
+                continue;
+            }
+            if (matchesKeyword(normalizedSql, i, normalizedKeyword)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private boolean matchesKeyword(String sql, int index, String keyword) {
+        if (!sql.regionMatches(index, keyword, 0, keyword.length())) {
+            return false;
+        }
+        boolean startOk = index == 0 || !Character.isLetterOrDigit(sql.charAt(index - 1));
+        int endIndex = index + keyword.length();
+        boolean endOk = endIndex >= sql.length() || !Character.isLetterOrDigit(sql.charAt(endIndex));
+        return startOk && endOk;
+    }
+
+    private TableSegment resolveMainTable(String sql) {
+        int fromIndex = findTopLevelKeyword(sql, "from");
+        if (fromIndex < 0) {
+            return null;
+        }
+        String fromPart = sql.substring(fromIndex + 4).trim();
+        if (fromPart.isEmpty() || fromPart.charAt(0) == '(') {
+            return null;
+        }
+        String[] tokens = fromPart.split("\\s+");
+        if (tokens.length == 0) {
+            return null;
+        }
+        String rawTableName = trimToken(tokens[0]);
+        if (rawTableName.isEmpty()) {
+            return null;
+        }
+        String alias = null;
+        if (tokens.length > 1) {
+            String second = trimToken(tokens[1]);
+            if ("as".equalsIgnoreCase(second) && tokens.length > 2) {
+                alias = trimToken(tokens[2]);
+            } else if (!isClauseKeyword(second)) {
+                alias = second;
+            }
+        }
+        String tableName = normalizeTableName(rawTableName);
+        String qualifier = alias != null && !alias.isEmpty() ? alias : rawTableName;
+        return new TableSegment(tableName, qualifier.replace("`", ""));
+    }
+
+    private String trimToken(String token) {
+        if (token == null) {
+            return "";
+        }
+        return token.replace(",", "").trim();
+    }
+
+    private String normalizeTableName(String tableName) {
+        String normalized = tableName.replace("`", "");
+        int dotIndex = normalized.lastIndexOf('.');
+        if (dotIndex >= 0) {
+            normalized = normalized.substring(dotIndex + 1);
+        }
+        return normalized;
+    }
+
+    private boolean isClauseKeyword(String token) {
+        String normalized = token.toLowerCase(Locale.ROOT);
+        return "left".equals(normalized)
+                || "right".equals(normalized)
+                || "inner".equals(normalized)
+                || "outer".equals(normalized)
+                || "join".equals(normalized)
+                || "where".equals(normalized)
+                || "order".equals(normalized)
+                || "group".equals(normalized)
+                || "limit".equals(normalized)
+                || "union".equals(normalized)
+                || "having".equals(normalized);
+    }
+
+    private static class TableSegment {
+        private final String tableName;
+        private final String qualifier;
+
+        private TableSegment(String tableName, String qualifier) {
+            this.tableName = tableName;
+            this.qualifier = qualifier;
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/common/utils/MinioUtils.java b/src/main/java/com/ruoyi/common/utils/MinioUtils.java
deleted file mode 100644
index d192f93..0000000
--- a/src/main/java/com/ruoyi/common/utils/MinioUtils.java
+++ /dev/null
@@ -1,433 +0,0 @@
-package com.ruoyi.common.utils;
-
-import com.baomidou.mybatisplus.core.toolkit.IdWorker;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.ruoyi.common.exception.UtilException;
-import com.ruoyi.common.exception.file.InvalidExtensionException;
-import com.ruoyi.common.utils.file.FileUploadUtils;
-import com.ruoyi.common.utils.file.MimeTypeUtils;
-import com.ruoyi.framework.web.domain.MinioResult;
-import io.minio.*;
-import io.minio.http.Method;
-import io.minio.messages.DeleteError;
-import io.minio.messages.DeleteObject;
-import lombok.Getter;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.springframework.util.FastByteArrayOutputStream;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletResponse;
-import java.io.InputStream;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-@Component
-public class MinioUtils {
-
-    @Autowired
-    private MinioClient minioClient;
-
-    @Value("${minio.preview-expiry}")
-    private Integer previewExpiry;
-
-    /**
-     * -- GETTER --
-     *  鑾峰彇榛樿瀛樺偍妗跺悕绉�
-     *
-     * @return
-     */
-    @Getter
-    @Value("${minio.default-bucket}")
-    private String defaultBucket;
-
-    /**
-     * 鍒ゆ柇瀛樺偍妗舵槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯鍒涘缓
-     *
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     */
-    public void existBucket(String bucketName) {
-        try {
-            boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
-            if (!exists) {
-                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * 鍒涘缓瀛樺偍妗�
-     *
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @return 鏄惁鍒涘缓鎴愬姛
-     */
-    public Boolean makeBucket(String bucketName) {
-        try {
-            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
-        } catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * 鍒犻櫎瀛樺偍妗�
-     *
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @return 鏄惁鍒犻櫎鎴愬姛
-     */
-    public Boolean removeBucket(String bucketName) {
-        try {
-            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
-        } catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * 鍒ゆ柇瀵硅薄鏄惁瀛樺湪
-     *
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @param originalFileName MinIO涓瓨鍌ㄥ璞″叏璺緞
-     * @return 瀵硅薄鏄惁瀛樺湪
-     */
-    public boolean existObject(String bucketName, String originalFileName) {
-        try {
-            minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(originalFileName).build());
-        } catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * 鏂囦欢涓婁紶
-     *
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @param file       鏂囦欢
-     * @return 妗朵腑浣嶇疆
-     */
-    public MinioResult upload(String bucketName, MultipartFile file, Boolean isPreviewExpiry) throws InvalidExtensionException {
-        MultipartFile[] fileArr = {file};
-        List<MinioResult> fileNames = upload(bucketName, fileArr, isPreviewExpiry);
-        return fileNames.isEmpty() ? null : fileNames.get(0);
-    }
-
-    /**
-     * 涓婁紶鏂囦欢
-     *
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @param fileList   鏂囦欢鍒楄〃
-     * @return 妗朵腑浣嶇疆鍒楄〃
-     */
-    public List<MinioResult> upload(String bucketName, List<MultipartFile> fileList, Boolean isPreviewExpiry) throws InvalidExtensionException {
-        MultipartFile[] fileArr = fileList.toArray(new MultipartFile[0]);
-        return upload(bucketName, fileArr, isPreviewExpiry);
-    }
-
-    /**
-     * description: 涓婁紶鏂囦欢
-     *
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @param fileArr    鏂囦欢鍒楄〃
-     * @return 妗朵腑浣嶇疆鍒楄〃
-     */
-    public List<MinioResult> upload(String bucketName, MultipartFile[] fileArr, Boolean isPreviewExpiry) throws InvalidExtensionException {
-        for (MultipartFile file : fileArr) {
-            FileUploadUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
-        }
-        // 淇濊瘉妗朵竴瀹氬瓨鍦�
-        existBucket(bucketName);
-        // 鎵ц姝e父鎿嶄綔
-        List<MinioResult> bucketFileNames = new ArrayList<>(fileArr.length);
-        for (MultipartFile file : fileArr) {
-            // 鑾峰彇鍘熷鏂囦欢鍚嶇О
-            String originalFileName = file.getOriginalFilename();
-            // 鑾峰彇褰撳墠鏃ユ湡锛屾牸寮忎緥濡傦細2020-11
-            String datePath = new SimpleDateFormat("yyyy-MM").format(new Date());
-            // 鏂囦欢鍚嶇О
-            String uuid = IdWorker.get32UUID();
-            // 鑾峰彇鏂囦欢鍚庣紑
-            String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
-            String bucketFilePath = datePath + "/" + uuid + suffix;
-
-            // 鎺ㄩ�佹枃浠跺埌MinIO
-            try (InputStream in = file.getInputStream()) {
-                minioClient.putObject(PutObjectArgs.builder()
-                        .bucket(bucketName)
-                        .object(bucketFilePath)
-                        .stream(in, in.available(), -1)
-                        .contentType(file.getContentType())
-                        .build()
-                );
-            } catch (Exception e) {
-                throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父:" + e);
-            }
-            MinioResult minioResult = new MinioResult();
-            minioResult.setBucketFileName(bucketFilePath);
-            // 杩斿洖姘镐箙棰勮鍦板潃
-            if (isPreviewExpiry) {
-                String previewUrl = getPreviewUrl(bucketFilePath, bucketName, isPreviewExpiry);
-                minioResult.setPreviewExpiry(previewUrl);
-            }
-            minioResult.setOriginalName(originalFileName);
-            bucketFileNames.add(minioResult);
-        }
-        return bucketFileNames;
-    }
-
-    /**
-     * 鏂囦欢涓嬭浇
-     *
-     * @param bucketName       瀛樺偍妗跺悕绉�
-     * @param bucketFileName   妗朵腑鏂囦欢鍚嶇О
-     * @param originalFileName 鍘熷鏂囦欢鍚嶇О
-     * @param response         response瀵硅薄
-     */
-    public void download(String bucketName, String bucketFileName, String originalFileName, HttpServletResponse response) {
-        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(bucketFileName).build();
-        try (GetObjectResponse objResponse = minioClient.getObject(objectArgs)) {
-            byte[] buf = new byte[1024];
-            int len;
-            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
-                while ((len = objResponse.read(buf)) != -1) {
-                    os.write(buf, 0, len);
-                }
-                os.flush();
-                byte[] bytes = os.toByteArray();
-                response.setCharacterEncoding("utf-8");
-                //璁剧疆寮哄埗涓嬭浇涓嶆墦寮�
-                response.setContentType("application/force-download");
-                // 璁剧疆闄勪欢鍚嶇О缂栫爜
-                originalFileName = new String(originalFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
-                // 璁剧疆闄勪欢鍚嶇О
-                response.addHeader("Content-Disposition", "attachment;fileName=" + originalFileName);
-                // 鍐欏叆鏂囦欢
-                try (ServletOutputStream stream = response.getOutputStream()) {
-                    stream.write(bytes);
-                    stream.flush();
-                }
-            }
-        } catch (Exception e) {
-            throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父");
-        }
-    }
-
-    /**
-     * 鑾峰彇宸蹭笂浼犲璞$殑鏂囦欢娴侊紙鍚庣鍥犱负涓氬姟闇�瑕佽幏鍙栨枃浠舵祦鍙互璋冪敤璇ユ柟娉曪級
-     *
-     * @param bucketName     瀛樺偍妗跺悕绉�
-     * @param bucketFileName 妗朵腑鏂囦欢鍚嶇О
-     * @return 鏂囦欢娴�
-     */
-    public InputStream getFileStream(String bucketName, String bucketFileName) throws Exception {
-        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(bucketFileName).build();
-        return minioClient.getObject(objectArgs);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鏂囦欢瀵硅薄缁撴灉
-     *
-     * @param bucketName      瀛樺偍妗跺悕绉�
-     * @param bucketFileName 妗朵腑鏂囦欢鍚嶇О
-     * @return 鍒犻櫎缁撴灉
-     */
-    public DeleteError removeObjectsResult(String bucketName, String bucketFileName) {
-        List<DeleteError> results = removeObjectsResult(bucketName, Collections.singletonList(bucketFileName));
-        return !results.isEmpty() ? results.get(0) : null;
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鏂囦欢瀵硅薄缁撴灉
-     *
-     * @param bucketName      瀛樺偍妗跺悕绉�
-     * @param bucketFileNames 妗朵腑鏂囦欢鍚嶇О闆嗗悎
-     * @return 鍒犻櫎缁撴灉
-     */
-    public List<DeleteError> removeObjectsResult(String bucketName, List<String> bucketFileNames) {
-        Iterable<Result<DeleteError>> results = removeObjects(bucketName, bucketFileNames);
-        List<DeleteError> res = new ArrayList<>();
-        for (Result<DeleteError> result : results) {
-            try {
-                res.add(result.get());
-            } catch (Exception e) {
-                throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父");
-            }
-        }
-        return res;
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鏂囦欢瀵硅薄
-     *
-     * @param bucketName      瀛樺偍妗跺悕绉�
-     * @param bucketFileNames 妗朵腑鏂囦欢鍚嶇О闆嗗悎
-     */
-    private Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> bucketFileNames) {
-        List<DeleteObject> dos = bucketFileNames.stream().map(DeleteObject::new).collect(Collectors.toList());
-        return minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
-    }
-
-    /**
-     * 鏌ヨ棰勮url
-     * @param bucketFileName minio鏂囦欢鍚嶇О
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @param isPreviewExpiry 鏄惁闇�瑕佽繃鏈熸椂闂� 榛樿24灏忔椂
-     * @return
-     */
-    public String getPreviewUrl(String bucketFileName, String bucketName, Boolean isPreviewExpiry) {
-        if (StringUtils.isNotBlank(bucketFileName)) {
-            try {
-                minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(bucketFileName).build());
-                // 涓篺alse鍙敓鎴�24灏忔椂鏈夋晥鏃堕暱鐨剈rl閾炬帴锛屽彲浠ヨ闂鏂囦欢
-                if (isPreviewExpiry){
-                    return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(bucketFileName).build());
-                }else {
-                    return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(bucketFileName).expiry(previewExpiry, TimeUnit.HOURS).build());
-                }
-            } catch (Exception e) {
-                throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父");
-            }
-        }
-        return null;
-    }
-
-    /**
-     * 鐢熸垚棰勮URL
-     * @param bucketFilename 鏂囦欢鍦∕inIO涓殑鍞竴鏍囪瘑
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @param useDefaultExpiry 鏄惁浣跨敤榛樿杩囨湡鏃堕棿锛坱rue=浣跨敤榛樿杩囨湡鏃堕棿锛宖alse=姘镐箙鏈夋晥锛�
-     * @return 棰勮URL
-     */
-    public String getPreviewUrls(String bucketFilename, String bucketName, boolean useDefaultExpiry) {
-        if (StringUtils.isBlank(bucketFilename)) {
-            return null;
-        }
-
-        try {
-            // 楠岃瘉鏂囦欢瀛樺湪鎬�
-            minioClient.statObject(StatObjectArgs.builder()
-                    .bucket(bucketName)
-                    .object(bucketFilename)
-                    .build());
-
-            GetPresignedObjectUrlArgs.Builder builder = GetPresignedObjectUrlArgs.builder()
-                    .method(Method.GET)
-                    .bucket(bucketName)
-                    .object(bucketFilename);
-
-            // 璁剧疆杩囨湡鏃堕棿锛歶seDefaultExpiry=true 浣跨敤閰嶇疆鐨勮繃鏈熸椂闂�
-            if (useDefaultExpiry) {
-                builder.expiry(previewExpiry, TimeUnit.HOURS);
-            }
-
-            return minioClient.getPresignedObjectUrl(builder.build());
-        } catch (Exception e) {
-            throw new UtilException("鐢熸垚棰勮URL澶辫触: " + e.getMessage(), e);
-        }
-    }
-
-
-    /**
-     * 鐢熸垚涓嬭浇URL锛堝己鍒舵祻瑙堝櫒涓嬭浇锛�
-     * @param bucketFilename 鏂囦欢鍦∕inIO涓殑鍞竴鏍囪瘑
-     * @param bucketName 瀛樺偍妗跺悕绉�
-     * @param originalFileName 鍘熷鏂囦欢鍚嶏紙鐢ㄤ簬涓嬭浇鏃舵樉绀猴級
-     * @param useDefaultExpiry 鏄惁浣跨敤榛樿杩囨湡鏃堕棿锛坱rue=浣跨敤榛樿锛宖alse=鏃犺繃鏈熸椂闂达級
-     * @return 涓嬭浇URL
-     */
-    public String getDownloadUrls(String bucketFilename, String bucketName, String originalFileName, boolean useDefaultExpiry) {
-        if (StringUtils.isBlank(bucketFilename)) {
-            return null;
-        }
-
-        try {
-            // 楠岃瘉鏂囦欢瀛樺湪鎬�
-            minioClient.statObject(StatObjectArgs.builder()
-                    .bucket(bucketName)
-                    .object(bucketFilename)
-                    .build());
-
-            // 姝g‘缂栫爜鏂囦欢鍚嶏細鏇挎崲 + 涓� %20
-            String encodedFileName = URLEncoder.encode(originalFileName, String.valueOf(StandardCharsets.UTF_8))
-                    .replace("+", "%20");
-
-            Map<String, String> reqParams = new HashMap<>();
-            reqParams.put("response-content-disposition",
-                    "attachment; filename=\"" + encodedFileName + "\"");
-
-            GetPresignedObjectUrlArgs.Builder builder = GetPresignedObjectUrlArgs.builder()
-                    .method(Method.GET)
-                    .bucket(bucketName)
-                    .object(bucketFilename)
-                    .extraQueryParams(reqParams);
-
-            // 鏍规嵁鍙傛暟鍐冲畾鏄惁璁剧疆杩囨湡鏃堕棿
-            if (useDefaultExpiry) {
-                // 浣跨敤榛樿杩囨湡鏃堕棿锛堜粠閰嶇疆璇诲彇锛�
-                builder.expiry(previewExpiry, TimeUnit.HOURS);
-            } else {
-                // 涓嶈缃繃鏈熸椂闂达紙MinIO 榛樿7澶╋級
-            }
-            return minioClient.getPresignedObjectUrl(builder.build());
-        } catch (Exception e) {
-            throw new UtilException("鐢熸垚涓嬭浇URL澶辫触: " + e.getMessage(), e);
-        }
-    }
-
-    public String getDownloadUrl(String bucketFileName, String bucketName) {
-        if (StringUtils.isNotBlank(bucketFileName)) {
-            try {
-                // 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦�
-                minioClient.statObject(StatObjectArgs.builder()
-                        .bucket(bucketName)
-                        .object(bucketFileName)
-                        .build());
-
-                // 璁剧疆鍝嶅簲澶�
-                Map<String, String> reqParams = new HashMap<>();
-                // 鎻愬彇鍘熷鏂囦欢鍚嶏紙濡傛灉瀛樺偍鏃朵繚鐣欎簡鍘熷鍚嶇О锛�
-                String originalFileName = extractOriginalFileName(bucketFileName);
-                reqParams.put("response-content-disposition",
-                        "attachment; filename=\"" + URLEncoder.encode(originalFileName, String.valueOf(StandardCharsets.UTF_8)) + "\"");
-
-                // 鏋勫缓棰勭鍚峌RL鍙傛暟
-                GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
-                        .method(Method.GET)
-                        .bucket(bucketName)
-                        .object(bucketFileName)
-                        .expiry(previewExpiry, TimeUnit.HOURS)
-                        .extraQueryParams(reqParams)
-                        .build();
-
-                return minioClient.getPresignedObjectUrl(args);
-            } catch (Exception e) {
-                throw new UtilException("MinioUtils锛氱敓鎴愪笅杞介摼鎺ュ紓甯�", e);
-            }
-        }
-        return null;
-    }
-
-    private String extractOriginalFileName(String bucketFileName) {
-        // 绀轰緥锛氬鏋滃瓨鍌ㄦ牸寮忎负 "鍘熷鏂囦欢鍚峗UUID"
-        int underscoreIndex = bucketFileName.lastIndexOf("_");
-        if (underscoreIndex > 0) {
-            return bucketFileName.substring(0, underscoreIndex);
-        }
-        // 濡傛灉娌℃湁鐗规畩鏍煎紡锛岀洿鎺ヨ繑鍥炲畬鏁存枃浠跺悕
-        return bucketFileName;
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/common/utils/OrderUtils.java b/src/main/java/com/ruoyi/common/utils/OrderUtils.java
index 7bb9aba..a110ec9 100644
--- a/src/main/java/com/ruoyi/common/utils/OrderUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/OrderUtils.java
@@ -2,9 +2,6 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.common.utils.uuid.UUID;
-import org.apache.poi.ss.formula.functions.T;
-import org.springframework.stereotype.Component;
 
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -12,7 +9,6 @@
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -24,82 +20,88 @@
 
     /**
      * List<Integer> 杞崲涓� Long[] 鏁扮粍
-     * @param ids
-     * @return
+     * @param ids ids
+     * @return Long[]
      */
     public static Long[] listIntegerToLongArray(List<Integer> ids) {
         return ids.stream()
-                // 澶勭悊null鍊硷細濡傛灉鍏冪礌涓簄ull锛岃浆鎹负0L锛堝彲鏍规嵁涓氬姟璋冩暣锛屾瘮濡傛姏寮傚父锛�
                 .map(id -> id != null ? id.longValue() : -1L)
-                // 灏哠tream<Long>杞崲涓篖ong[]鏁扮粍
                 .toArray(Long[]::new);
     }
 
     /**
      * 鍒ゆ柇鐩爣id鏄惁鍦ㄩ�楀彿鍒嗛殧鐨勫瓧绗︿覆涓�
-     * @param targetId
-     * @param str
-     * @return
+     * @param targetId targetId
+     * @param str source
+     * @return boolean
      */
     public boolean isStaffIdExist(Object targetId,String str) {
-        // 绌哄�兼牎楠岋紝閬垮厤绌烘寚閽�
         if (str == null || str.trim().isEmpty() || targetId == null) {
             return false;
         }
-        // 鎸夐�楀彿鍒嗗壊鎴愭暟缁�
         String[] idArray = str.split(",");
-        // 閬嶅巻鏁扮粍鍒ゆ柇鏄惁鍖呭惈鐩爣id
         for (String id : idArray) {
-            // 鍘婚櫎绌烘牸锛堥槻姝㈠瓧绗︿覆涓湁澶氫綑绌烘牸锛屽"1, 121"锛�
             String cleanId = id.trim();
-            // 杞崲涓烘暟瀛楀苟姣旇緝
             try {
                 if (cleanId.equals(String.valueOf(targetId))) {
                     return true;
                 }
             } catch (NumberFormatException e) {
-                // 鑻ュ瓨鍦ㄩ潪鏁板瓧ID锛岀洿鎺ヨ繑鍥瀎alse
                 return false;
             }
         }
         return false;
     }
 
-
-
     /**
-     * 鏌ヨ褰撳ぉ锛堝熀浜巆reateTime瀛楁锛夌殑璁板綍鏁伴噺
-     * @param mapper 瀹炰綋绫诲搴旂殑BaseMapper
-     * @param <T> 瀹炰綋绫绘硾鍨�
-     * @return 褰撳ぉ璁板綍鏁伴噺
+     * 鏌ヨ褰撳ぉ鍩轰簬 create_time 鐨勬渶鏂扮紪鍙凤紝骞剁敓鎴愪笅涓�涓紪鍙�
+     * @param mapper mapper
+     * @param preFix 缂栧彿鍓嶇紑
+     * @param code 缂栧彿瀛楁
+     * @param <T> 瀹炰綋绫诲瀷
+     * @return 璁㈠崟缂栧彿
      */
-    public static <T> String countTodayByCreateTime(BaseMapper<T> mapper,String preFix) {
-        // 鑾峰彇褰撳ぉ寮�濮嬫椂闂达紙00:00:00锛�
-        LocalDateTime todayStart = LocalDateTime.of(
-                LocalDateTime.now().toLocalDate(),
-                LocalTime.MIN
-        );
-        // 鑾峰彇褰撳ぉ缁撴潫鏃堕棿锛�23:59:59.999锛�
-        LocalDateTime todayEnd = LocalDateTime.of(
-                LocalDateTime.now().toLocalDate(),
-                LocalTime.MAX
-        );
+    public static <T> String countTodayByCreateTime(BaseMapper<T> mapper,String preFix,String code) {
+        LocalDate today = LocalDate.now();
+        LocalDateTime todayStart = today.atStartOfDay();
+        LocalDateTime tomorrowStart = today.plusDays(1).atStartOfDay();
+        String dateStr = today.format(DateTimeFormatter.BASIC_ISO_DATE);
+        String codePrefix = preFix + dateStr;
 
-        // 杞崲涓篋ate绫诲瀷锛堝鏋滃疄浣撶被涓璫reateTime鏄疞ocalDateTime鍙洿鎺ヤ娇鐢級
-        Date startDate = Date.from(todayStart.atZone(ZoneId.systemDefault()).toInstant());
-        Date endDate = Date.from(todayEnd.atZone(ZoneId.systemDefault()).toInstant());
+        QueryWrapper<T> wrapper = new QueryWrapper<>();
+        wrapper.select(code)
+                .ge("create_time", todayStart)
+                .lt("create_time", tomorrowStart)
+                .likeRight(code, codePrefix)
+                .orderByDesc(code)
+                .last("LIMIT 1");
 
-        // 鏋勫缓鏌ヨ鏉′欢
-        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
-        queryWrapper.ge("create_time", startDate)  // 澶т簬绛変簬褰撳ぉ寮�濮�
-                .lt("create_time", endDate);   // 灏忎簬褰撳ぉ缁撴潫锛堥伩鍏嶆绉掔簿搴﹂棶棰橈級
+        long nextSeq = 1;
+        List<Map<String, Object>> records = mapper.selectMaps(wrapper);
+        if (!records.isEmpty()) {
+            Object lastCode = records.get(0).get(code);
+            if (lastCode != null) {
+                nextSeq = extractSequence(lastCode.toString(), codePrefix) + 1;
+            }
+        }
 
-        // 鎵ц鏌ヨ
-        Long aLong = mapper.selectCount(queryWrapper);
-        // 鎷兼帴璁㈠崟缂栧彿 preFix + 鏃堕棿锛坹yyyMMdd锛� + 璁㈠崟鏁伴噺(001)
-        return preFix + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE).replaceAll("-", "") + String.format("%03d", (aLong + 1)) + "-" + new Date().getTime();
+        return preFix + dateStr + String.format("%03d", nextSeq);
     }
 
+    private static long extractSequence(String fullCode, String codePrefix) {
+        if (!fullCode.startsWith(codePrefix)) {
+            return 0;
+        }
+        String seqStr = fullCode.substring(codePrefix.length()).trim();
+        if (seqStr.isEmpty()) {
+            return 0;
+        }
+        try {
+            return Long.parseLong(seqStr);
+        } catch (NumberFormatException e) {
+            return 0;
+        }
+    }
 
     /**
      * 鏌ヨ褰撳ぉ锛堝熀浜巆reateTime瀛楁锛夌殑璁板綍鏁伴噺
@@ -108,29 +110,23 @@
      * @return 褰撳ぉ璁板綍鏁伴噺
      */
     public static <T> String countAfterServiceTodayByCreateTime(BaseMapper<T> mapper,String preFix) {
-        // 鑾峰彇褰撳ぉ寮�濮嬫椂闂达紙00:00:00锛�
         LocalDateTime todayStart = LocalDateTime.of(
                 LocalDateTime.now().toLocalDate(),
                 LocalTime.MIN
         );
-        // 鑾峰彇褰撳ぉ缁撴潫鏃堕棿锛�23:59:59.999锛�
         LocalDateTime todayEnd = LocalDateTime.of(
                 LocalDateTime.now().toLocalDate(),
                 LocalTime.MAX
         );
 
-        // 杞崲涓篋ate绫诲瀷锛堝鏋滃疄浣撶被涓璫reateTime鏄疞ocalDateTime鍙洿鎺ヤ娇鐢級
         Date startDate = Date.from(todayStart.atZone(ZoneId.systemDefault()).toInstant());
         Date endDate = Date.from(todayEnd.atZone(ZoneId.systemDefault()).toInstant());
 
-        // 鏋勫缓鏌ヨ鏉′欢
         QueryWrapper<T> queryWrapper = new QueryWrapper<>();
-        queryWrapper.ge("create_time", startDate)  // 澶т簬绛変簬褰撳ぉ寮�濮�
-                .lt("create_time", endDate);   // 灏忎簬褰撳ぉ缁撴潫锛堥伩鍏嶆绉掔簿搴﹂棶棰橈級
+        queryWrapper.ge("create_time", startDate)
+                .lt("create_time", endDate);
 
-        // 鎵ц鏌ヨ
         Long aLong = mapper.selectCount(queryWrapper);
-        // 鎷兼帴璁㈠崟缂栧彿 preFix + 鏃堕棿锛坹yyyMMdd锛� + 璁㈠崟鏁伴噺(001)
         return preFix + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE).replaceAll("-", "") + String.format("%03d", (aLong + 1));
     }
 }
diff --git a/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/src/main/java/com/ruoyi/common/utils/ServletUtils.java
index 292b8da..a7882ee 100644
--- a/src/main/java/com/ruoyi/common/utils/ServletUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/ServletUtils.java
@@ -7,10 +7,10 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
 import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
diff --git a/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java b/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
index d9821e0..03e8972 100644
--- a/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
+++ b/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
@@ -1,9 +1,9 @@
 package com.ruoyi.common.utils.bean;
 
 import java.util.Set;
-import javax.validation.ConstraintViolation;
-import javax.validation.ConstraintViolationException;
-import javax.validation.Validator;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import jakarta.validation.Validator;
 
 /**
  * bean瀵硅薄灞炴�ч獙璇�
diff --git a/src/main/java/com/ruoyi/common/utils/excel/ExcelUtils.java b/src/main/java/com/ruoyi/common/utils/excel/ExcelUtils.java
index 230bb77..e54f253 100644
--- a/src/main/java/com/ruoyi/common/utils/excel/ExcelUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/excel/ExcelUtils.java
@@ -15,8 +15,8 @@
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.web.multipart.MultipartFile;
  
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
diff --git a/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
index d4815b0..ccadb17 100644
--- a/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
@@ -9,8 +9,8 @@
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
diff --git a/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
index 8baad38..359ee07 100644
--- a/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
+++ b/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
@@ -5,7 +5,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
-import javax.servlet.ServletRequest;
+import jakarta.servlet.ServletRequest;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
index 0a16b62..34cf78e 100644
--- a/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -1,27 +1,19 @@
 package com.ruoyi.common.utils.http;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+
+import javax.net.ssl.*;
+import java.io.*;
 import java.net.ConnectException;
 import java.net.SocketTimeoutException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.charset.StandardCharsets;
 import java.security.cert.X509Certificate;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.utils.StringUtils;
-import org.springframework.http.MediaType;
 
 /**
  * 閫氱敤http鍙戦�佹柟娉�
diff --git a/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
index 3316240..24f89b6 100644
--- a/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
@@ -2,7 +2,7 @@
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.StringUtils;
 
diff --git a/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
index cdab562..bb2ebb5 100644
--- a/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+++ b/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -23,7 +23,7 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.RegExUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
diff --git a/src/main/java/com/ruoyi/common/vo/FileVo.java b/src/main/java/com/ruoyi/common/vo/FileVo.java
index bc7adb8..4ac5307 100644
--- a/src/main/java/com/ruoyi/common/vo/FileVo.java
+++ b/src/main/java/com/ruoyi/common/vo/FileVo.java
@@ -1,6 +1,6 @@
 package com.ruoyi.common.vo;
 
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -8,25 +8,25 @@
 @Data
 public class FileVo {
 
-    @ApiModelProperty(value = "鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty(value = "鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private int fileSize;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     private Integer updateUser;
 
     private Long id;
diff --git a/src/main/java/com/ruoyi/common/vo/SimpleFileVo.java b/src/main/java/com/ruoyi/common/vo/SimpleFileVo.java
index ea817c7..1ee9a00 100644
--- a/src/main/java/com/ruoyi/common/vo/SimpleFileVo.java
+++ b/src/main/java/com/ruoyi/common/vo/SimpleFileVo.java
@@ -5,7 +5,7 @@
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
 import java.io.Serializable;
 
 /**
diff --git a/src/main/java/com/ruoyi/common/xss/Xss.java b/src/main/java/com/ruoyi/common/xss/Xss.java
index 14e43dc..93a3840 100644
--- a/src/main/java/com/ruoyi/common/xss/Xss.java
+++ b/src/main/java/com/ruoyi/common/xss/Xss.java
@@ -1,7 +1,7 @@
 package com.ruoyi.common.xss;
 
-import javax.validation.Constraint;
-import javax.validation.Payload;
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/src/main/java/com/ruoyi/common/xss/XssValidator.java b/src/main/java/com/ruoyi/common/xss/XssValidator.java
index b859428..585fa8a 100644
--- a/src/main/java/com/ruoyi/common/xss/XssValidator.java
+++ b/src/main/java/com/ruoyi/common/xss/XssValidator.java
@@ -1,8 +1,8 @@
 package com.ruoyi.common.xss;
 
 import com.ruoyi.common.utils.StringUtils;
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
diff --git a/src/main/java/com/ruoyi/compensationperformance/controller/CompensationPerformanceController.java b/src/main/java/com/ruoyi/compensationperformance/controller/CompensationPerformanceController.java
index f6eee0f..25f91c5 100644
--- a/src/main/java/com/ruoyi/compensationperformance/controller/CompensationPerformanceController.java
+++ b/src/main/java/com/ruoyi/compensationperformance/controller/CompensationPerformanceController.java
@@ -1,6 +1,5 @@
 package com.ruoyi.compensationperformance.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -10,42 +9,37 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.mapper.SysUserMapper;
-import com.ruoyi.purchase.dto.PaymentRegistrationDto;
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.StaffOnJob;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  * @author :yys
  * @date : 2025/8/8 9:56
  */
 @RestController
-@Api(tags = "钖叕缁╂晥")
+@Tag(name = "钖叕缁╂晥")
 @RequestMapping("/compensationPerformance")
+@AllArgsConstructor
 public class CompensationPerformanceController extends BaseController {
 
-    @Autowired
     private CompensationPerformanceService compensationPerformanceService;
-
-    @Autowired
     private StaffOnJobMapper staffOnJobMapper;
 
     @GetMapping("/listPage")
     @Log(title = "钖叕缁╂晥-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("钖叕缁╂晥-鍒嗛〉鏌ヨ")
+    @Operation(summary = "钖叕缁╂晥-鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, String staffName, String payDateStr) {
         IPage<CompensationPerformance> listPage = compensationPerformanceService.listPage(page, staffName, payDateStr);
         return AjaxResult.success(listPage);
@@ -53,7 +47,7 @@
 
     @PostMapping("/add")
     @Log(title = "钖叕缁╂晥-娣诲姞", businessType = BusinessType.INSERT)
-    @ApiOperation("钖叕缁╂晥-娣诲姞")
+    @Operation(summary = "钖叕缁╂晥-娣诲姞")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody CompensationPerformance compensationPerformance) {
         boolean save = compensationPerformanceService.save(compensationPerformance);
@@ -62,7 +56,7 @@
 
     @PostMapping("/update")
     @Log(title = "钖叕缁╂晥-淇敼", businessType = BusinessType.UPDATE)
-    @ApiOperation("钖叕缁╂晥-淇敼")
+    @Operation(summary = "钖叕缁╂晥-淇敼")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody CompensationPerformance compensationPerformance) {
         boolean update = compensationPerformanceService.updateById(compensationPerformance);
@@ -71,7 +65,7 @@
 
     @DeleteMapping("/delete")
     @Log(title = "钖叕缁╂晥-鍒犻櫎", businessType = BusinessType.DELETE)
-    @ApiOperation("钖叕缁╂晥-鍒犻櫎")
+    @Operation(summary = "钖叕缁╂晥-鍒犻櫎")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
diff --git a/src/main/java/com/ruoyi/compensationperformance/pojo/CompensationPerformance.java b/src/main/java/com/ruoyi/compensationperformance/pojo/CompensationPerformance.java
index 686b975..bc28ded 100644
--- a/src/main/java/com/ruoyi/compensationperformance/pojo/CompensationPerformance.java
+++ b/src/main/java/com/ruoyi/compensationperformance/pojo/CompensationPerformance.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -21,25 +20,25 @@
  */
 @Data
 @TableName("compensation_performance")
-@ApiModel("钖叕缁╂晥鏄庣粏")
+@Schema(name = "钖叕缁╂晥鏄庣粏")
 public class CompensationPerformance implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
     @TableId(value = "id", type = IdType.AUTO)
-    @ApiModelProperty("涓婚敭")
+    @Schema(description = "涓婚敭")
     private Long id;
 
     /**
      * 鍛樺伐id
      */
-    @ApiModelProperty("鍛樺伐id")
+    @Schema(description = "鍛樺伐id")
     private Long staffId;
 
     /**
      * 鍛樺伐濮撳悕
      */
-    @ApiModelProperty("鍛樺伐濮撳悕")
+    @Schema(description = "鍛樺伐濮撳悕")
     @Excel(name = "鍛樺伐濮撳悕")
     @TableField(exist = false)
     private String staffName;
@@ -47,7 +46,7 @@
     /**
      * 宀椾綅鍚嶇О
      */
-    @ApiModelProperty("宀椾綅鍚嶇О")
+    @Schema(description = "宀椾綅鍚嶇О")
     @Excel(name = "宀椾綅鍚嶇О")
     @TableField(exist = false)
     private String postName;
@@ -55,7 +54,7 @@
     /**
      * 閮ㄩ棬鍚嶇О
      */
-    @ApiModelProperty("閮ㄩ棬鍚嶇О")
+    @Schema(description = "閮ㄩ棬鍚嶇О")
     @Excel(name = "閮ㄩ棬鍚嶇О")
     @TableField(exist = false)
     private String deptName;
@@ -63,7 +62,7 @@
     /**
      * 钖祫鏈堜唤
      */
-    @ApiModelProperty("钖祫鏈堜唤")
+    @Schema(description = "钖祫鏈堜唤")
     @Excel(name = "鏈堜唤", dateFormat = "yyyy-MM", width = 20)
     @JsonFormat(pattern = "yyyy-MM", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM")
@@ -72,84 +71,84 @@
     /**
      * 鍩烘湰宸ヨ祫
      */
-    @ApiModelProperty("鍩烘湰宸ヨ祫")
+    @Schema(description = "鍩烘湰宸ヨ祫")
     @Excel(name = "鍩烘湰宸ヨ祫")
     private BigDecimal basicSalary;
 
     /**
      * 璁′欢宸ヨ祫
      */
-    @ApiModelProperty("璁′欢宸ヨ祫")
+    @Schema(description = "璁′欢宸ヨ祫")
     @Excel(name = "璁′欢宸ヨ祫")
     private BigDecimal pieceworkSalary;
 
     /**
      * 璁℃椂宸ヨ祫
      */
-    @ApiModelProperty("璁℃椂宸ヨ祫")
+    @Schema(description = "璁℃椂宸ヨ祫")
     @Excel(name = "璁℃椂宸ヨ祫")
     private BigDecimal hourlySalary;
 
     /**
      * 鍏朵粬鏀跺叆
      */
-    @ApiModelProperty("鍏朵粬鏀跺叆")
+    @Schema(description = "鍏朵粬鏀跺叆")
     @Excel(name = "鍏朵粬鏀跺叆")
     private BigDecimal otherIncome;
 
     /**
      * 绀句繚涓汉
      */
-    @ApiModelProperty("绀句繚涓汉")
+    @Schema(description = "绀句繚涓汉")
     @Excel(name = "绀句繚涓汉")
     private BigDecimal socialSecurityIndividuals;
 
     /**
      * 鍏Н閲戜釜浜�
      */
-    @ApiModelProperty("鍏Н閲戜釜浜�")
+    @Schema(description = "鍏Н閲戜釜浜�")
     @Excel(name = "鍏Н閲戜釜浜�")
     private BigDecimal providentFundIndividuals;
 
     /**
      * 宸ヨ祫涓◣
      */
-    @ApiModelProperty("宸ヨ祫涓◣")
+    @Schema(description = "宸ヨ祫涓◣")
     @Excel(name = "宸ヨ祫涓◣")
     private BigDecimal personalIncomeTax;
 
     /**
      * 鍏朵粬鏀嚭
      */
-    @ApiModelProperty("鍏朵粬鏀嚭")
+    @Schema(description = "鍏朵粬鏀嚭")
     @Excel(name = "鍏朵粬鏀嚭")
     private BigDecimal otherDeductions;
 
     /**
      * 搴斿彂宸ヨ祫
      */
-    @ApiModelProperty("搴斿彂宸ヨ祫")
+    @Schema(description = "搴斿彂宸ヨ祫")
     @Excel(name = "搴斿彂宸ヨ祫")
     private BigDecimal payableWages;
 
     /**
      * 搴旀墸宸ヨ祫
      */
-    @ApiModelProperty("搴旀墸宸ヨ祫")
+    @Schema(description = "搴旀墸宸ヨ祫")
     @Excel(name = "搴旀墸宸ヨ祫")
     private BigDecimal deductibleWages;
 
     /**
      * 瀹炲彂宸ヨ祫
      */
-    @ApiModelProperty("瀹炲彂宸ヨ祫")
+    @Schema(description = "瀹炲彂宸ヨ祫")
     @Excel(name = "瀹炲彂宸ヨ祫")
     private BigDecimal actualWages;
 
     /**
      * 澶囨敞
      */
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     @Excel(name = "澶囨敞")
     private String remark;
 
@@ -185,4 +184,7 @@
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime updateTime;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/compensationperformance/service/impl/CompensationPerformanceServiceImpl.java b/src/main/java/com/ruoyi/compensationperformance/service/impl/CompensationPerformanceServiceImpl.java
index b3b3aa7..019de96 100644
--- a/src/main/java/com/ruoyi/compensationperformance/service/impl/CompensationPerformanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/compensationperformance/service/impl/CompensationPerformanceServiceImpl.java
@@ -6,8 +6,8 @@
 import com.ruoyi.compensationperformance.mapper.CompensationPerformanceMapper;
 import com.ruoyi.compensationperformance.pojo.CompensationPerformance;
 import com.ruoyi.compensationperformance.service.CompensationPerformanceService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -18,10 +18,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class CompensationPerformanceServiceImpl extends ServiceImpl<CompensationPerformanceMapper, CompensationPerformance> implements CompensationPerformanceService {
 
-    @Autowired
-    private CompensationPerformanceMapper compensationPerformanceMapper;
+    private final CompensationPerformanceMapper compensationPerformanceMapper;
 
 
     @Override
diff --git a/src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java b/src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java
index 6f293d4..586ee42 100644
--- a/src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java
+++ b/src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java
@@ -9,8 +9,9 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
@@ -20,23 +21,23 @@
  * @date : 2025/8/29 10:28
  */
 @RestController
-@Api(tags = "瀹㈡埛鎷滆")
+@Tag(name = "瀹㈡埛鎷滆")
 @RequestMapping("/customerVisits")
+@AllArgsConstructor
 public class CustomerVisitsController extends BaseController {
 
-    @Autowired
     private CustomerVisitsServiceImpl customerVisitsService;
 
     @GetMapping("/listPage")
     @Log(title = "瀹㈡埛鎷滆-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("瀹㈡埛鎷滆-鍒嗛〉鏌ヨ")
+    @Operation(summary = "瀹㈡埛鎷滆-鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, CustomerVisits customerVisits) {
         IPage<CustomerVisits> listPage = customerVisitsService.listPage(page, customerVisits);
         return AjaxResult.success(listPage);
     }
 
     @Log(title = "瀹㈡埛鎷滆-娣诲姞", businessType = BusinessType.INSERT)
-    @ApiOperation("瀹㈡埛鎷滆-娣诲姞")
+    @Operation(summary = "瀹㈡埛鎷滆-娣诲姞")
     @PostMapping("/add")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody CustomerVisits customerVisits) {
@@ -48,7 +49,7 @@
     }
 
     @Log(title = "瀹㈡埛鎷滆-缂栬緫", businessType = BusinessType.UPDATE)
-    @ApiOperation("瀹㈡埛鎷滆-缂栬緫")
+    @Operation(summary = "瀹㈡埛鎷滆-缂栬緫")
     @PostMapping("update")
     public AjaxResult updateCustomerVisit(@RequestBody CustomerVisits customerVisits) {
         boolean updateResult = customerVisitsService.updateCustomerVisit(customerVisits);
@@ -59,7 +60,7 @@
     }
 
     @Log(title = "瀹㈡埛鎷滆-鍒犻櫎", businessType = BusinessType.DELETE)
-    @ApiOperation("瀹㈡埛鎷滆-鍒犻櫎")
+    @Operation(summary = "瀹㈡埛鎷滆-鍒犻櫎")
     @DeleteMapping("{customerId}")
     public AjaxResult deleteCustomerVisit(@PathVariable Integer customerId) {
         if (customerId == null) {
diff --git a/src/main/java/com/ruoyi/customervisits/pojo/CustomerVisits.java b/src/main/java/com/ruoyi/customervisits/pojo/CustomerVisits.java
index 722ab60..2f19cf1 100644
--- a/src/main/java/com/ruoyi/customervisits/pojo/CustomerVisits.java
+++ b/src/main/java/com/ruoyi/customervisits/pojo/CustomerVisits.java
@@ -4,8 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Builder;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -21,7 +20,7 @@
 @TableName("customer_visits")
 @Data
 @Builder
-@ApiModel
+@Schema
 public class CustomerVisits {
 
     private static final long serialVersionUID = 1L;
@@ -32,55 +31,55 @@
     /**
      * 瀹㈡埛鍚嶇О
      */
-    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
     /**
      * 鑱旂郴浜�
      */
-    @ApiModelProperty("鑱旂郴浜�")
+    @Schema(description = "鑱旂郴浜�")
     private String contact;
 
     /**
      * 鑱旂郴鐢佃瘽
      */
-    @ApiModelProperty("鑱旂郴鐢佃瘽")
+    @Schema(description = "鑱旂郴鐢佃瘽")
     private String contactPhone;
 
     /**
      * 浣嶇疆
      */
-    @ApiModelProperty("浣嶇疆")
+    @Schema(description = "浣嶇疆")
     private String location;
 
     /**
      * 鎷滆浜�
      */
-    @ApiModelProperty("鎷滆浜�")
+    @Schema(description = "鎷滆浜�")
     private String visitingPeople;
 
     /**
      * 鎷滆鐩殑
      */
-    @ApiModelProperty("鎷滆鐩殑")
+    @Schema(description = "鎷滆鐩殑")
     private String purposeVisit;
 
     /**
      * 鎷滆鏃堕棿
      */
-    @ApiModelProperty("鎷滆鏃堕棿")
+    @Schema(description = "鎷滆鏃堕棿")
     private String purposeDate;
 
     /**
      * 鎷滆鍦板潃
      */
-    @ApiModelProperty("鎷滆鍦板潃")
+    @Schema(description = "鎷滆鍦板潃")
     private String visitAddress;
 
     /**
      * 澶囨敞
      */
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
     /**
@@ -112,4 +111,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java b/src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java
index f44742a..2e0a0b0 100644
--- a/src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java
+++ b/src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java
@@ -8,8 +8,8 @@
 import com.ruoyi.customervisits.mapper.CustomerVisitsMapper;
 import com.ruoyi.customervisits.pojo.CustomerVisits;
 import com.ruoyi.customervisits.service.CustomerVisitsService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -19,10 +19,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class CustomerVisitsServiceImpl extends ServiceImpl<CustomerVisitsMapper, CustomerVisits> implements CustomerVisitsService {
 
-    @Autowired
-    private CustomerVisitsMapper customerVisitsMapper;
+    private final CustomerVisitsMapper customerVisitsMapper;
 
     @Override
     public IPage<CustomerVisits> listPage(Page page, CustomerVisits customerVisits) {
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java b/src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java
index 59b0b4f..1fd1c04 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java
@@ -5,23 +5,23 @@
 import com.ruoyi.device.pojo.DeviceDefectRecord;
 import com.ruoyi.device.service.DeviceDefectRecordService;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-@Api(tags = "璁惧缂洪櫡璁板綍绠$悊")
+@Tag(name = "璁惧缂洪櫡璁板綍绠$悊")
 @RequestMapping("/defect")
+@AllArgsConstructor
 @RestController
 public class DeviceDefectRecordController {
-    @Autowired
     private DeviceDefectRecordService deviceDefectRecordService;
-    @ApiOperation("璁惧缂洪櫡璁板綍鍒楄〃")
+    @Operation(summary = "璁惧缂洪櫡璁板綍鍒楄〃")
     @GetMapping("/page")
     public AjaxResult page(Page page , DeviceDefectRecordDto deviceDefectRecordDto) {
         return AjaxResult.success(deviceDefectRecordService.listPage(page,deviceDefectRecordDto));
     }
-    @ApiOperation("璁惧id鏌ヨ璁惧缂洪櫡璁板綍鍒楄〃")
+    @Operation(summary = "璁惧id鏌ヨ璁惧缂洪櫡璁板綍鍒楄〃")
     @GetMapping("/find/{deviceLedgerId}")
     public AjaxResult find(@PathVariable Long deviceLedgerId) {
         DeviceDefectRecordDto deviceDefectRecordDto = new DeviceDefectRecordDto();
@@ -30,17 +30,17 @@
     }
 
     @PostMapping("/add")
-    @ApiOperation("娣诲姞璁惧缂洪櫡璁板綍")
+    @Operation(summary = "娣诲姞璁惧缂洪櫡璁板綍")
     public AjaxResult add(@RequestBody DeviceDefectRecord deviceDefectRecord) {
         return AjaxResult.success(deviceDefectRecordService.add(deviceDefectRecord));
     }
     @PostMapping("/update")
-    @ApiOperation("淇敼璁惧缂洪櫡璁板綍")
+    @Operation(summary = "淇敼璁惧缂洪櫡璁板綍")
     public AjaxResult update(@RequestBody DeviceDefectRecord deviceDefectRecord) {
         return AjaxResult.success(deviceDefectRecordService.updateByDDR(deviceDefectRecord));
     }
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎璁惧缂洪櫡璁板綍")
+    @Operation(summary = "鍒犻櫎璁惧缂洪櫡璁板綍")
     public AjaxResult delete(@PathVariable Long id) {
         return AjaxResult.success(deviceDefectRecordService.removeById(id));
     }
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java b/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
index f79d4d2..f4b807d 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
@@ -3,7 +3,9 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.device.dto.DeviceLedgerDto;
+import com.ruoyi.device.execl.DeviceLedgerExeclDto;
 import com.ruoyi.device.mapper.DeviceLedgerMapper;
 import com.ruoyi.device.mapper.DeviceMaintenanceMapper;
 import com.ruoyi.device.pojo.DeviceLedger;
@@ -11,60 +13,56 @@
 import com.ruoyi.device.service.IDeviceLedgerService;
 import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-@Api(tags = "璁惧鍙拌处绠$悊")
+@Tag(name = "璁惧鍙拌处绠$悊")
 @RequestMapping("/device/ledger")
 @RestController
+@AllArgsConstructor
 public class DeviceLedgerController {
 
-    @Autowired
     private IDeviceLedgerService deviceLedgerService;
-
-    @Autowired
     private DeviceLedgerMapper deviceLedgerMapper;
-
-    @Autowired
     private DeviceMaintenanceMapper deviceMaintenanceMapper;
 
 
 
-    @ApiOperation("璁惧鍙拌处鍒楄〃")
+    @Operation(summary = "璁惧鍙拌处鍒楄〃")
     @GetMapping("/page")
     public AjaxResult page(Page page , DeviceLedgerDto deviceLedger) {
         return AjaxResult.success(deviceLedgerService.queryPage(page,deviceLedger));
     }
 
     @PostMapping()
-    @ApiOperation("娣诲姞璁惧鍙拌处")
+    @Operation(summary = "娣诲姞璁惧鍙拌处")
     public AjaxResult add(@RequestBody DeviceLedger deviceLedger) {
 
         return deviceLedgerService.saveDeviceLedger(deviceLedger);
     }
 
-    @ApiOperation("鏍规嵁id鏌ヨ璁惧鍙拌处")
+    @Operation(summary = "鏍规嵁id鏌ヨ璁惧鍙拌处")
     @GetMapping("/{id}")
     public AjaxResult detail(@PathVariable Long id) {
         return AjaxResult.success(deviceLedgerService.getById(id));
     }
 
     @PutMapping ()
-    @ApiOperation("淇敼璁惧鍙拌处")
+    @Operation(summary = "淇敼璁惧鍙拌处")
     public AjaxResult update(@RequestBody DeviceLedger deviceLedger) {
         return deviceLedgerService.updateDeviceLedger(deviceLedger);
     }
 
     @DeleteMapping("/{ids}")
-    @ApiOperation("鍒犻櫎璁惧鍙拌处")
+    @Operation(summary = "鍒犻櫎璁惧鍙拌处")
     public AjaxResult delete(@PathVariable("ids") ArrayList<Long> ids) {
         boolean b = deviceLedgerService.removeBatchByIds(ids);
         if (!b) {
@@ -74,13 +72,20 @@
     }
 
     @PostMapping("export")
-    @ApiOperation("瀵煎嚭璁惧鍙拌处")
+    @Operation(summary = "瀵煎嚭璁惧鍙拌处")
     public void export(HttpServletResponse response, Long[] ids) {
          deviceLedgerService.export(response, ids);
     }
 
-    @PostMapping("import")
-    @ApiOperation("瀵煎叆璁惧鍙拌处")
+    @Operation(summary = "涓嬭浇妯℃澘")
+    @PostMapping("/downloadTemplate")
+    public void downloadTemplate(HttpServletResponse response) {
+        ExcelUtil<DeviceLedgerExeclDto> util = new ExcelUtil<>(DeviceLedgerExeclDto.class);
+        util.importTemplateExcel(response, "璁惧瀵煎叆妯℃澘");
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "瀵煎叆璁惧鍙拌处")
     public AjaxResult importData(MultipartFile file) throws IOException {
         Boolean b = deviceLedgerService.importData(file);
         if (b) {
@@ -91,14 +96,14 @@
 
 
     @GetMapping("getDeviceLedger")
-    @ApiOperation("鑾峰彇璁惧鍙拌处")
+    @Operation(summary = "鑾峰彇璁惧鍙拌处")
     public AjaxResult getDeviceLedger( ) {
         return AjaxResult.success(deviceLedgerService.list(new QueryWrapper<DeviceLedger>().lambda()
                 .select(DeviceLedger::getId, DeviceLedger::getDeviceName,DeviceLedger::getDeviceModel)));
     }
 
     @GetMapping("scanDevice")
-    @ApiOperation("鑾峰彇璁惧鍙拌处")
+    @Operation(summary = "鑾峰彇璁惧鍙拌处")
     @Anonymous
     public AjaxResult scanDevice(Long id) {
         List<DeviceMaintenance> list = deviceMaintenanceMapper.list1(id);
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java b/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
index 0804b79..e34fc37 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
@@ -8,50 +8,48 @@
 import com.ruoyi.device.service.IDeviceLedgerService;
 import com.ruoyi.device.service.IDeviceMaintenanceService;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.Arrays;
 
-@Api(tags = "璁惧淇濆吇")
+@Tag(name = "璁惧淇濆吇")
 @RestController
 @RequestMapping("/device/maintenance")
+@AllArgsConstructor
 public class DeviceMaintenanceController {
 
 
-    @Autowired
     private IDeviceMaintenanceService deviceMaintenanceService;
-
-    @Autowired
     private IDeviceLedgerService deviceLedgerService;
 
-    @ApiOperation("璁惧淇濆吇鍒楄〃")
+    @Operation(summary = "璁惧淇濆吇鍒楄〃")
     @GetMapping("/page")
     public AjaxResult page(Page page , DeviceMaintenanceDto deviceMaintenanceDto) {
         return AjaxResult.success(deviceMaintenanceService.queryPage(page,deviceMaintenanceDto));
     }
 
     @PostMapping()
-    @ApiOperation("娣诲姞璁惧淇濆吇")
-    public AjaxResult add(@RequestBody DeviceMaintenance deviceMaintenance) {
+    @Operation(summary = "娣诲姞璁惧淇濆吇")
+    public AjaxResult add(@RequestBody DeviceMaintenanceDto deviceMaintenance) {
         DeviceLedger byId = deviceLedgerService.getById(deviceMaintenance.getDeviceLedgerId());
         deviceMaintenance.setDeviceName(byId.getDeviceName());
         deviceMaintenance.setDeviceModel(byId.getDeviceModel());
         return deviceMaintenanceService.saveDeviceRepair(deviceMaintenance);
     }
 
-    @ApiOperation("鏍规嵁id鏌ヨ璁惧淇濆吇")
+    @Operation(summary = "鏍规嵁id鏌ヨ璁惧淇濆吇")
     @GetMapping("/{id}")
     public AjaxResult detail(@PathVariable Long id) {
         return AjaxResult.success(deviceMaintenanceService.detailById(id));
     }
 
     @PutMapping ()
-    @ApiOperation("淇敼璁惧淇濆吇")
-    public AjaxResult update(@RequestBody DeviceMaintenance deviceMaintenance) {
+    @Operation(summary = "淇敼璁惧淇濆吇")
+    public AjaxResult update(@RequestBody DeviceMaintenanceDto deviceMaintenance) {
         DeviceLedger byId = deviceLedgerService.getById(deviceMaintenance.getDeviceLedgerId());
         deviceMaintenance.setDeviceName(byId.getDeviceName());
         deviceMaintenance.setDeviceModel(byId.getDeviceModel());
@@ -59,14 +57,14 @@
     }
 
     @PostMapping ("maintenance")
-    @ApiOperation("淇敼璁惧淇濆吇")
-    public AjaxResult maintenance(@RequestBody DeviceMaintenance deviceMaintenance) {
+    @Operation(summary = "淇敼璁惧淇濆吇")
+    public AjaxResult maintenance(@RequestBody DeviceMaintenanceDto deviceMaintenance) {
         return deviceMaintenanceService.updateDeviceDeviceMaintenance(deviceMaintenance);
     }
 
 
     @DeleteMapping("/{ids}")
-    @ApiOperation("鍒犻櫎璁惧淇濆吇")
+    @Operation(summary = "鍒犻櫎璁惧淇濆吇")
     public AjaxResult delete(@PathVariable("ids") Long[] ids) {
         boolean b = deviceMaintenanceService.removeBatchByIds(Arrays.asList(ids));
         if (!b) {
@@ -76,7 +74,7 @@
     }
 
     @PostMapping("export")
-    @ApiOperation("瀵煎嚭璁惧淇濆吇")
+    @Operation(summary = "瀵煎嚭璁惧淇濆吇")
     public void export(HttpServletResponse response, Long[] ids) {
         deviceMaintenanceService.export(response, ids);
     }
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java b/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java
index d7da280..d92d334 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java
@@ -5,11 +5,11 @@
 import com.ruoyi.device.pojo.DeviceMaintenanceFile;
 import com.ruoyi.device.service.DeviceMaintenanceFileService;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
@@ -22,7 +22,7 @@
  */
 @RestController
 @RequestMapping("/maintenanceTaskFile")
-@Api(tags = "璁惧淇濆吇闄勪欢")
+@Tag(name = "璁惧淇濆吇闄勪欢")
 public class DeviceMaintenanceFileController {
 
     @Resource
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceRepairController.java b/src/main/java/com/ruoyi/device/controller/DeviceRepairController.java
index 7ac0907..d3c19bb 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceRepairController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceRepairController.java
@@ -4,61 +4,56 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.device.dto.DeviceRepairDto;
 import com.ruoyi.device.pojo.DeviceRepair;
-import com.ruoyi.device.service.IDeviceLedgerService;
 import com.ruoyi.device.service.IDeviceRepairService;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.Arrays;
 
-@Api(tags = "璁惧鎶ヤ慨绠$悊")
+@Tag(name = "璁惧鎶ヤ慨绠$悊")
 @RequestMapping("/device/repair")
 @RestController
+@AllArgsConstructor
 public class DeviceRepairController {
 
-    @Autowired
     private IDeviceRepairService deviceRepairService;
 
-    @Autowired
-    private IDeviceLedgerService deviceLedgerService;
-
-    @ApiOperation("璁惧鎶ヤ慨鍒楄〃")
+    @Operation(summary = "璁惧鎶ヤ慨鍒楄〃")
     @GetMapping("/page")
     public AjaxResult page(Page page , DeviceRepairDto deviceRepairDto) {
         return AjaxResult.success(deviceRepairService.queryPage(page,deviceRepairDto));
     }
 
     @PostMapping()
-    @ApiOperation("娣诲姞璁惧鎶ヤ慨")
-    public AjaxResult add( @RequestBody DeviceRepair deviceRepair) {
-        return deviceRepairService.saveDeviceRepair(deviceRepair);
+    @Operation(summary = "娣诲姞璁惧鎶ヤ慨")
+    public AjaxResult add( @RequestBody DeviceRepairDto deviceRepairDto) {
+        return deviceRepairService.saveDeviceRepair(deviceRepairDto);
     }
 
-    @ApiOperation("鏍规嵁id鏌ヨ璁惧鎶ヤ慨")
+    @Operation(summary = "鏍规嵁id鏌ヨ璁惧鎶ヤ慨")
     @GetMapping("/{id}")
     public AjaxResult detail(@PathVariable Long id) {
-        DeviceRepairDto byId = deviceRepairService.detailById(id);
-        return AjaxResult.success(byId);
+        return AjaxResult.success(deviceRepairService.detailById(id));
     }
 
     @PutMapping ()
-    @ApiOperation("淇敼璁惧鎶ヤ慨")
-    public AjaxResult update( @RequestBody DeviceRepair deviceRepair) {
-        return deviceRepairService.updateDeviceRepair(deviceRepair);
+    @Operation(summary = "淇敼璁惧鎶ヤ慨")
+    public AjaxResult update( @RequestBody DeviceRepairDto deviceRepairDto) {
+        return deviceRepairService.updateDeviceRepair(deviceRepairDto);
     }
 
     @PostMapping ("repair")
-    @ApiOperation("璁惧缁翠慨")
-    public AjaxResult repair( @RequestBody DeviceRepair deviceRepair) {
-        return deviceRepairService.updateDeviceRepair(deviceRepair);
+    @Operation(summary = "璁惧缁翠慨")
+    public AjaxResult repair( @RequestBody DeviceRepairDto deviceRepairDto) {
+        return deviceRepairService.updateDeviceRepair(deviceRepairDto);
     }
 
     @DeleteMapping("/{ids}")
-    @ApiOperation("鍒犻櫎璁惧鎶ヤ慨")
+    @Operation(summary = "鍒犻櫎璁惧鎶ヤ慨")
     public AjaxResult delete(@PathVariable("ids") Long[] ids) {
         boolean b = deviceRepairService.removeBatchByIds(Arrays.asList(ids));
         if (!b) {
@@ -68,7 +63,7 @@
     }
 
     @PostMapping("export")
-    @ApiOperation("瀵煎嚭璁惧鎶ヤ慨")
+    @Operation(summary = "瀵煎嚭璁惧鎶ヤ慨")
     public void export(HttpServletResponse response, Long[] ids) {
         deviceRepairService.export(response, ids);
     }
diff --git a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
index fd8398c..b6f8c27 100644
--- a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
+++ b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
@@ -7,8 +7,9 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -18,39 +19,39 @@
  * @author :yys
  * @date : 2025/12/22 14:58
  */
-@Api(tags = "璁惧淇濆吇瀹氭椂浠诲姟绠$悊")
+@Tag(name = "璁惧淇濆吇瀹氭椂浠诲姟绠$悊")
 @RestController
 @RequestMapping("/deviceMaintenanceTask")
+@AllArgsConstructor
 public class MaintenanceTaskController extends BaseController {
 
 
-    @Autowired
     private MaintenanceTaskService maintenanceTaskService;
 
 
     @GetMapping("/listPage")
-    @ApiOperation(value = "璁惧淇濆吇瀹氭椂浠诲姟鍒楄〃")
+    @Operation(summary = "璁惧淇濆吇瀹氭椂浠诲姟鍒楄〃")
     public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
         return maintenanceTaskService.listPage(page,maintenanceTask);
     }
 
 
     @PostMapping("/add")
-    @ApiOperation(value = "娣诲姞璁惧淇濆吇瀹氭椂浠诲姟")
+    @Operation(summary = "娣诲姞璁惧淇濆吇瀹氭椂浠诲姟")
     @Log(title = "璁惧淇濆吇瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody MaintenanceTask maintenanceTask) {
         return maintenanceTaskService.add(maintenanceTask);
     }
 
     @PostMapping("/update")
-    @ApiOperation(value = "淇敼璁惧淇濆吇瀹氭椂浠诲姟")
+    @Operation(summary = "淇敼璁惧淇濆吇瀹氭椂浠诲姟")
     @Log(title = "璁惧淇濆吇瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody MaintenanceTask maintenanceTask) {
         return maintenanceTaskService.updateByMaintenanceTaskId(maintenanceTask);
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation(value = "鍒犻櫎璁惧淇濆吇瀹氭椂浠诲姟")
+    @Operation(summary = "鍒犻櫎璁惧淇濆吇瀹氭椂浠诲姟")
     @Log(title = "璁惧淇濆吇瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         return maintenanceTaskService.delete(ids);
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceDefectRecordDto.java b/src/main/java/com/ruoyi/device/dto/DeviceDefectRecordDto.java
index aa1e0aa..e7d1602 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceDefectRecordDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceDefectRecordDto.java
@@ -1,14 +1,14 @@
 package com.ruoyi.device.dto;
 
 import com.ruoyi.device.pojo.DeviceDefectRecord;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 @Data
 public class DeviceDefectRecordDto extends DeviceDefectRecord {
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     private String deviceName;
 
-    @ApiModelProperty("璁惧鍨嬪彿")
+    @Schema(description = "璁惧鍨嬪彿")
     private String deviceModel;
 }
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java b/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
index 75d9250..79e0aff 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
@@ -5,7 +5,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -39,13 +39,13 @@
     /**
      * 璁惧鍝佺墝
      */
-    @ApiModelProperty("璁惧鍝佺墝")
+    @Schema(description = "璁惧鍝佺墝")
     private String deviceBrand;
 
     /**
      * 瀛樻斁浣嶇疆
      */
-    @ApiModelProperty("瀛樻斁浣嶇疆")
+    @Schema(description = "瀛樻斁浣嶇疆")
     private String storageLocation;
 
 
@@ -115,34 +115,34 @@
      */
     private Long tenantId;
 
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     private String status;
 
-    @ApiModelProperty("璁″垝杩愯鏃堕棿")
+    @Schema(description = "璁″垝杩愯鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate planRuntimeTime;
 
-    @ApiModelProperty("寮�濮嬭繍琛屾椂闂�")
+    @Schema(description = "寮�濮嬭繍琛屾椂闂�")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime startRuntimeTime;
 
-    @ApiModelProperty("缁撴潫杩愯鏃堕棿")
+    @Schema(description = "缁撴潫杩愯鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime endRuntimeTime;
 
-    @ApiModelProperty("杩愯鏃堕暱")
+    @Schema(description = "杩愯鏃堕暱")
     private String runtimeDuration;
 
 
-    @ApiModelProperty("鏄惁鎶樻棫 1-鏄� 2-鍚�")
+    @Schema(description = "鏄惁鎶樻棫 1-鏄� 2-鍚�")
     private Integer isDepr;
 
-    @ApiModelProperty("姣忓勾鎶樻棫閲戦")
+    @Schema(description = "姣忓勾鎶樻棫閲戦")
     private BigDecimal annualDepreciationAmount;
 
-    @ApiModelProperty("璁惧绫诲瀷")
+    @Schema(description = "璁惧绫诲瀷")
     private String type;
 }
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java b/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
index 522a324..127d82b 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
@@ -2,68 +2,56 @@
 
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.annotations.ApiModelProperty;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.device.pojo.DeviceMaintenance;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 @Data
-public class DeviceMaintenanceDto {
+public class DeviceMaintenanceDto extends DeviceMaintenance {
 
 
-    @ApiModelProperty("璁惧淇濆吇id")
+    @Schema(description = "璁惧淇濆吇id")
     private Long id;
 
-    @ApiModelProperty("璁惧鍙拌处id")
+    @Schema(description = "璁惧鍙拌处id")
     private Long deviceLedgerId;
 
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     private String deviceName;
 
-    @ApiModelProperty("瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     private String deviceModel;
 
-    @ApiModelProperty("璁″垝淇濆吇鏃ユ湡")
-    private String maintenancePlanTimeReq;
-
-    @ApiModelProperty("璁″垝淇濆吇鏃ユ湡")
-    private String maintenancePlanTime;
-
-    @ApiModelProperty("瀹為檯淇濆吇浜�")
+    @Schema(description = "瀹為檯淇濆吇浜�")
     private String maintenanceActuallyName;
 
-    @ApiModelProperty("瀹為檯淇濆吇鏃ユ湡")
-    private String maintenanceActuallyTime;
-
-    @ApiModelProperty("瀹為檯淇濆吇鏃ユ湡")
-    private String maintenanceActuallyTimeReq;
-
-    @ApiModelProperty("淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
+    @Schema(description = "淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
     private String maintenanceResult;
 
-    @ApiModelProperty("鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
+    @Schema(description = "鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
     private Integer status;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
+    @Schema(description = "鍒涘缓鏃堕棿")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.UPDATE)
+    @Schema(description = "鏇存柊鏃堕棿")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
-    @TableField(fill = FieldFill.INSERT)
-    private String createUser;
+    @Schema(description = "鏇存柊浜�")
+    private String updateUserName;
 
-    @ApiModelProperty("鏇存柊浜�")
-    @TableField(fill = FieldFill.UPDATE)
-    private String updateUser;
-
-    @ApiModelProperty("绉熸埛id")
-    @TableField(fill = FieldFill.INSERT)
+    @Schema(description = "绉熸埛id")
     private Long tenantId;
 
-    @ApiModelProperty("鍒涘缓浜哄悕绉�")
+    @Schema(description = "鍒涘缓浜哄悕绉�")
     private String createUserName;
+
+    @Schema(description = "淇濆吇鍥剧墖")
+    private List<StorageBlobDTO> storageBlobDTOs;
+
 }
+
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java b/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
index 92cfe8c..12def24 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
@@ -1,74 +1,20 @@
 package com.ruoyi.device.dto;
 
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.annotations.ApiModelProperty;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.device.pojo.DeviceRepair;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import java.time.LocalDateTime;
-import java.util.Date;
+import java.util.List;
 
 @Data
-public class DeviceRepairDto {
+public class DeviceRepairDto extends DeviceRepair {
 
-    @ApiModelProperty("璁惧鎶ヤ慨id")
-    private Long id;
-
-    @ApiModelProperty("璁惧鍙拌处id")
-    private Long deviceLedgerId;
-
-    @ApiModelProperty("璁惧鍚嶇О")
-    private String deviceName;
-
-    @ApiModelProperty("璁惧鍨嬪彿")
-    private String deviceModel;
-
-    @ApiModelProperty("鎶ヤ慨鏃堕棿")
-    private Date repairTime;
-    
+    @Schema(description = "鎶ヤ慨鏃堕棿瀛楃涓�")
     private String repairTimeStr;
 
-    @ApiModelProperty("鎶ヤ慨浜�")
-    private String repairName;
-
-    @ApiModelProperty("鎶ヤ慨鍐呭")
-    private String remark;
-
-    @ApiModelProperty("缁翠慨浜�")
-    private String maintenanceName;
-
-    @ApiModelProperty("缁翠慨鏃堕棿")
-    private Date maintenanceTime;
-
+    @Schema(description = "缁翠慨鏃堕棿瀛楃涓�")
     private String maintenanceTimeStr;
 
-    @ApiModelProperty("缁翠慨缁撴灉")
-    private String maintenanceResult;
-
-    @ApiModelProperty("鐘舵��")
-    private Integer status;
-
-    @ApiModelProperty("鍒涘缓鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    @ApiModelProperty("鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.UPDATE)
-    private LocalDateTime updateTime;
-
-    @ApiModelProperty("鍒涘缓浜�")
-    @TableField(fill = FieldFill.INSERT)
-    private String createUser;
-
-    @ApiModelProperty("鏇存柊浜�")
-    @TableField(fill = FieldFill.UPDATE)
-    private String updateUser;
-
-    @ApiModelProperty("绉熸埛id")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-
+    private List<StorageBlobDTO> storageBlobDTOs;
 }
-
diff --git a/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java b/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java
index 0067da9..a9eafa8 100644
--- a/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java
+++ b/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java
@@ -1,9 +1,14 @@
 package com.ruoyi.device.execl;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Date;
 
 @Data
 public class DeviceLedgerExeclDto {
@@ -14,6 +19,18 @@
      */
     @Excel(name = "璁惧鍚嶇О" ,sort = 1)
     private String deviceName;
+
+    /**
+     * 璁惧绫诲瀷
+     */
+    @Excel(name = "璁惧绫诲瀷",sort = 0,combo = {"鐢熶骇璁惧","鍔炲叕璁惧","妫�鏌ヨ澶�","杩愯緭璁惧","鍏朵粬璁惧"})
+    private String type;
+
+    @Schema(description = "璁″垝杩愯鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "璁″垝杩愯鏃堕棿",sort = 10,dateFormat = "yyyy-MM-dd")
+    private Date planRuntimeTime;
 
     /**
      * 瑙勬牸鍨嬪彿
@@ -36,8 +53,8 @@
     /**
      * 鏁伴噺
      */
-    @Excel(name = "鏁伴噺",sort = 5)
-    private BigDecimal number;
+    @Excel(name = "鏁伴噺",sort = 5, type = Excel.Type.EXPORT)
+    private BigDecimal number = BigDecimal.ONE;
 
     /**
      * 鍚◣鍗曚环
@@ -48,7 +65,7 @@
     /**
      * 鍚◣鎬讳环
      */
-    @Excel(name = "鍚◣鎬讳环",sort = 7)
+    @Excel(name = "鍚◣鎬讳环",sort = 7, type = Excel.Type.EXPORT)
     private BigDecimal taxIncludingPriceTotal;
 
     /**
@@ -60,17 +77,8 @@
     /**
      * 涓嶅惈绋庢�讳环
      */
-    @Excel(name = "涓嶅惈绋庢�讳环",sort = 9)
+    @Excel(name = "涓嶅惈绋庢�讳环",sort = 9, type = Excel.Type.EXPORT)
     private BigDecimal unTaxIncludingPriceTotal;
-//
-//    /**
-//     * 褰曞叆鏃堕棿
-//     *
-//     */
-//    @Excel(name = "褰曞叆鏃堕棿",sort = 10)
-//    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-//    private LocalDateTime createTime;
-
 
 
     /**
diff --git a/src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java b/src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java
index 2f0e29c..809e4e6 100644
--- a/src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java
+++ b/src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java
@@ -1,7 +1,7 @@
 package com.ruoyi.device.execl;
 
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -13,39 +13,43 @@
 
 
 
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "璁惧鍚嶇О")
     private String deviceName;
 
     @Excel(name = "瑙勬牸鍨嬪彿")
-    @ApiModelProperty("瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     private String deviceModel;
 
+    @Schema(description = "椤圭洰")
+    @Excel(name = "椤圭洰")
+    private String machineryCategory;
+
     @Excel(name = "璁″垝淇濆吇鏃ユ湡", dateFormat = "yyyy-MM-dd HH:mm:ss", width = 30)
-    @ApiModelProperty("璁″垝淇濆吇鏃ユ湡")
+    @Schema(description = "璁″垝淇濆吇鏃ユ湡")
     private Date maintenancePlanTime;
 
-    @ApiModelProperty("瀹為檯淇濆吇浜�")
+    @Schema(description = "瀹為檯淇濆吇浜�")
     @Excel(name = "瀹為檯淇濆吇浜�")
     private String maintenanceActuallyName;
 
-    @ApiModelProperty("瀹為檯淇濆吇鏃ユ湡")
+    @Schema(description = "瀹為檯淇濆吇鏃ユ湡")
     @Excel(name = "瀹為檯淇濆吇鏃ユ湡", dateFormat = "yyyy-MM-dd HH:mm:ss", width = 30)
     private LocalDateTime maintenanceActuallyTime;
 
-    @ApiModelProperty("淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
+    @Schema(description = "淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
     @Excel(name = "淇濆吇缁撴灉")
     private String maintenanceResult;
 
-    @ApiModelProperty("鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
+    @Schema(description = "鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
     @Excel(name = "鐘舵��")
     private String status;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @Excel(name = "褰曞叆鏃堕棿", dateFormat = "yyyy-MM-dd HH:mm:ss", width = 30)
     private Date createTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
 //    @Excel(name = "褰曞叆浜�")
     private String createUser;
 
diff --git a/src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java b/src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java
index 9d16e4d..c782da2 100644
--- a/src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java
+++ b/src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java
@@ -2,7 +2,7 @@
 
 
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -11,48 +11,52 @@
 @Data
 public class DeviceRepairExeclDto {
 
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "璁惧鍚嶇О")
     private String deviceName;
 
-    @ApiModelProperty("璁惧鍨嬪彿")
+    @Schema(description = "璁惧鍨嬪彿")
     @Excel(name = "璁惧鍨嬪彿")
     private String deviceModel;
 
-    @ApiModelProperty("鎶ヤ慨鏃堕棿")
+    @Schema(description = "椤圭洰")
+    @Excel(name = "椤圭洰")
+    private String machineryCategory;
+
+    @Schema(description = "鎶ヤ慨鏃堕棿")
     @Excel(name = "鎶ヤ慨鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
     private Date repairTime;
 
-    @ApiModelProperty("鎶ヤ慨浜�")
+    @Schema(description = "鎶ヤ慨浜�")
     @Excel(name = "鎶ヤ慨浜�")
     private String repairName;
 
-    @ApiModelProperty("鎶ヤ慨鍐呭")
+    @Schema(description = "鎶ヤ慨鍐呭")
     @Excel(name = "鎶ヤ慨鍐呭")
     private String remark;
 
-    @ApiModelProperty("缁翠慨浜�")
+    @Schema(description = "缁翠慨浜�")
     @Excel(name = "缁翠慨浜�")
     private String maintenanceName;
 
-    @ApiModelProperty("缁翠慨鏃堕棿")
+    @Schema(description = "缁翠慨鏃堕棿")
     @Excel(name = "缁翠慨鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
     private LocalDateTime maintenanceTime;
 
-    @ApiModelProperty("缁翠慨缁撴灉")
+    @Schema(description = "缁翠慨缁撴灉")
     @Excel(name = "缁翠慨缁撴灉")
     private String maintenanceResult;
 
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     @Excel(name = "鐘舵��")
     private String statusStr;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @Excel(name = "褰曞叆鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
     private LocalDateTime createTime;
 
 //    @Excel(name = "褰曞叆浜�")
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     private String createUser;
 
 
diff --git a/src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java b/src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java
index 1e2c049..0fd6c72 100644
--- a/src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java
+++ b/src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java
@@ -7,6 +7,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.device.dto.DeviceMaintenanceDto;
 import com.ruoyi.device.pojo.DeviceMaintenance;
+import com.ruoyi.device.vo.DeviceMaintenanceVo;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
@@ -16,7 +17,7 @@
 
     IPage<DeviceMaintenanceDto> queryPage(Page page, DeviceMaintenanceDto deviceMaintenanceDto);
 
-    DeviceMaintenanceDto detailById(Long id);
+    DeviceMaintenanceVo detailById(Long id);
 
     @InterceptorIgnore(tenantLine = "true")
     List<DeviceMaintenance> list1(Long id);
diff --git a/src/main/java/com/ruoyi/device/mapper/DeviceRepairMapper.java b/src/main/java/com/ruoyi/device/mapper/DeviceRepairMapper.java
index cbfcbcd..52af77a 100644
--- a/src/main/java/com/ruoyi/device/mapper/DeviceRepairMapper.java
+++ b/src/main/java/com/ruoyi/device/mapper/DeviceRepairMapper.java
@@ -5,12 +5,13 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.device.dto.DeviceRepairDto;
 import com.ruoyi.device.pojo.DeviceRepair;
+import com.ruoyi.device.vo.DeviceRepairVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 @Mapper
 public interface DeviceRepairMapper extends BaseMapper<DeviceRepair> {
-    IPage<DeviceRepairDto> queryPage(Page page, @Param("deviceRepairDto") DeviceRepairDto deviceRepairDto);
+    IPage<DeviceRepairVo> queryPage(Page page, @Param("deviceRepairDto") DeviceRepairDto deviceRepairDto);
 
-    DeviceRepairDto detailById(Long id);
+    DeviceRepairVo detailById(Long id);
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceDefectRecord.java b/src/main/java/com/ruoyi/device/pojo/DeviceDefectRecord.java
index 966b8ae..f188b35 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceDefectRecord.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceDefectRecord.java
@@ -4,7 +4,7 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -13,39 +13,42 @@
 @Data
 @TableName("device_defect_record")
 public class DeviceDefectRecord {
-    @ApiModelProperty("璁惧缂洪櫡璁板綍id")
+    @Schema(description = "璁惧缂洪櫡璁板綍id")
     private Long id;
-    @ApiModelProperty("璁惧鍙拌处id")
+    @Schema(description = "璁惧鍙拌处id")
     private Long deviceLedgerId;
-    @ApiModelProperty("缂洪櫡鎻忚堪")
+    @Schema(description = "缂洪櫡鎻忚堪")
     private String defectDescription;
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     private String status;
-    @ApiModelProperty("娑堥櫎鏃堕棿")
+    @Schema(description = "娑堥櫎鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime eliminateTime;
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java b/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java
index f8c9e53..61239ac 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java
@@ -4,8 +4,7 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,7 +17,7 @@
  */
 @Data
 @TableName("device_ledger")
-@ApiModel
+@Schema
 public class DeviceLedger {
 
     /**
@@ -30,25 +29,25 @@
     /**
      * 璁惧鍚嶇О
      */
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     private String deviceName;
 
     /**
      * 瑙勬牸鍨嬪彿
      */
-    @ApiModelProperty("瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     private String deviceModel;
 
     /**
      * 璁惧鍝佺墝
      */
-    @ApiModelProperty("璁惧鍝佺墝")
+    @Schema(description = "璁惧鍝佺墝")
     private String deviceBrand;
 
     /**
      * 瀛樻斁浣嶇疆
      */
-    @ApiModelProperty("瀛樻斁浣嶇疆")
+    @Schema(description = "瀛樻斁浣嶇疆")
     private String storageLocation;
 
     /**
@@ -122,41 +121,44 @@
 
     /* ***************************     杩愯绠$悊        ***************************   */
 
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     private String status;
 
-    @ApiModelProperty("璁″垝杩愯鏃堕棿")
+    @Schema(description = "璁″垝杩愯鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate planRuntimeTime;
 
-    @ApiModelProperty("寮�濮嬭繍琛屾椂闂�")
+    @Schema(description = "寮�濮嬭繍琛屾椂闂�")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime startRuntimeTime;
 
-    @ApiModelProperty("缁撴潫杩愯鏃堕棿")
+    @Schema(description = "缁撴潫杩愯鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime endRuntimeTime;
 
-    @ApiModelProperty("杩愯鏃堕暱")
+    @Schema(description = "杩愯鏃堕暱")
     private String runtimeDuration;
 
-    @ApiModelProperty("鏄惁鎶樻棫 1-鏄� 2-鍚�")
+    @Schema(description = "鏄惁鎶樻棫 1-鏄� 2-鍚�")
     private Integer isDepr;
 
-    @ApiModelProperty("姣忓勾鎶樻棫閲戦")
+    @Schema(description = "姣忓勾鎶樻棫閲戦")
     private BigDecimal annualDepreciationAmount;
 
     @TableField(exist = false)
-    @ApiModelProperty("绱鎶樻棫")
+    @Schema(description = "绱鎶樻棫")
     private BigDecimal deprAmount;
 
     @TableField(exist = false)
-    @ApiModelProperty("鍑�鍊�")
+    @Schema(description = "鍑�鍊�")
     private BigDecimal netValue;
 
-    @ApiModelProperty("璁惧绫诲瀷")
+    @Schema(description = "璁惧绫诲瀷")
     private String type;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
index a9368b0..b635e5f 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
@@ -4,84 +4,103 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 @Data
 @TableName("device_maintenance")
-@ApiModel("璁惧淇濆吇璁板綍")
+@Schema(name = "璁惧淇濆吇璁板綍")
 public class DeviceMaintenance {
 
-    @ApiModelProperty("璁惧淇濆吇id")
+    @Schema(description = "璁惧淇濆吇id")
     private Long id;
 
-    @ApiModelProperty("璁惧鍙拌处id")
+    @Schema(description = "璁惧鍙拌处id")
     private Long deviceLedgerId;
 
-    @ApiModelProperty("淇濆吇浠诲姟id")
+    @Schema(description = "淇濆吇浠诲姟id")
     private Long maintenanceTaskId;
 
-    @ApiModelProperty(value = "棰戞")
+    @Schema(description = "棰戞")
     private String frequencyType;
 
-    @ApiModelProperty(value = "棰戞璇︽儏")
+    @Schema(description = "棰戞璇︽儏")
     private String frequencyDetail;
 
-    @ApiModelProperty(value = "涓嬫鎵ц鏃堕棿")
+    @Schema(description = "涓嬫鎵ц鏃堕棿")
     private LocalDateTime nextExecutionTime;
 
-    @ApiModelProperty(value = "鏈�鍚庢墽琛屾椂闂�")
+    @Schema(description = "鏈�鍚庢墽琛屾椂闂�")
     private LocalDateTime lastExecutionTime;
+
+    @Schema(description = "璁惧椤圭洰")
+    private String machineryCategory;
 
 
     private String deviceName;
 
     private String deviceModel;
 
-    @ApiModelProperty("璁″垝淇濆吇鏃ユ湡")
+    @Schema(description = "璁″垝淇濆吇鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime maintenancePlanTime;
 
-    @ApiModelProperty("瀹為檯淇濆吇浜�")
+    @Schema(description = "瀹為檯淇濆吇浜�")
     private String maintenanceActuallyName;
 
-    @ApiModelProperty("瀹為檯淇濆吇鏃ユ湡")
+    @Schema(description = "瀹為檯淇濆吇鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime maintenanceActuallyTime;
 
-    @ApiModelProperty("淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
+    @Schema(description = "淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
     private String maintenanceResult;
 
-    @ApiModelProperty("鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
+    @Schema(description = "鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
     private Integer status;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @Schema(description = "棰嗙敤澶囦欢ids")
+    private String sparePartsIds;
+
+    @Schema(description = "浣跨敤澶囦欢鍒楄〃")
+    @TableField(exist = false)
+    private List<SparePartUse> sparePartsUseList;
+
+    @Data
+    public static class SparePartUse {
+        private Long id;
+        private Integer quantity;
+    }
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java
index 59226e1..a6ae8ae 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,7 +22,7 @@
 @Getter
 @Setter
 @TableName("device_maintenance_file")
-@ApiModel(value = "DeviceMaintenanceFile瀵硅薄", description = "璁惧淇濆吇璁板綍闄勪欢")
+@Schema(name = "DeviceMaintenanceFile瀵硅薄", description = "璁惧淇濆吇璁板綍闄勪欢")
 public class DeviceMaintenanceFile implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -31,35 +30,38 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty("鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty("鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private Integer fileSize;
 
-    @ApiModelProperty("璁惧淇濆吇璁板綍ID")
+    @Schema(description = "璁惧淇濆吇璁板綍ID")
     private Integer deviceMaintenanceId;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
 
-    @ApiModelProperty("绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java b/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
index a567366..9db134e 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
@@ -4,73 +4,92 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.List;
 
 @Data
 @TableName("device_repair")
 public class DeviceRepair {
 
-    @ApiModelProperty("璁惧鎶ヤ慨id")
+    @Schema(description = "璁惧鎶ヤ慨id")
     private Long id;
 
-    @ApiModelProperty("璁惧鍙拌处id")
+    @Schema(description = "璁惧鍙拌处id")
     private Long deviceLedgerId;
 
     private String deviceName;
 
     private String deviceModel;
 
-    @ApiModelProperty("鎶ヤ慨鏃堕棿")
+    @Schema(description = "鎶ヤ慨鏃堕棿")
     private Date repairTime;
 
-    @ApiModelProperty("鎶ヤ慨浜�")
+    @Schema(description = "鎶ヤ慨浜�")
     private String repairName;
 
-    @ApiModelProperty("鎶ヤ慨鍐呭")
+    @Schema(description = "鎶ヤ慨鍐呭")
     private String remark;
 
-    @ApiModelProperty("缁翠慨浜�")
+    @Schema(description = "璁惧椤圭洰")
+    private String machineryCategory;
+
+
+    @Schema(description = "缁翠慨浜�")
     private String maintenanceName;
 
-    @ApiModelProperty("缁翠慨鏃堕棿")
+    @Schema(description = "缁翠慨鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime maintenanceTime;
 
-    @ApiModelProperty("缁翠慨缁撴灉")
+    @Schema(description = "缁翠慨缁撴灉")
     private String maintenanceResult;
 
-    @ApiModelProperty("鐘舵�� 0 寰呯淮淇� 1瀹岀粨 2 澶辫触")
+    @Schema(description = "鐘舵�� 0 寰呯淮淇� 1瀹岀粨 2 澶辫触")
     private Integer status;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+    @Schema(description = "棰嗙敤澶囦欢ids")
+    private String sparePartsIds;
 
+    @Schema(description = "浣跨敤澶囦欢鍒楄〃")
+    @TableField(exist = false)
+    private List<SparePartUse> sparePartsUseList;
+
+    @Data
+    public static class SparePartUse {
+        private Long id;
+        private Integer quantity;
+    }
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
index a6f4432..0edfc7b 100644
--- a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
+++ b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -1,13 +1,13 @@
 package com.ruoyi.device.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,13 +19,13 @@
  * @date : 2025/9/19 10:27
  */
 @Data
-@ApiModel
+@Schema
 @TableName("maintenance_task")
 public class MaintenanceTask {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     private String deviceModel;
 
     /**
@@ -34,76 +34,79 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "淇濆吇浠诲姟鍚嶇О")
     private String taskName;
 
-    @ApiModelProperty(value = "璁惧id")
+    @Schema(description = "璁惧id")
     private Long taskId;
 
-    @ApiModelProperty(value = "棰戞")
+    @Schema(description = "棰戞")
     @Excel(name = "棰戞")
     private String frequencyType;
 
-    @ApiModelProperty(value = "棰戞璇︽儏")
+    @Schema(description = "棰戞璇︽儏")
     @Excel(name = "寮�濮嬫棩鏈熶笌鏃堕棿")
     private String frequencyDetail;
 
-    @ApiModelProperty(value = "涓嬫鎵ц鏃堕棿")
+    @Schema(description = "涓嬫鎵ц鏃堕棿")
     private LocalDateTime nextExecutionTime;
 
-    @ApiModelProperty(value = "鏈�鍚庢墽琛屾椂闂�")
+    @Schema(description = "鏈�鍚庢墽琛屾椂闂�")
     private LocalDateTime lastExecutionTime;
 
-    @ApiModelProperty(value = "鏄惁婵�娲�")
+    @Schema(description = "鏄惁婵�娲�")
     private boolean isActive;
 
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     @Excel(name = "澶囨敞")
     private String remarks;
 
-    @ApiModelProperty(value = "褰曞叆浜篿d")
+    @Schema(description = "褰曞叆浜篿d")
     private Long registrantId;
 
-    @ApiModelProperty(value = "褰曞叆浜�")
+    @Schema(description = "褰曞叆浜�")
     @Excel(name = "褰曞叆浜�")
     private String registrant;
 
-    @ApiModelProperty(value = "褰曞叆鏃ユ湡")
+    @Schema(description = "褰曞叆鏃ユ湡")
     @Excel(name = "褰曞叆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate registrationDate;
 
-    @ApiModelProperty(value = "鐘舵��")
+    @Schema(description = "鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @Schema(description = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
     @TableField(exist = false)
     private String dateStr;
 
-    @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+    @Schema(description = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+    @Schema(description = "璁板綍鍒涘缓鏃堕棿")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
 //    @JsonFormat(pattern = "yyyy-MM-dd")
 //    @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+    @Schema(description = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+    @Schema(description = "璁板綍鏈�鍚庢洿鏂版椂闂�")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java b/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java
index 0d6493e..d34ea65 100644
--- a/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java
+++ b/src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java
@@ -8,7 +8,7 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 public interface IDeviceLedgerService  extends IService<DeviceLedger> {
diff --git a/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java b/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java
index 82db913..e5a4080 100644
--- a/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java
+++ b/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java
@@ -5,19 +5,20 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.device.dto.DeviceMaintenanceDto;
 import com.ruoyi.device.pojo.DeviceMaintenance;
+import com.ruoyi.device.vo.DeviceMaintenanceVo;
 import com.ruoyi.framework.web.domain.AjaxResult;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 public interface IDeviceMaintenanceService extends IService<DeviceMaintenance> {
 
     IPage<DeviceMaintenanceDto> queryPage(Page page, DeviceMaintenanceDto deviceMaintenanceDto);
 
-    AjaxResult saveDeviceRepair(DeviceMaintenance deviceMaintenance);
+    AjaxResult saveDeviceRepair(DeviceMaintenanceDto deviceMaintenance);
 
-    AjaxResult updateDeviceDeviceMaintenance(DeviceMaintenance deviceMaintenance);
+    AjaxResult updateDeviceDeviceMaintenance(DeviceMaintenanceDto deviceMaintenance);
 
     void export(HttpServletResponse response, Long[] ids);
 
-    DeviceMaintenanceDto detailById(Long id);
+    DeviceMaintenanceVo detailById(Long id);
 }
diff --git a/src/main/java/com/ruoyi/device/service/IDeviceRepairService.java b/src/main/java/com/ruoyi/device/service/IDeviceRepairService.java
index 5877ffd..8d20acd 100644
--- a/src/main/java/com/ruoyi/device/service/IDeviceRepairService.java
+++ b/src/main/java/com/ruoyi/device/service/IDeviceRepairService.java
@@ -5,20 +5,21 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.device.dto.DeviceRepairDto;
 import com.ruoyi.device.pojo.DeviceRepair;
+import com.ruoyi.device.vo.DeviceRepairVo;
 import com.ruoyi.framework.web.domain.AjaxResult;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 
 public interface IDeviceRepairService extends IService<DeviceRepair> {
 
-    IPage<DeviceRepairDto> queryPage(Page page, DeviceRepairDto deviceRepairDto);
+    IPage<DeviceRepairVo> queryPage(Page page, DeviceRepairDto deviceRepairDto);
 
-    AjaxResult saveDeviceRepair(DeviceRepair deviceRepair);
+    AjaxResult saveDeviceRepair(DeviceRepairDto deviceRepairDto);
 
-    AjaxResult updateDeviceRepair(DeviceRepair deviceRepair);
+    AjaxResult updateDeviceRepair(DeviceRepairDto deviceRepairDto);
 
     void export(HttpServletResponse response, Long[] ids);
 
-    DeviceRepairDto detailById(Long id);
+    DeviceRepairVo detailById(Long id);
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java
index 10c4f5f..3741de4 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java
@@ -10,7 +10,7 @@
 import com.ruoyi.device.pojo.DeviceDefectRecord;
 import com.ruoyi.device.pojo.DeviceRepair;
 import com.ruoyi.device.service.DeviceDefectRecordService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -19,12 +19,10 @@
 
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class DeviceDefectRecordServiceImpl extends ServiceImpl<DeviceDefectRecordMapper, DeviceDefectRecord> implements DeviceDefectRecordService {
-    @Autowired
-    private DeviceDefectRecordMapper deviceDefectRecordMapper;
-
-    @Autowired
-    private DeviceRepairMapper deviceRepairMapper;
+    private final DeviceDefectRecordMapper deviceDefectRecordMapper;
+    private final DeviceRepairMapper deviceRepairMapper;
 
     @Override
     public IPage<DeviceDefectRecordDto> listPage(Page page, DeviceDefectRecordDto deviceDefectRecordDto) {
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
index b614149..b4c5d65 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -15,27 +16,26 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
-import lombok.AllArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 @Slf4j
 public class DeviceLedgerServiceImpl  extends ServiceImpl<DeviceLedgerMapper, DeviceLedger> implements IDeviceLedgerService {
 
-    @Autowired
-    private DeviceLedgerMapper deviceLedgerMapper;
-    @Autowired
-    private SysUserMapper sysUserMapper;
+    private final DeviceLedgerMapper deviceLedgerMapper;
+    private final SysUserMapper sysUserMapper;
 
     @Override
     public IPage<DeviceLedgerDto> queryPage(Page page, DeviceLedgerDto deviceLedger) {
@@ -112,6 +112,11 @@
                 deviceLedger.setCreateUser(SecurityUtils.getUserId().intValue());
             }
             BeanUtils.copyProperties(c,deviceLedger);
+            // 閫氳繃鍚◣鍗曚环銆佹暟閲忋�佺◣鐜囪绠楀惈绋庢�讳环锛屼笉鍚◣鎬讳环
+            deviceLedger.setTaxIncludingPriceTotal(c.getTaxIncludingPriceUnit());
+            deviceLedger.setNumber(BigDecimal.ONE);
+            deviceLedger.setPlanRuntimeTime(DateUtils.toLocalDate(c.getPlanRuntimeTime()));
+            deviceLedger.setUnTaxIncludingPriceTotal(deviceLedger.getTaxIncludingPriceTotal().divide(BigDecimal.ONE.add(c.getTaxRate()),2, RoundingMode.HALF_UP));
             deviceLedgerMapper.insert(deviceLedger);
         });
 
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
index 6e90b28..fbf03ad 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
@@ -4,6 +4,8 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.device.dto.DeviceMaintenanceDto;
@@ -11,22 +13,32 @@
 import com.ruoyi.device.mapper.DeviceMaintenanceMapper;
 import com.ruoyi.device.pojo.DeviceMaintenance;
 import com.ruoyi.device.service.IDeviceMaintenanceService;
+import com.ruoyi.device.vo.DeviceMaintenanceVo;
+import com.ruoyi.device.vo.DeviceRepairVo;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper;
+import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
+import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord;
+import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 
 
 @Service
+@RequiredArgsConstructor
 public class DeviceMaintenanceServiceImpl extends ServiceImpl<DeviceMaintenanceMapper, DeviceMaintenance> implements IDeviceMaintenanceService {
 
-
-
-    @Autowired
-    private DeviceMaintenanceMapper deviceMaintenanceMapper;
+    private final DeviceMaintenanceMapper deviceMaintenanceMapper;
+    private final SparePartsMapper sparePartsMapper;
+    private final SparePartsRequisitionRecordService sparePartsRequisitionRecordService;
+    private final FileUtil fileUtil;
 
     @Override
     public IPage<DeviceMaintenanceDto> queryPage(Page page, DeviceMaintenanceDto deviceMaintenanceDto) {
@@ -35,17 +47,57 @@
     }
 
     @Override
-    public AjaxResult saveDeviceRepair(DeviceMaintenance deviceMaintenance) {
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult saveDeviceRepair(DeviceMaintenanceDto deviceMaintenance) {
         boolean save = this.save(deviceMaintenance);
         if (save){
+            // 澶勭悊鍥剧墖涓婁紶
+            fileUtil.saveStorageAttachmentByRecordTypeAndRecordId("file", RecordTypeEnum.DEVICE_MAINTENANCE, deviceMaintenance.getId(), deviceMaintenance.getStorageBlobDTOs());
             return AjaxResult.success();
         }
         return AjaxResult.error();
     }
 
     @Override
-    public AjaxResult updateDeviceDeviceMaintenance(DeviceMaintenance deviceMaintenance) {
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult updateDeviceDeviceMaintenance(DeviceMaintenanceDto deviceMaintenance) {
+        DeviceMaintenance oldDeviceMaintenance = this.getById(deviceMaintenance.getId());
+        // 澶勭悊澶囦欢浣跨敤鎯呭喌
+        if (com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(deviceMaintenance.getSparePartsUseList())) {
+            List<Long> sparePartIds = new ArrayList<>();
+            for (DeviceMaintenance.SparePartUse sparePartUse : deviceMaintenance.getSparePartsUseList()) {
+                // 鑾峰彇澶囦欢淇℃伅
+                SpareParts spareParts = sparePartsMapper.selectById(sparePartUse.getId());
+                if (spareParts != null) {
+                    // 妫�鏌ユ暟閲忔槸鍚﹁冻澶�
+                    if (spareParts.getQuantity().compareTo(new BigDecimal(sparePartUse.getQuantity())) >= 0) {
+                        // 鏇存柊鏁伴噺
+                        spareParts.setQuantity(spareParts.getQuantity().subtract(new BigDecimal(sparePartUse.getQuantity())));
+                        sparePartsMapper.updateById(spareParts);
+                        sparePartIds.add(sparePartUse.getId());
+
+                        // 鍒涘缓澶囦欢棰嗙敤璁板綍
+                        SparePartsRequisitionRecord record = new SparePartsRequisitionRecord();
+                        record.setSourceType(1); // 1 淇濆吇
+                        record.setSourceId(deviceMaintenance.getId());
+                        record.setDeviceLedgerId(oldDeviceMaintenance.getDeviceLedgerId());
+                        record.setSparePartsId(sparePartUse.getId());
+                        record.setQuantity(sparePartUse.getQuantity());
+                        sparePartsRequisitionRecordService.save(record);
+                    } else {
+                        return AjaxResult.error("澶囦欢 " + spareParts.getName() + " 鏁伴噺涓嶈冻");
+                    }
+                }
+            }
+            // 鏇存柊澶囦欢IDs瀛楁
+            if (!sparePartIds.isEmpty()) {
+                deviceMaintenance.setSparePartsIds(StringUtils.join(sparePartIds, ","));
+            }
+        }
+
         if (this.updateById(deviceMaintenance)) {
+            // 澶勭悊鍥剧墖涓婁紶
+            fileUtil.saveStorageAttachmentByRecordTypeAndRecordId("file", RecordTypeEnum.DEVICE_MAINTENANCE, deviceMaintenance.getId(), deviceMaintenance.getStorageBlobDTOs());
             return AjaxResult.success();
         }
         return AjaxResult.error();
@@ -67,8 +119,9 @@
     }
 
     @Override
-    public DeviceMaintenanceDto detailById(Long id) {
-
-        return deviceMaintenanceMapper.detailById(id);
+    public DeviceMaintenanceVo detailById(Long id) {
+        DeviceMaintenanceVo vo = deviceMaintenanceMapper.detailById(id);
+        vo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.DEVICE_MAINTENANCE, id));
+        return vo;
     }
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
index feab01b..897e569 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
@@ -3,6 +3,10 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.device.dto.DeviceDefectRecordDto;
@@ -14,50 +18,99 @@
 import com.ruoyi.device.service.DeviceDefectRecordService;
 import com.ruoyi.device.service.IDeviceLedgerService;
 import com.ruoyi.device.service.IDeviceRepairService;
+import com.ruoyi.device.vo.DeviceRepairVo;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import lombok.AllArgsConstructor;
+import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper;
+import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
+import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord;
+import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 @Slf4j
 public class DeviceRepairServiceImpl extends ServiceImpl<DeviceRepairMapper, DeviceRepair> implements IDeviceRepairService {
 
-    @Autowired
-    private DeviceDefectRecordService deviceDefectRecordService;
-    @Autowired
-    private DeviceRepairMapper deviceRepairMapper;
-    @Autowired
-    private IDeviceLedgerService deviceLedgerService;
-    @Override
-    public IPage<DeviceRepairDto> queryPage(Page page, DeviceRepairDto deviceRepairDto) {
+    private final DeviceDefectRecordService deviceDefectRecordService;
+    private final DeviceRepairMapper deviceRepairMapper;
+    private final IDeviceLedgerService deviceLedgerService;
+    private final SparePartsMapper sparePartsMapper;
+    private final SparePartsRequisitionRecordService sparePartsRequisitionRecordService;
+    private final FileUtil fileUtil;
 
-        return deviceRepairMapper.queryPage(page, deviceRepairDto);
+    @Override
+    public IPage<DeviceRepairVo> queryPage(Page page, DeviceRepairDto deviceRepairDto) {
+        IPage<DeviceRepairVo> pageDto = deviceRepairMapper.queryPage(page, deviceRepairDto);
+        for (DeviceRepairVo vo : pageDto.getRecords()) {
+           vo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.DEVICE_REPAIR, vo.getId()));
+        }
+        return pageDto;
     }
 
     @Override
-    public AjaxResult saveDeviceRepair(DeviceRepair deviceRepair) {
-        DeviceLedger byId = deviceLedgerService.getById(deviceRepair.getDeviceLedgerId());
-        deviceRepair.setDeviceName(byId.getDeviceName());
-        deviceRepair.setDeviceModel(byId.getDeviceModel());
-        boolean save = this.save(deviceRepair);
-        if (save){
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult saveDeviceRepair(DeviceRepairDto deviceRepairDto) {
+        DeviceLedger byId = deviceLedgerService.getById(deviceRepairDto.getDeviceLedgerId());
+        deviceRepairDto.setDeviceName(byId.getDeviceName());
+        deviceRepairDto.setDeviceModel(byId.getDeviceModel());
+        boolean save = this.save(deviceRepairDto);
+        if (save) {
+            // 澶勭悊鍥剧墖涓婁紶
+            fileUtil.saveStorageAttachmentByRecordTypeAndRecordId("file", RecordTypeEnum.DEVICE_REPAIR, deviceRepairDto.getId(), deviceRepairDto.getStorageBlobDTOs());
             return AjaxResult.success();
         }
-        return AjaxResult.error();
+        return AjaxResult.error("淇濆瓨澶辫触");
     }
 
     @Override
-    public AjaxResult updateDeviceRepair(DeviceRepair deviceRepair) {
-        if (this.updateById(deviceRepair)) {
-            Long id = deviceRepair.getId();
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult updateDeviceRepair(DeviceRepairDto deviceRepairDto) {
+        DeviceRepair oldDeviceRepair = this.getById(deviceRepairDto.getId());
+        // 澶勭悊澶囦欢浣跨敤鎯呭喌
+        if (CollectionUtils.isNotEmpty(deviceRepairDto.getSparePartsUseList())) {
+            List<Long> sparePartIds = new ArrayList<>();
+            for (DeviceRepairDto.SparePartUse sparePartUse : deviceRepairDto.getSparePartsUseList()) {
+                // 鑾峰彇澶囦欢淇℃伅
+                SpareParts spareParts = sparePartsMapper.selectById(sparePartUse.getId());
+                if (spareParts != null) {
+                    // 妫�鏌ユ暟閲忔槸鍚﹁冻澶�
+                    if (spareParts.getQuantity().compareTo(new BigDecimal(sparePartUse.getQuantity())) >= 0) {
+                        // 鏇存柊鏁伴噺
+                        spareParts.setQuantity(spareParts.getQuantity().subtract(new BigDecimal(sparePartUse.getQuantity())));
+                        sparePartsMapper.updateById(spareParts);
+                        sparePartIds.add(sparePartUse.getId());
+
+                        // 鍒涘缓澶囦欢棰嗙敤璁板綍
+                        SparePartsRequisitionRecord record = new SparePartsRequisitionRecord();
+                        record.setSourceType(0); // 0 缁翠慨
+                        record.setSourceId(deviceRepairDto.getId());
+                        record.setDeviceLedgerId(oldDeviceRepair.getDeviceLedgerId());
+                        record.setSparePartsId(sparePartUse.getId());
+                        record.setQuantity(sparePartUse.getQuantity());
+                        sparePartsRequisitionRecordService.save(record);
+                    } else {
+                        return AjaxResult.error("澶囦欢 " + spareParts.getName() + " 鏁伴噺涓嶈冻");
+                    }
+                }
+            }
+            // 鏇存柊澶囦欢IDs瀛楁
+            if (!sparePartIds.isEmpty()) {
+                deviceRepairDto.setSparePartsIds(StringUtils.join(sparePartIds, ","));
+            }
+        }
+
+        if (this.updateById(deviceRepairDto)) {
+            Long id = deviceRepairDto.getId();
             //
             DeviceDefectRecordDto deviceDefectRecordDto = new DeviceDefectRecordDto();
             deviceDefectRecordDto.setDeviceLedgerId(id);
@@ -69,6 +122,8 @@
                     deviceDefectRecordService.updateByDDR(deviceDefectRecord);
                 });
             }
+            // 澶勭悊鍥剧墖涓婁紶
+            fileUtil.saveStorageAttachmentByRecordTypeAndRecordId("file", RecordTypeEnum.DEVICE_REPAIR, id, deviceRepairDto.getStorageBlobDTOs());
             return AjaxResult.success();
         }
         return AjaxResult.error();
@@ -109,9 +164,10 @@
     }
 
     @Override
-    public DeviceRepairDto detailById(Long id) {
-
-        return deviceRepairMapper.detailById(id);
+    public DeviceRepairVo detailById(Long id) {
+        DeviceRepairVo vo = deviceRepairMapper.detailById(id);
+        vo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.DEVICE_REPAIR, id));
+        return vo;
     }
 
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
index fca829a..b9deb2d 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
@@ -2,8 +2,8 @@
 
 import com.ruoyi.device.pojo.DeviceMaintenance;
 import com.ruoyi.device.pojo.MaintenanceTask;
+import lombok.RequiredArgsConstructor;
 import org.quartz.*;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Component;
@@ -19,14 +19,13 @@
 
 @Component
 @DisallowConcurrentExecution // 绂佹骞跺彂鎵ц鍚屼竴涓狫ob
+@RequiredArgsConstructor
 public class MaintenanceTaskJob implements Job, Serializable {
     private static final long serialVersionUID = 1L; // 蹇呴』瀹氫箟搴忓垪鍖朓D
 
-    @Autowired
-    private DeviceMaintenanceServiceImpl deviceMaintenanceService;
+    private final DeviceMaintenanceServiceImpl deviceMaintenanceService;
 
-    @Autowired
-    private JdbcTemplate jdbcTemplate;
+    private final JdbcTemplate jdbcTemplate;
 
     @Override
     public void execute(JobExecutionContext context) throws JobExecutionException {
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
index 384862b..ec7a8e3 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
@@ -1,9 +1,9 @@
 package com.ruoyi.device.service.impl;
 
 import com.ruoyi.device.pojo.MaintenanceTask;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.*;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalTime;
@@ -19,10 +19,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class MaintenanceTaskScheduler {
 
-    @Autowired
-    private Scheduler scheduler;
+    private final Scheduler scheduler;
 
     /**
      * 娣诲姞鏂颁换鍔″埌璋冨害鍣�
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
index 0c00da7..3aaac94 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -11,8 +11,8 @@
 import com.ruoyi.inspectiontask.service.impl.TimingTaskServiceImpl;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
@@ -24,19 +24,13 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class MaintenanceTaskServiceImpl extends ServiceImpl<MaintenanceTaskMapper, MaintenanceTask> implements MaintenanceTaskService {
 
-    @Autowired
-    private MaintenanceTaskMapper maintenanceTaskMapper;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private TimingTaskServiceImpl timingTaskService;
-
-    @Autowired
-    private MaintenanceTaskScheduler maintenanceTaskScheduler;
+    private final MaintenanceTaskMapper maintenanceTaskMapper;
+    private final SysUserMapper sysUserMapper;
+    private final TimingTaskServiceImpl timingTaskService;
+    private final MaintenanceTaskScheduler maintenanceTaskScheduler;
 
     @Override
     public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
diff --git a/src/main/java/com/ruoyi/device/vo/DeviceMaintenanceVo.java b/src/main/java/com/ruoyi/device/vo/DeviceMaintenanceVo.java
new file mode 100644
index 0000000..f71c5cb
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/vo/DeviceMaintenanceVo.java
@@ -0,0 +1,51 @@
+package com.ruoyi.device.vo;
+
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.device.pojo.DeviceMaintenance;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+public class DeviceMaintenanceVo extends DeviceMaintenance {
+    @Schema(description = "璁惧淇濆吇id")
+    private Long id;
+
+    @Schema(description = "璁惧鍙拌处id")
+    private Long deviceLedgerId;
+
+    @Schema(description = "璁惧鍚嶇О")
+    private String deviceName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String deviceModel;
+
+    @Schema(description = "瀹為檯淇濆吇浜�")
+    private String maintenanceActuallyName;
+
+    @Schema(description = "淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
+    private String maintenanceResult;
+
+    @Schema(description = "鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
+    private Integer status;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鏇存柊浜�")
+    private String updateUserName;
+
+    @Schema(description = "绉熸埛id")
+    private Long tenantId;
+
+    @Schema(description = "鍒涘缓浜哄悕绉�")
+    private String createUserName;
+
+    @Schema(description = "淇濆吇鍥剧墖鍒楄〃")
+    private List<StorageBlobVO> storageBlobVOs;
+}
diff --git a/src/main/java/com/ruoyi/device/vo/DeviceRepairVo.java b/src/main/java/com/ruoyi/device/vo/DeviceRepairVo.java
new file mode 100644
index 0000000..e90c501
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/vo/DeviceRepairVo.java
@@ -0,0 +1,20 @@
+package com.ruoyi.device.vo;
+
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.device.pojo.DeviceRepair;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class DeviceRepairVo extends DeviceRepair {
+
+    @Schema(description = "鎶ヤ慨鏃堕棿瀛楃涓�")
+    private String repairTimeStr;
+
+    @Schema(description = "缁翠慨鏃堕棿瀛楃涓�")
+    private String maintenanceTimeStr;
+
+    private List<StorageBlobVO> storageBlobVOs;
+}
diff --git a/src/main/java/com/ruoyi/dto/DateQueryDto.java b/src/main/java/com/ruoyi/dto/DateQueryDto.java
index c653fea..22dac0e 100644
--- a/src/main/java/com/ruoyi/dto/DateQueryDto.java
+++ b/src/main/java/com/ruoyi/dto/DateQueryDto.java
@@ -1,8 +1,7 @@
 package com.ruoyi.dto;
 
 import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -10,14 +9,14 @@
  * @date : 2025/7/23 11:31
  */
 @Data
-@ApiModel
+@Schema
 public class DateQueryDto {
 
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
+    @Schema(description = "寮�濮嬫椂闂�")
     @TableField(exist = false)
     private String entryDateStart;
 
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
+    @Schema(description = "缁撴潫鏃堕棿")
     @TableField(exist = false)
     private String entryDateEnd;
 
diff --git a/src/main/java/com/ruoyi/dto/MapDto.java b/src/main/java/com/ruoyi/dto/MapDto.java
index 4a8847c..ddf3bd5 100644
--- a/src/main/java/com/ruoyi/dto/MapDto.java
+++ b/src/main/java/com/ruoyi/dto/MapDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -11,16 +10,16 @@
  * @date : 2025/7/25 10:37
  */
 @Data
-@ApiModel
+@Schema
 public class MapDto {
 
-    @ApiModelProperty(value = "鍚嶇О")
+    @Schema(description = "鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏁伴噺")
+    @Schema(description = "鏁伴噺")
     private String value;
 
-    @ApiModelProperty(value = "鍗犳瘮")
+    @Schema(description = "鍗犳瘮")
     private String rate;
 
 }
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/ElectricityConsumptionAreaController.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/ElectricityConsumptionAreaController.java
index e6babfe..bba6088 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/ElectricityConsumptionAreaController.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/ElectricityConsumptionAreaController.java
@@ -2,10 +2,6 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.basic.dto.ProductDto;
-import com.ruoyi.basic.dto.ProductTreeDto;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.equipmentenergyconsumption.dto.ElectricityConsumptionAreaTreeDto;
 import com.ruoyi.equipmentenergyconsumption.pojo.ElectricityConsumptionArea;
 import com.ruoyi.equipmentenergyconsumption.service.ElectricityConsumptionAreaService;
@@ -13,22 +9,21 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
-@Api(tags = "鐢ㄧ數鍖哄煙")
+@Tag(name = "鐢ㄧ數鍖哄煙")
 @RequestMapping("/electricityConsumptionArea")
+@AllArgsConstructor
 public class ElectricityConsumptionAreaController extends BaseController {
 
-    @Autowired
-    private ElectricityConsumptionAreaService electricityConsumptionAreaService;
+    private final ElectricityConsumptionAreaService electricityConsumptionAreaService;
 
     /**
      * 鏌ヨ鏍戠粨鏋�
@@ -39,7 +34,7 @@
     }
 
     @GetMapping("/listPage")
-    @ApiOperation("鐢ㄧ數鍖哄煙-鍒嗛〉鏌ヨ")
+    @Operation(summary = "鐢ㄧ數鍖哄煙-鍒嗛〉鏌ヨ")
     @Log(title = "鐢ㄧ數鍖哄煙-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, ElectricityConsumptionArea electricityConsumptionArea) {
         IPage<ElectricityConsumptionArea> listPage = electricityConsumptionAreaService.listPage(page, electricityConsumptionArea);
@@ -47,7 +42,7 @@
     }
 
     @PostMapping("/add")
-    @ApiOperation("鐢ㄧ數鍖哄煙-鏂板")
+    @Operation(summary = "鐢ㄧ數鍖哄煙-鏂板")
     @Log(title = "鐢ㄧ數鍖哄煙-鏂板", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody ElectricityConsumptionArea electricityConsumptionArea) {
         boolean save = electricityConsumptionAreaService.saveOrUpdate(electricityConsumptionArea);
@@ -55,7 +50,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鐢ㄧ數鍖哄煙-鍒犻櫎")
+    @Operation(summary = "鐢ㄧ數鍖哄煙-鍒犻櫎")
     @Log(title = "鐢ㄧ數鍖哄煙-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EnergyPeriodController.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EnergyPeriodController.java
index 1c4842f..e0409b5 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EnergyPeriodController.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EnergyPeriodController.java
@@ -3,30 +3,30 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.equipmentenergyconsumption.pojo.ElectricityConsumptionArea;
 import com.ruoyi.equipmentenergyconsumption.pojo.EnergyPeriod;
 import com.ruoyi.equipmentenergyconsumption.service.EnergyPeriodService;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/energyPeriod")
-@Api(tags = "鐢ㄧ數鏃舵")
+@Tag(name = "鐢ㄧ數鏃舵")
+@AllArgsConstructor
 public class EnergyPeriodController extends BaseController {
-    @Autowired
-    private EnergyPeriodService energyPeriodService;
+    private final EnergyPeriodService energyPeriodService;
+
     @GetMapping("/listPage")
-    @ApiOperation("鐢ㄧ數鏃舵-鍒嗛〉鏌ヨ")
+    @Operation(summary = "鐢ㄧ數鏃舵-鍒嗛〉鏌ヨ")
     @Log(title = "鐢ㄧ數鏃舵-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, EnergyPeriod energyPeriod) {
         IPage<EnergyPeriod> listPage = energyPeriodService.listPage(page, energyPeriod);
@@ -34,7 +34,7 @@
     }
 
     @PostMapping("/add")
-    @ApiOperation("鐢ㄧ數鏃舵-鏂板")
+    @Operation(summary = "鐢ㄧ數鏃舵-鏂板")
     @Log(title = "鐢ㄧ數鏃舵-鏂板", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody EnergyPeriod energyPeriod) {
         boolean save = energyPeriodService.save(energyPeriod);
@@ -42,7 +42,7 @@
     }
 
     @PostMapping("/addBatch")
-    @ApiOperation("鐢ㄧ數鏃舵-鎵归噺鏂板")
+    @Operation(summary = "鐢ㄧ數鏃舵-鎵归噺鏂板")
     @Log(title = "鐢ㄧ數鏃舵-鎵归噺鏂板", businessType = BusinessType.INSERT)
     public AjaxResult addBatch(@RequestBody List<EnergyPeriod> energyPeriods) {
         boolean save = energyPeriodService.saveBatch(energyPeriods);
@@ -50,7 +50,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("鐢ㄧ數鏃舵-淇敼")
+    @Operation(summary = "鐢ㄧ數鏃舵-淇敼")
     @Log(title = "鐢ㄧ數鏃舵-淇敼", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody EnergyPeriod energyPeriod) {
         boolean update = energyPeriodService.updateById(energyPeriod);
@@ -58,10 +58,10 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鐢ㄧ數鏃舵-鍒犻櫎")
+    @Operation(summary = "鐢ㄧ數鏃舵-鍒犻櫎")
     @Log(title = "鐢ㄧ數鏃舵-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
-        if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
         boolean remove = energyPeriodService.removeBatchByIds(ids);
         return remove ? AjaxResult.success() : AjaxResult.error("鍒犻櫎澶辫触");
     }
@@ -72,13 +72,13 @@
      */
     @Log(title = "瀵煎嚭鐢ㄧ數鏃舵", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭鐢ㄧ數鏃舵")
+    @Operation(summary = "瀵煎嚭鐢ㄧ數鏃舵")
     public void export(HttpServletResponse response) {
-        Page page = new Page(-1,-1);
+        Page page = new Page(-1, -1);
         EnergyPeriod energyPeriod = new EnergyPeriod();
         IPage<EnergyPeriod> listPage = energyPeriodService.listPage(page, energyPeriod);
         ExcelUtil<EnergyPeriod> util = new ExcelUtil<EnergyPeriod>(EnergyPeriod.class);
-        util.exportExcel(response, listPage.getRecords() , "鐢ㄧ數鏃舵鏁版嵁");
+        util.exportExcel(response, listPage.getRecords(), "鐢ㄧ數鏃舵鏁版嵁");
     }
 
 }
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EquipmentEnergyConsumptionController.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EquipmentEnergyConsumptionController.java
index e71fe31..d401a99 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EquipmentEnergyConsumptionController.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EquipmentEnergyConsumptionController.java
@@ -13,15 +13,16 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -30,16 +31,15 @@
  * @date : 2025/7/29 13:19
  */
 @RestController
-@Api(tags = "璁惧鑳借��")
+@Tag(name = "璁惧鑳借��")
 @RequestMapping("/equipmentEnergyConsumption")
+@AllArgsConstructor
 public class EquipmentEnergyConsumptionController extends BaseController {
 
-
-    @Autowired
     private EquipmentEnergyConsumptionService equipmentEnergyConsumptionService;
 
     @GetMapping("/listPage")
-    @ApiOperation("璁惧鑳借��-鍒嗛〉鏌ヨ")
+    @Operation(summary = "璁惧鑳借��-鍒嗛〉鏌ヨ")
     @Log(title = "璁惧鑳借��-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, EquipmentEnergyConsumption equipmentEnergyConsumption) {
         IPage<EquipmentEnergyConsumption> listPage = equipmentEnergyConsumptionService.listPage(page, equipmentEnergyConsumption);
@@ -47,7 +47,7 @@
     }
 
     @GetMapping("/deviceList")
-    @ApiOperation("璁惧鍙拌处-鏌ヨ")
+    @Operation(summary = "璁惧鍙拌处-鏌ヨ")
     @Log(title = "璁惧鍙拌处-鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult deviceList(DeviceLedger deviceLedger) {
         List<DeviceLedger> listPage = equipmentEnergyConsumptionService.deviceList(deviceLedger);
@@ -55,7 +55,7 @@
     }
 
     @PostMapping("/add")
-    @ApiOperation("璁惧鑳借��-鏂板")
+    @Operation(summary = "璁惧鑳借��-鏂板")
     @Log(title = "璁惧鑳借��-鏂板", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody EquipmentEnergyConsumption equipmentEnergyConsumption) {
         boolean save = equipmentEnergyConsumptionService.save(equipmentEnergyConsumption);
@@ -63,7 +63,7 @@
     }
 
     @PostMapping("/addBatch")
-    @ApiOperation("璁惧鑳借��-鎵归噺鏂板")
+    @Operation(summary = "璁惧鑳借��-鎵归噺鏂板")
     @Log(title = "璁惧鑳借��-鎵归噺鏂板", businessType = BusinessType.INSERT)
     public AjaxResult addBatch(@RequestBody List<EquipmentEnergyConsumption> list) {
         boolean save = equipmentEnergyConsumptionService.saveBatch(list);
@@ -71,7 +71,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("璁惧鑳借��-淇敼")
+    @Operation(summary = "璁惧鑳借��-淇敼")
     @Log(title = "璁惧鑳借��-淇敼", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody EquipmentEnergyConsumption equipmentEnergyConsumption) {
         boolean update = equipmentEnergyConsumptionService.updateById(equipmentEnergyConsumption);
@@ -79,7 +79,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("璁惧鑳借��-鍒犻櫎")
+    @Operation(summary = "璁惧鑳借��-鍒犻櫎")
     @Log(title = "璁惧鑳借��-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -92,7 +92,7 @@
      */
     @Log(title = "瀵煎叆璁惧鑳借��", businessType = BusinessType.IMPORT)
     @PostMapping("/importData")
-    @ApiOperation("瀵煎叆璁惧鑳借��")
+    @Operation(summary = "瀵煎叆璁惧鑳借��")
     public AjaxResult importData(MultipartFile file) throws Exception {
         return equipmentEnergyConsumptionService.importData(file);
     }
@@ -102,7 +102,7 @@
      */
     @Log(title = "瀵煎嚭璁惧鑳借��", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭璁惧鑳借��")
+    @Operation(summary = "瀵煎嚭璁惧鑳借��")
     public void export(HttpServletResponse response) {
         Page page = new Page<>(-1,-1);
         EquipmentEnergyConsumption equipmentEnergyConsumption = new EquipmentEnergyConsumption();
@@ -112,7 +112,7 @@
     }
 
     @GetMapping("/listPageByTrend")
-    @ApiOperation("璁惧鑳借��-鑳芥簮瓒嬪娍-鍒嗛〉鏌ヨ")
+    @Operation(summary = "璁惧鑳借��-鑳芥簮瓒嬪娍-鍒嗛〉鏌ヨ")
     @Log(title = "璁惧鑳借��-鑳芥簮瓒嬪娍-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPageByTrend(Page page, EquipmentEnergyConsumption equipmentEnergyConsumption) {
         IPage<EquipmentEnergyConsumption> listPage = equipmentEnergyConsumptionService.listPageByTrend(page, equipmentEnergyConsumption);
@@ -124,7 +124,7 @@
      */
     @Log(title = "瀵煎嚭鑳芥簮瓒嬪娍", businessType = BusinessType.EXPORT)
     @PostMapping("/exportTwo")
-    @ApiOperation("瀵煎嚭鑳芥簮瓒嬪娍")
+    @Operation(summary = "瀵煎嚭鑳芥簮瓒嬪娍")
     public void exportTwo(HttpServletResponse response) {
         Page page = new Page<>(-1,-1);
         EquipmentEnergyConsumption equipmentEnergyConsumption = new EquipmentEnergyConsumption();
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/ElectricityConsumptionAreaTreeDto.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/ElectricityConsumptionAreaTreeDto.java
index b481090..1ce0969 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/ElectricityConsumptionAreaTreeDto.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/ElectricityConsumptionAreaTreeDto.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.ruoyi.basic.dto.ProductTreeDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.List;
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/EquipmentEnergyConsumptionDto.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/EquipmentEnergyConsumptionDto.java
index 15689d0..f21660a 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/EquipmentEnergyConsumptionDto.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/dto/EquipmentEnergyConsumptionDto.java
@@ -6,7 +6,7 @@
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -28,28 +28,28 @@
     /**
      * 璁惧缂栧彿
      */
-    @ApiModelProperty("璁惧缂栧彿")
+    @Schema(description = "璁惧缂栧彿")
     @Excel(name = "瑙勬牸鍨嬪彿")
     private String code;
 
     /**
      * 璁惧鍚嶇О
      */
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "璁惧鍚嶇О")
     private String name;
 
     /**
      * 棰濆畾鍔熺巼
      */
-    @ApiModelProperty("棰濆畾鍔熺巼")
+    @Schema(description = "棰濆畾鍔熺巼")
 //    @Excel(name = "棰濆畾鍔熺巼")
     private String powerRating;
 
     /**
      * 瀹為檯鍔熺巼
      */
-    @ApiModelProperty("瀹為檯鍔熺巼")
+    @Schema(description = "瀹為檯鍔熺巼")
 //    @Excel(name = "瀹為檯鍔熺巼")
     private String powerActual;
 
@@ -57,14 +57,14 @@
     /**
      * 褰撴棩鐢ㄧ數閲�
      */
-    @ApiModelProperty("褰撴棩鐢ㄧ數閲�")
+    @Schema(description = "褰撴棩鐢ㄧ數閲�")
 //    @Excel(name = "褰撴棩鐢ㄧ數閲�")
     private BigDecimal dayNum;
 
     /**
      * 鏄ㄧ敤鐢甸噺
      */
-    @ApiModelProperty("鏄ㄧ敤鐢甸噺")
+    @Schema(description = "鏄ㄧ敤鐢甸噺")
     @TableField(exist = false)
     @Excel(name = "鏄ㄧ敤鐢甸噺")
     private BigDecimal toDayNum;
@@ -72,7 +72,7 @@
     /**
      * 鏈湀骞冲潎鐢甸噺锛�30澶╄绠楋級
      */
-    @ApiModelProperty("鏈湀骞冲潎鐢甸噺锛�30澶╄绠楋級")
+    @Schema(description = "鏈湀骞冲潎鐢甸噺锛�30澶╄绠楋級")
     @TableField(exist = false)
     @Excel(name = "鏈湀骞冲潎鐢甸噺")
     private BigDecimal avgNum;
@@ -81,7 +81,7 @@
     /**
      * 瓒嬪娍
      */
-    @ApiModelProperty("瓒嬪娍")
+    @Schema(description = "瓒嬪娍")
     @TableField(exist = false)
     @Excel(name = "瓒嬪娍")
     private String trend;
@@ -89,13 +89,13 @@
     /**
      * 绱鐢ㄧ數閲�
      */
-    @ApiModelProperty("绱鐢ㄧ數閲�")
+    @Schema(description = "绱鐢ㄧ數閲�")
 //    @Excel(name = "绱鐢ㄧ數閲�")
     private BigDecimal sumNum;
     /**
      * 杩愯鏃堕棿
      */
-    @ApiModelProperty("杩愯鏃堕棿")
+    @Schema(description = "杩愯鏃堕棿")
     @Excel(name = "杩愯鏃堕棿" , width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date runDate;
@@ -103,7 +103,7 @@
     /**
      * 姣忔棩闄愬埗鐢甸噺
      */
-    @ApiModelProperty("姣忔棩闄愬埗鐢甸噺")
+    @Schema(description = "姣忔棩闄愬埗鐢甸噺")
 //    @Excel(name = "姣忔棩闄愬埗鐢甸噺")
     private BigDecimal everyNum;
 
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/ElectricityConsumptionArea.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/ElectricityConsumptionArea.java
index 4911305..c0101a2 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/ElectricityConsumptionArea.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/ElectricityConsumptionArea.java
@@ -2,14 +2,13 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 
 @Data
 @TableName("electricity_consumption_area")
-@ApiModel
+@Schema
 public class ElectricityConsumptionArea {
 
         @TableId(value = "id", type = IdType.AUTO)
@@ -18,13 +17,13 @@
         /**
          * 鍖哄煙鍚嶇О
          */
-        @ApiModelProperty("鍖哄煙鍚嶇О")
+        @Schema(description = "鍖哄煙鍚嶇О")
         private String areaName;
 
         /**
          * 鍖哄煙绫诲瀷
          */
-        @ApiModelProperty("鍖哄煙绫诲瀷")
+        @Schema(description = "鍖哄煙绫诲瀷")
         private String areaType;
         /**
          * 鎺掑簭
@@ -40,4 +39,11 @@
          */
         @TableField(fill = FieldFill.INSERT)
         private Long tenantId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EnergyPeriod.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EnergyPeriod.java
index 20c9e8f..876606c 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EnergyPeriod.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EnergyPeriod.java
@@ -2,29 +2,28 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.Date;
 
 @Data
 @TableName("energy_period")
-@ApiModel
+@Schema
 public class EnergyPeriod {
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
     /**
      * 鏃ユ湡
      */
-    @ApiModelProperty("鏃ユ湡")
+    @Schema(description = "鏃ユ湡")
     @Excel(name = "鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date date;
     /**
      * 鍗曚环
      */
-    @ApiModelProperty("鍗曚环")
+    @Schema(description = "鍗曚环")
     @Excel(name = "鍗曚环")
     private Double price;
     /**
@@ -35,25 +34,32 @@
     /**
      * 宄版
      */
-    @ApiModelProperty("宄版")
+    @Schema(description = "宄版")
     @Excel(name = "宄版")
     private Double peak;
     /**
      * 璋锋
      */
-    @ApiModelProperty("璋锋")
+    @Schema(description = "璋锋")
     @Excel(name = "璋锋")
     private Double valley;
     /**
      * 骞虫
      */
-    @ApiModelProperty("骞虫")
+    @Schema(description = "骞虫")
     @Excel(name = "骞虫")
     private Double flat;
     /**
      * 灏栨
      */
-    @ApiModelProperty("灏栨")
+    @Schema(description = "灏栨")
     @Excel(name = "灏栨")
     private Double sharp;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EquipmentEnergyConsumption.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EquipmentEnergyConsumption.java
index 846fc8a..249e84b 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EquipmentEnergyConsumption.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EquipmentEnergyConsumption.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Builder;
 import lombok.Data;
 
@@ -19,7 +18,7 @@
  */
 @Data
 @TableName("equipment_energy_consumption")
-@ApiModel
+@Schema
 public class EquipmentEnergyConsumption {
 
     private static final long serialVersionUID = 1L;
@@ -30,28 +29,28 @@
     /**
      * 璁惧缂栧彿
      */
-    @ApiModelProperty("璁惧缂栧彿")
+    @Schema(description = "璁惧缂栧彿")
     @Excel(name = "璁惧缂栧彿")
     private String code;
 
     /**
      * 璁惧鍚嶇О
      */
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "璁惧鍚嶇О")
     private String name;
 
     /**
      * 棰濆畾鍔熺巼
      */
-    @ApiModelProperty("棰濆畾鍔熺巼")
+    @Schema(description = "棰濆畾鍔熺巼")
     @Excel(name = "棰濆畾鍔熺巼")
     private String powerRating;
 
     /**
      * 瀹為檯鍔熺巼
      */
-    @ApiModelProperty("瀹為檯鍔熺巼")
+    @Schema(description = "瀹為檯鍔熺巼")
     @Excel(name = "瀹為檯鍔熺巼")
     private String powerActual;
 
@@ -59,21 +58,21 @@
     /**
      * 褰撴棩鐢ㄧ數閲�
      */
-    @ApiModelProperty("褰撴棩鐢ㄧ數閲�")
+    @Schema(description = "褰撴棩鐢ㄧ數閲�")
     @Excel(name = "褰撴棩鐢ㄧ數閲�")
     private BigDecimal dayNum;
 
     /**
      * 鏄ㄧ敤鐢甸噺
      */
-    @ApiModelProperty("鏄ㄧ敤鐢甸噺")
+    @Schema(description = "鏄ㄧ敤鐢甸噺")
     @TableField(exist = false)
     private BigDecimal toDayNum;
 
     /**
      * 鏈湀骞冲潎鐢甸噺锛�30澶╄绠楋級
      */
-    @ApiModelProperty("鏈湀骞冲潎鐢甸噺锛�30澶╄绠楋級")
+    @Schema(description = "鏈湀骞冲潎鐢甸噺锛�30澶╄绠楋級")
     @TableField(exist = false)
     private BigDecimal avgNum;
 
@@ -81,20 +80,20 @@
     /**
      * 瓒嬪娍
      */
-    @ApiModelProperty("瓒嬪娍")
+    @Schema(description = "瓒嬪娍")
     @TableField(exist = false)
     private String trend;
 
     /**
      * 绱鐢ㄧ數閲�
      */
-    @ApiModelProperty("绱鐢ㄧ數閲�")
+    @Schema(description = "绱鐢ㄧ數閲�")
     @Excel(name = "绱鐢ㄧ數閲�")
     private BigDecimal sumNum;
     /**
      * 杩愯鏃堕棿
      */
-    @ApiModelProperty("杩愯鏃堕棿")
+    @Schema(description = "杩愯鏃堕棿")
     @Excel(name = "杩愯鏃堕棿" , width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date runDate;
@@ -102,7 +101,7 @@
     /**
      * 姣忔棩闄愬埗鐢甸噺
      */
-    @ApiModelProperty("姣忔棩闄愬埗鐢甸噺")
+    @Schema(description = "姣忔棩闄愬埗鐢甸噺")
     @Excel(name = "姣忔棩闄愬埗鐢甸噺")
     private BigDecimal everyNum;
 
@@ -139,4 +138,7 @@
      *鎵�灞炵敤鐢靛尯鍩焛d
      */
     private Long electricityConsumptionAreaId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/ElectricityConsumptionAreaServiceImpl.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/ElectricityConsumptionAreaServiceImpl.java
index abccda9..c53ed64 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/ElectricityConsumptionAreaServiceImpl.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/ElectricityConsumptionAreaServiceImpl.java
@@ -4,16 +4,13 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.dto.ProductTreeDto;
-import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.equipmentenergyconsumption.dto.ElectricityConsumptionAreaTreeDto;
 import com.ruoyi.equipmentenergyconsumption.mapper.ElectricityConsumptionAreaMapper;
 import com.ruoyi.equipmentenergyconsumption.pojo.ElectricityConsumptionArea;
 import com.ruoyi.equipmentenergyconsumption.service.ElectricityConsumptionAreaService;
-
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
@@ -22,10 +19,10 @@
 
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class ElectricityConsumptionAreaServiceImpl extends ServiceImpl<ElectricityConsumptionAreaMapper, ElectricityConsumptionArea> implements ElectricityConsumptionAreaService {
 
-    @Autowired
-    private ElectricityConsumptionAreaMapper electricityConsumptionAreaMapper;
+    private final ElectricityConsumptionAreaMapper electricityConsumptionAreaMapper;
 
     @Override
     public IPage<ElectricityConsumptionArea> listPage(Page page, ElectricityConsumptionArea electricityConsumptionArea) {
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EnergyPeriodServiceImpl.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EnergyPeriodServiceImpl.java
index 4eabf91..22d1a70 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EnergyPeriodServiceImpl.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EnergyPeriodServiceImpl.java
@@ -6,15 +6,15 @@
 import com.ruoyi.equipmentenergyconsumption.mapper.EnergyPeriodMapper;
 import com.ruoyi.equipmentenergyconsumption.pojo.EnergyPeriod;
 import com.ruoyi.equipmentenergyconsumption.service.EnergyPeriodService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class EnergyPeriodServiceImpl extends ServiceImpl<EnergyPeriodMapper, EnergyPeriod> implements EnergyPeriodService {
-    @Autowired
-    private EnergyPeriodMapper energyPeriodMapper;
+    private final EnergyPeriodMapper energyPeriodMapper;
 
     @Override
     public IPage<EnergyPeriod> listPage(Page page, EnergyPeriod energyPeriod) {
diff --git a/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EquipmentEnergyConsumptionServiceImpl.java b/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EquipmentEnergyConsumptionServiceImpl.java
index 90b3d8f..486ad48 100644
--- a/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EquipmentEnergyConsumptionServiceImpl.java
+++ b/src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EquipmentEnergyConsumptionServiceImpl.java
@@ -4,7 +4,6 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.device.mapper.DeviceLedgerMapper;
 import com.ruoyi.device.pojo.DeviceLedger;
@@ -12,8 +11,8 @@
 import com.ruoyi.equipmentenergyconsumption.pojo.EquipmentEnergyConsumption;
 import com.ruoyi.equipmentenergyconsumption.service.EquipmentEnergyConsumptionService;
 import com.ruoyi.framework.web.domain.AjaxResult;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
@@ -29,14 +28,12 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class EquipmentEnergyConsumptionServiceImpl extends ServiceImpl<EquipmentEnergyConsumptionMapper, EquipmentEnergyConsumption> implements EquipmentEnergyConsumptionService {
 
 
-    @Autowired
-    private EquipmentEnergyConsumptionMapper equipmentEnergyConsumptionMapper;
-
-    @Autowired
-    private DeviceLedgerMapper deviceLedgerMapper;
+    private final EquipmentEnergyConsumptionMapper equipmentEnergyConsumptionMapper;
+    private final DeviceLedgerMapper deviceLedgerMapper;
 
     @Override
     public IPage<EquipmentEnergyConsumption> listPage(Page page, EquipmentEnergyConsumption equipmentEnergyConsumption) {
diff --git a/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
index 45d3bfe..9b9e1dc 100644
--- a/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
+++ b/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
@@ -2,8 +2,8 @@
 
 import java.util.Collection;
 import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.ArrayUtils;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.annotation.AfterReturning;
diff --git a/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
index 278bcc4..4a9966c 100644
--- a/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
+++ b/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
@@ -1,8 +1,10 @@
 package com.ruoyi.framework.aspectj;
 
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.List;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.framework.aspectj.lang.annotation.RateLimiter;
+import com.ruoyi.framework.aspectj.lang.enums.LimitType;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
@@ -13,11 +15,10 @@
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.core.script.RedisScript;
 import org.springframework.stereotype.Component;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.ip.IpUtils;
-import com.ruoyi.framework.aspectj.lang.annotation.RateLimiter;
-import com.ruoyi.framework.aspectj.lang.enums.LimitType;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * 闄愭祦澶勭悊
diff --git a/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/src/main/java/com/ruoyi/framework/config/DruidConfig.java
index f0519d5..4dde749 100644
--- a/src/main/java/com/ruoyi/framework/config/DruidConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/DruidConfig.java
@@ -1,28 +1,25 @@
 package com.ruoyi.framework.config;
 
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.sql.DataSource;
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceBuilder;
+import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.aspectj.lang.enums.DataSourceType;
+import com.ruoyi.framework.config.properties.DruidProperties;
+import com.ruoyi.framework.datasource.DynamicDataSource;
+import jakarta.servlet.*;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
-import com.alibaba.druid.pool.DruidDataSource;
-import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
-import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
-import com.alibaba.druid.util.Utils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.framework.aspectj.lang.enums.DataSourceType;
-import com.ruoyi.framework.config.properties.DruidProperties;
-import com.ruoyi.framework.datasource.DynamicDataSource;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * druid 閰嶇疆澶氭暟鎹簮
@@ -96,7 +93,7 @@
         Filter filter = new Filter()
         {
             @Override
-            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
+            public void init(jakarta.servlet.FilterConfig filterConfig) throws ServletException
             {
             }
             @Override
diff --git a/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/src/main/java/com/ruoyi/framework/config/FilterConfig.java
index 610807a..6a79b5d 100644
--- a/src/main/java/com/ruoyi/framework/config/FilterConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/FilterConfig.java
@@ -1,16 +1,18 @@
 package com.ruoyi.framework.config;
 
-import java.util.HashMap;
-import java.util.Map;
-import javax.servlet.DispatcherType;
+import com.ruoyi.common.filter.RepeatableFilter;
+import com.ruoyi.common.filter.XssFilter;
+import com.ruoyi.common.utils.StringUtils;
+import jakarta.servlet.DispatcherType;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import com.ruoyi.common.filter.RepeatableFilter;
-import com.ruoyi.common.filter.XssFilter;
-import com.ruoyi.common.utils.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Filter閰嶇疆
@@ -18,6 +20,7 @@
  * @author ruoyi
  */
 @Configuration
+@RequiredArgsConstructor
 public class FilterConfig
 {
     @Value("${xss.excludes}")
diff --git a/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java b/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
index 86950fd..69a5f41 100644
--- a/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
@@ -7,87 +7,68 @@
 import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
-import com.ruoyi.common.handler.CustomTenantLineHandler;
+import com.ruoyi.common.interceptor.DataScopeSqlInterceptor;
 import org.apache.ibatis.executor.Executor;
 import org.apache.ibatis.mapping.BoundSql;
 import org.apache.ibatis.mapping.MappedStatement;
 import org.apache.ibatis.session.ResultHandler;
 import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 
-import java.sql.SQLException;
-
 /**
- * Mybatis Plus 閰嶇疆
- *
- * @author ruoyi
+ * MyBatis Plus config.
  */
 @EnableTransactionManagement(proxyTargetClass = true)
 @Configuration
-public class MybatisPlusConfig
-{
+public class MybatisPlusConfig {
+
+    @Autowired
+    private DataScopeSqlInterceptor dataScopeSqlInterceptor;
+
     @Bean
-    public MybatisPlusInterceptor mybatisPlusInterceptor()
-    {
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
-        // 绉熸埛鎻掍欢
-//        TenantLineInnerInterceptor tenantLineInnerInterceptor = new TenantLineInnerInterceptor(new CustomTenantLineHandler());
-//        interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
-        // 鍒嗛〉鎻掍欢
+        // Rewrite the original SQL before pagination generates the count query.
+        interceptor.addInnerInterceptor(dataScopeSqlInterceptor);
         interceptor.addInnerInterceptor(paginationInnerInterceptor());
-        // 涔愯閿佹彃浠�
         interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
-        // 闃绘柇鎻掍欢
         interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
         return interceptor;
     }
 
     /**
-     * 鍒嗛〉鎻掍欢锛岃嚜鍔ㄨ瘑鍒暟鎹簱绫诲瀷 https://baomidou.com/guide/interceptor-pagination.html
+     * Pagination interceptor.
      */
-//    public PaginationInnerInterceptor paginationInnerInterceptor()
-//    {
-//        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
-//        // 璁剧疆鏁版嵁搴撶被鍨嬩负mysql
-//        paginationInnerInterceptor.setDbType(DbType.MYSQL);
-//        // 璁剧疆鏈�澶у崟椤甸檺鍒舵暟閲忥紝榛樿 500 鏉★紝-1 涓嶅彈闄愬埗
-//        paginationInnerInterceptor.setMaxLimit(-1L);
-//        return paginationInnerInterceptor;
-//    }
-
     public PaginationInnerInterceptor paginationInnerInterceptor() {
         PaginationInnerInterceptor interceptor = new PaginationInnerInterceptor(DbType.MYSQL) {
             @Override
             public void beforeQuery(Executor executor, MappedStatement ms, Object parameter,
-                                    RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
+                                    RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
                 IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);
                 if (page != null && page.getSize() <= 0) {
-                    // 褰搒ize<=0鏃讹紝涓嶈繘琛屽垎椤�
                     return;
                 }
                 super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
             }
         };
-        interceptor.setMaxLimit(1000L); // 寤鸿璁剧疆鍚堢悊鐨勬渶澶у��
+        interceptor.setMaxLimit(1000L);
         return interceptor;
     }
 
     /**
-     * 涔愯閿佹彃浠� https://baomidou.com/guide/interceptor-optimistic-locker.html
+     * Optimistic lock interceptor.
      */
-    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor()
-    {
+    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
         return new OptimisticLockerInnerInterceptor();
     }
 
     /**
-     * 濡傛灉鏄鍏ㄨ〃鐨勫垹闄ゆ垨鏇存柊鎿嶄綔锛屽氨浼氱粓姝㈣鎿嶄綔 https://baomidou.com/guide/interceptor-block-attack.html
+     * Block full-table update and delete.
      */
-    public BlockAttackInnerInterceptor blockAttackInnerInterceptor()
-    {
+    public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
         return new BlockAttackInnerInterceptor();
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
index 396e2a9..b388ebd 100644
--- a/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -1,7 +1,8 @@
 package com.ruoyi.framework.config;
 
-import java.util.concurrent.TimeUnit;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
+import lombok.RequiredArgsConstructor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.CacheControl;
@@ -11,8 +12,8 @@
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
+
+import java.util.concurrent.TimeUnit;
 
 /**
  * 閫氱敤閰嶇疆
@@ -20,10 +21,10 @@
  * @author ruoyi
  */
 @Configuration
+@RequiredArgsConstructor
 public class ResourcesConfig implements WebMvcConfigurer
 {
-    @Autowired
-    private RepeatSubmitInterceptor repeatSubmitInterceptor;
+    private final RepeatSubmitInterceptor repeatSubmitInterceptor;
 
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry)
diff --git a/src/main/java/com/ruoyi/framework/config/ScheduleConfig.java b/src/main/java/com/ruoyi/framework/config/ScheduleConfig.java
index 576d2c9..4dfb27a 100644
--- a/src/main/java/com/ruoyi/framework/config/ScheduleConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/ScheduleConfig.java
@@ -3,7 +3,7 @@
 //import org.springframework.context.annotation.Bean;
 //import org.springframework.context.annotation.Configuration;
 //import org.springframework.scheduling.quartz.SchedulerFactoryBean;
-//import javax.sql.DataSource;
+//import jakarta.sql.DataSource;
 //import java.util.Properties;
 //
 ///**
diff --git a/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
index 4b31dfa..dcaa947 100644
--- a/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -1,6 +1,10 @@
 package com.ruoyi.framework.config;
 
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
+import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
+import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
+import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
+import lombok.RequiredArgsConstructor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.HttpMethod;
@@ -16,10 +20,6 @@
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.logout.LogoutFilter;
 import org.springframework.web.filter.CorsFilter;
-import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
-import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
-import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
-import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
 
 /**
  * spring security閰嶇疆
@@ -28,43 +28,38 @@
  */
 @EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
 @Configuration
+@RequiredArgsConstructor
 public class SecurityConfig
 {
     /**
      * 鑷畾涔夌敤鎴疯璇侀�昏緫
      */
-    @Autowired
-    private UserDetailsService userDetailsService;
+    private final UserDetailsService userDetailsService;
     
     /**
      * 璁よ瘉澶辫触澶勭悊绫�
      */
-    @Autowired
-    private AuthenticationEntryPointImpl unauthorizedHandler;
+    private final AuthenticationEntryPointImpl unauthorizedHandler;
 
     /**
      * 閫�鍑哄鐞嗙被
      */
-    @Autowired
-    private LogoutSuccessHandlerImpl logoutSuccessHandler;
+    private final LogoutSuccessHandlerImpl logoutSuccessHandler;
 
     /**
      * token璁よ瘉杩囨护鍣�
      */
-    @Autowired
-    private JwtAuthenticationTokenFilter authenticationTokenFilter;
+    private final JwtAuthenticationTokenFilter authenticationTokenFilter;
     
     /**
      * 璺ㄥ煙杩囨护鍣�
      */
-    @Autowired
-    private CorsFilter corsFilter;
+    private final CorsFilter corsFilter;
 
     /**
      * 鍏佽鍖垮悕璁块棶鐨勫湴鍧�
      */
-    @Autowired
-    private PermitAllUrlProperties permitAllUrl;
+    private final PermitAllUrlProperties permitAllUrl;
 
     /**
      * 韬唤楠岃瘉瀹炵幇
@@ -108,16 +103,51 @@
             // 鍩轰簬token锛屾墍浠ヤ笉闇�瑕乻ession
             .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
             // 娉ㄨВ鏍囪鍏佽鍖垮悕璁块棶鐨剈rl
-            .authorizeHttpRequests((requests) -> {
-                permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
-                // 瀵逛簬鐧诲綍login 娉ㄥ唽register 楠岃瘉鐮乧aptchaImage 鍏佽鍖垮悕璁块棶
-                requests.antMatchers("/login", "/register", "/captchaImage","/loginCheck","/userLoginFacotryList/**","/loginCheckFactory").permitAll()
-                    // 闈欐�佽祫婧愶紝鍙尶鍚嶈闂�
-                    .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**","/javaWork/**","/**/*.pdf").permitAll()
-                    .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
-                    // 闄や笂闈㈠鐨勬墍鏈夎姹傚叏閮ㄩ渶瑕侀壌鏉冭璇�
-                    .anyRequest().authenticated();
-            })
+                // todo ai鐢熸垚锛� 鍚庢湡鑻ユ湁闂璇疯嚜琛屼紭鍖�
+                .authorizeHttpRequests(requests -> {
+
+                    // 1. 鏀捐鍔ㄦ�侀厤缃殑 URL
+                    permitAllUrl.getUrls().forEach(url ->
+                            requests.requestMatchers(url).permitAll()
+                    );
+
+                    // 2. 鐧诲綍 / 娉ㄥ唽 / 楠岃瘉鐮� / 绛夋斁琛�
+                    requests.requestMatchers(
+                            "/login",
+                            "/register",
+                            "/captchaImage",
+                            "/loginCheck",
+                            "/userLoginFacotryList/**",
+                            "/loginCheckFactory"
+                    ).permitAll();
+
+                    // 3. 闈欐�佽祫婧愭斁琛�
+                    requests.requestMatchers(HttpMethod.GET,
+                            "/",
+                            "/*.html",
+                            "/**/*.html",
+                            "/**/*.css",
+                            "/**/*.js",
+                            "/profile/**",
+                            "/javaWork/**",
+                            "/**/*.pdf"
+                    ).permitAll();
+
+                    // 4. swagger / druid 鏀捐
+                    requests.requestMatchers(
+                            "/swagger-ui.html",
+                            "/doc.html",
+                            "/swagger-ui/**",
+                            "/swagger-resources/**",
+                            "/v3/api-docs/**",
+                            "/webjars/**",
+                            "/*/api-docs",
+                            "/druid/**"
+                    ).permitAll();
+
+                    // 5. 鍏朵粬鍏ㄩ儴鎷︽埅
+                    requests.anyRequest().authenticated();
+                })
             // 娣诲姞Logout filter
             .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
             // 娣诲姞JWT filter
diff --git a/src/main/java/com/ruoyi/framework/config/ServerConfig.java b/src/main/java/com/ruoyi/framework/config/ServerConfig.java
index 157e9f4..4c1c476 100644
--- a/src/main/java/com/ruoyi/framework/config/ServerConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/ServerConfig.java
@@ -1,6 +1,6 @@
 package com.ruoyi.framework.config;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.utils.ServletUtils;
 
diff --git a/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java b/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java
index ccf8d65..e42ef54 100644
--- a/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java
+++ b/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java
@@ -1,124 +1,53 @@
-package com.ruoyi.framework.config;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.models.auth.In;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.service.ApiKey;
-import springfox.documentation.service.AuthorizationScope;
-import springfox.documentation.service.Contact;
-import springfox.documentation.service.SecurityReference;
-import springfox.documentation.service.SecurityScheme;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spi.service.contexts.SecurityContext;
-import springfox.documentation.spring.web.plugins.Docket;
-
-/**
- * Swagger2鐨勬帴鍙i厤缃�
- * 
- * @author ruoyi
- */
-@Configuration
-public class SwaggerConfig
-{
-    /** 绯荤粺鍩虹閰嶇疆 */
-    @Autowired
-    private RuoYiConfig ruoyiConfig;
-
-    /** 鏄惁寮�鍚痵wagger */
-    @Value("${swagger.enabled}")
-    private boolean enabled;
-
-    /** 璁剧疆璇锋眰鐨勭粺涓�鍓嶇紑 */
-    @Value("${swagger.pathMapping}")
-    private String pathMapping;
-
-    /**
-     * 鍒涘缓API
-     */
-    @Bean
-    public Docket createRestApi()
-    {
-        return new Docket(DocumentationType.OAS_30)
-                // 鏄惁鍚敤Swagger
-                .enable(enabled)
-                // 鐢ㄦ潵鍒涘缓璇PI鐨勫熀鏈俊鎭紝灞曠ず鍦ㄦ枃妗g殑椤甸潰涓紙鑷畾涔夊睍绀虹殑淇℃伅锛�
-                .apiInfo(apiInfo())
-                // 璁剧疆鍝簺鎺ュ彛鏆撮湶缁橲wagger灞曠ず
-                .select()
-                // 鎵弿鎵�鏈夋湁娉ㄨВ鐨刟pi锛岀敤杩欑鏂瑰紡鏇寸伒娲�
-                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
-                // 鎵弿鎸囧畾鍖呬腑鐨剆wagger娉ㄨВ
-                // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
-                // 鎵弿鎵�鏈� .apis(RequestHandlerSelectors.any())
-                .paths(PathSelectors.any())
-                .build()
-                /* 璁剧疆瀹夊叏妯″紡锛宻wagger鍙互璁剧疆璁块棶token */
-                .securitySchemes(securitySchemes())
-                .securityContexts(securityContexts());
-//                .pathMapping(pathMapping);
-    }
-
-    /**
-     * 瀹夊叏妯″紡锛岃繖閲屾寚瀹歵oken閫氳繃Authorization澶磋姹傚ご浼犻��
-     */
-    private List<SecurityScheme> securitySchemes()
-    {
-        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
-        apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
-        return apiKeyList;
-    }
-
-    /**
-     * 瀹夊叏涓婁笅鏂�
-     */
-    private List<SecurityContext> securityContexts()
-    {
-        List<SecurityContext> securityContexts = new ArrayList<>();
-        securityContexts.add(
-                SecurityContext.builder()
-                        .securityReferences(defaultAuth())
-                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
-                        .build());
-        return securityContexts;
-    }
-
-    /**
-     * 榛樿鐨勫畨鍏ㄤ笂寮曠敤
-     */
-    private List<SecurityReference> defaultAuth()
-    {
-        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
-        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
-        authorizationScopes[0] = authorizationScope;
-        List<SecurityReference> securityReferences = new ArrayList<>();
-        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
-        return securityReferences;
-    }
-
-    /**
-     * 娣诲姞鎽樿淇℃伅
-     */
-    private ApiInfo apiInfo()
-    {
-        // 鐢ˋpiInfoBuilder杩涜瀹氬埗
-        return new ApiInfoBuilder()
-                // 璁剧疆鏍囬
-                .title("鏍囬锛氳嫢渚濈鐞嗙郴缁焈鎺ュ彛鏂囨。")
-                // 鎻忚堪
-                .description("鎻忚堪锛氱敤浜庣鐞嗛泦鍥㈡棗涓嬪叕鍙哥殑浜哄憳淇℃伅,鍏蜂綋鍖呮嫭XXX,XXX妯″潡...")
-                // 浣滆�呬俊鎭�
-                .contact(new Contact(ruoyiConfig.getName(), null, null))
-                // 鐗堟湰
-                .version("鐗堟湰鍙�:" + ruoyiConfig.getVersion())
-                .build();
-    }
-}
+package com.ruoyi.framework.config;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+import org.springdoc.core.models.GroupedOpenApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * OpenAPI 鏂囨。閰嶇疆銆�
+ */
+@Configuration
+@ConditionalOnProperty(prefix = "swagger", name = "enabled", havingValue = "true", matchIfMissing = true)
+public class SwaggerConfig
+{
+    @Autowired
+    private RuoYiConfig ruoyiConfig;
+
+    @Bean
+    public OpenAPI openAPI()
+    {
+        String schemeName = "Authorization";
+        return new OpenAPI()
+                .info(new Info()
+                        .title("鏍囬锛氳嫢渚濈鐞嗙郴缁熸帴鍙f枃妗�")
+                        .description("鎻忚堪锛氱敤浜庣鐞嗛泦鍥㈡棗涓嬪叕鍙哥殑浜哄憳淇℃伅锛屽叿浣撳寘鎷� XXX銆乆XX 妯″潡銆�")
+                        .version("鐗堟湰鍙凤細" + ruoyiConfig.getVersion())
+                        .contact(new Contact().name(ruoyiConfig.getName())))
+                .components(new Components().addSecuritySchemes(schemeName,
+                        new SecurityScheme()
+                                .name(schemeName)
+                                .type(SecurityScheme.Type.APIKEY)
+                                .in(SecurityScheme.In.HEADER)))
+                .addSecurityItem(new SecurityRequirement().addList(schemeName));
+    }
+
+    @Bean
+    public GroupedOpenApi defaultOpenApi()
+    {
+        return GroupedOpenApi.builder()
+                .group("default")
+                // 鎵弿椤圭洰鐪熷疄鏆撮湶鐨勬帴鍙h矾寰勶紝涓嶇敤 swagger.pathMapping 鍋氫簩娆¤繃婊わ紝
+                // 鍚﹀垯鍍� /dev-api 杩欑被缃戝叧鍓嶇紑浼氭妸鏈湴 Controller 鍏ㄩ儴杩囨护鎺夈��
+                .pathsToMatch("/**")
+                .build();
+    }
+}
diff --git a/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java b/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
index bc22e20..e2626bd 100644
--- a/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
+++ b/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
@@ -1,11 +1,6 @@
 package com.ruoyi.framework.config.properties;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.regex.Pattern;
+import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
 import org.apache.commons.lang3.RegExUtils;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.InitializingBean;
@@ -16,7 +11,9 @@
 import org.springframework.web.method.HandlerMethod;
 import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
 import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
-import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
+
+import java.util.*;
+import java.util.regex.Pattern;
 
 /**
  * 璁剧疆Anonymous娉ㄨВ鍏佽鍖垮悕璁块棶鐨剈rl
@@ -40,18 +37,36 @@
         RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
         Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
 
+//        map.keySet().forEach(info -> {
+//            HandlerMethod handlerMethod = map.get(info);
+//
+//            // 鑾峰彇鏂规硶涓婅竟鐨勬敞瑙� 鏇夸唬path variable 涓� *
+//            Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
+//            Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
+//                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
+//
+//            // 鑾峰彇绫讳笂杈圭殑娉ㄨВ, 鏇夸唬path variable 涓� *
+//            Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
+//            Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
+//                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
+//        });
+
         map.keySet().forEach(info -> {
             HandlerMethod handlerMethod = map.get(info);
+            // 鑾峰彇鏂规硶涓婄殑鍖垮悕璁块棶娉ㄨВ
+            Anonymous anonymous = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
+            if (Objects.nonNull(anonymous)) {
+                // 閲嶇偣锛歋pring Boot 3 鍏煎鎬у啓娉�
+                Set<String> patterns = new HashSet<>();
+                if (info.getPatternsCondition() != null) {
+                    patterns.addAll(info.getPatternsCondition().getPatterns());
+                }
+                if (info.getPathPatternsCondition() != null) {
+                    patterns.addAll(info.getPathPatternsCondition().getPatternValues());
+                }
 
-            // 鑾峰彇鏂规硶涓婅竟鐨勬敞瑙� 鏇夸唬path variable 涓� *
-            Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
-            Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
-                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
-
-            // 鑾峰彇绫讳笂杈圭殑娉ㄨВ, 鏇夸唬path variable 涓� *
-            Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
-            Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
-                    .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
+                patterns.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, "*")));
+            }
         });
     }
 
diff --git a/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java
index 014ae38..aeae267 100644
--- a/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java
+++ b/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java
@@ -1,9 +1,10 @@
 package com.ruoyi.framework.datasource;
 
-import java.util.Map;
-import javax.sql.DataSource;
 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 
+import javax.sql.DataSource;
+import java.util.Map;
+
 /**
  * 鍔ㄦ�佹暟鎹簮
  * 
diff --git a/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
index a559159..fd80428 100644
--- a/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
+++ b/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
@@ -1,8 +1,8 @@
 package com.ruoyi.framework.interceptor;
 
 import java.lang.reflect.Method;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.stereotype.Component;
 import org.springframework.web.method.HandlerMethod;
 import org.springframework.web.servlet.HandlerInterceptor;
diff --git a/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
index ef335f3..fa95ca7 100644
--- a/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
+++ b/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
@@ -3,7 +3,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
index 8d8fb5a..31c6f81 100644
--- a/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
+++ b/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
@@ -1,9 +1,9 @@
 package com.ruoyi.framework.manager;
 
+import jakarta.annotation.PreDestroy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
-import javax.annotation.PreDestroy;
 
 /**
  * 纭繚搴旂敤閫�鍑烘椂鑳藉叧闂悗鍙扮嚎绋�
diff --git a/src/main/java/com/ruoyi/framework/security/LoginUser.java b/src/main/java/com/ruoyi/framework/security/LoginUser.java
index bb91be1..330ae43 100644
--- a/src/main/java/com/ruoyi/framework/security/LoginUser.java
+++ b/src/main/java/com/ruoyi/framework/security/LoginUser.java
@@ -76,47 +76,58 @@
      */
     private Long tenantId;
 
-    /**
-     * 褰撳墠閮ㄩ棬id
-     */
-    private Long currentDeptId;
+    /**
+     * 褰撳墠閮ㄩ棬id
+     */
+    private Long currentDeptId;
+
+    /**
+     * 鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級
+     */
+    private Integer aiEnabled;
+
+    private String dataScope;
 
     public LoginUser()
     {
     }
 
-    public LoginUser(SysUser user, Set<String> permissions)
-    {
-        this.user = user;
-        this.permissions = permissions;
-    }
+    public LoginUser(SysUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
-    public LoginUser(Long userId, Long [] deptId, SysUser user, Set<String> permissions)
-    {
-        this.userId = userId;
-        this.deptIds = deptId;
-        this.user = user;
-        this.permissions = permissions;
-    }
+    public LoginUser(Long userId, Long [] deptId, SysUser user, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptIds = deptId;
+        this.user = user;
+        this.permissions = permissions;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
-    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId, Set<String> permissions)
-    {
-        this.userId = userId;
-        this.deptIds = deptIds;
-        this.user = user;
-        this.permissions = permissions;
-        this.tenantId = tenantId;
-    }
+    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptIds = deptIds;
+        this.user = user;
+        this.permissions = permissions;
+        this.tenantId = tenantId;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
-    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId,Long currentDeptId, Set<String> permissions)
-    {
-        this.userId = userId;
-        this.deptIds = deptIds;
-        this.user = user;
-        this.permissions = permissions;
-        this.tenantId = tenantId;
-        this.currentDeptId = currentDeptId;
-    }
+    public LoginUser(Long userId, Long [] deptIds, SysUser user,Long tenantId,Long currentDeptId, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptIds = deptIds;
+        this.user = user;
+        this.permissions = permissions;
+        this.tenantId = tenantId;
+        this.currentDeptId = currentDeptId;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
     public Long getUserId()
     {
@@ -287,10 +298,11 @@
         return user;
     }
 
-    public void setUser(SysUser user)
-    {
-        this.user = user;
-    }
+    public void setUser(SysUser user)
+    {
+        this.user = user;
+        this.aiEnabled = user == null ? null : user.getAiEnabled();
+    }
 
     @Override
     public Collection<? extends GrantedAuthority> getAuthorities()
@@ -314,7 +326,29 @@
         return currentDeptId;
     }
 
-    public void setCurrentDeptId(Long currentDeptId) {
-        this.currentDeptId = currentDeptId;
-    }
-}
+    public void setCurrentDeptId(Long currentDeptId) {
+        this.currentDeptId = currentDeptId;
+    }
+
+    public Integer getAiEnabled() {
+        if (aiEnabled != null) {
+            return aiEnabled;
+        }
+        if (user != null && user.getAiEnabled() != null) {
+            return user.getAiEnabled();
+        }
+        return 0;
+    }
+
+    public void setAiEnabled(Integer aiEnabled) {
+        this.aiEnabled = aiEnabled;
+    }
+
+    public String getDataScope() {
+        return dataScope;
+    }
+
+    public void setDataScope(String dataScope) {
+        this.dataScope = dataScope;
+    }
+}
diff --git a/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
index ede50be..93d4c77 100644
--- a/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
+++ b/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
@@ -1,10 +1,10 @@
 package com.ruoyi.framework.security.filter;
 
 import java.io.IOException;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.context.SecurityContextHolder;
@@ -22,23 +22,35 @@
  * @author ruoyi
  */
 @Component
-public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
-{
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
+{
     @Autowired
     private TokenService tokenService;
 
     @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException
-    {
-        LoginUser loginUser = tokenService.getLoginUser(request);
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+            throws ServletException, IOException
+    {
+        LoginUser loginUser = tokenService.getLoginUser(request);
         if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
         {
             tokenService.verifyToken(loginUser);
             UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
             authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
             SecurityContextHolder.getContext().setAuthentication(authenticationToken);
-        }
-        chain.doFilter(request, response);
-    }
-}
+        }
+        chain.doFilter(request, response);
+    }
+
+    @Override
+    protected boolean shouldNotFilterAsyncDispatch()
+    {
+        return false;
+    }
+
+    @Override
+    protected boolean shouldNotFilterErrorDispatch()
+    {
+        return false;
+    }
+}
diff --git a/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java b/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java
index 6dff702..d43cd7c 100644
--- a/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java
+++ b/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java
@@ -2,8 +2,8 @@
 
 import java.io.IOException;
 import java.io.Serializable;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.AuthenticationEntryPoint;
 import org.springframework.stereotype.Component;
diff --git a/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java b/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java
index 04f37b6..65b4443 100644
--- a/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java
+++ b/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java
@@ -1,13 +1,5 @@
 package com.ruoyi.framework.security.handle;
 
-import java.io.IOException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
 import com.alibaba.fastjson2.JSON;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.utils.ServletUtils;
@@ -17,21 +9,30 @@
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.security.service.TokenService;
 import com.ruoyi.framework.web.domain.AjaxResult;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+
+import java.io.IOException;
 
 /**
  * 鑷畾涔夐��鍑哄鐞嗙被 杩斿洖鎴愬姛
- * 
+ *
  * @author ruoyi
  */
 @Configuration
+@RequiredArgsConstructor
 public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
 {
-    @Autowired
-    private TokenService tokenService;
+    private final TokenService tokenService;
 
     /**
      * 閫�鍑哄鐞�
-     * 
+     *
      * @return
      */
     @Override
diff --git a/src/main/java/com/ruoyi/framework/security/service/SysLoginService.java b/src/main/java/com/ruoyi/framework/security/service/SysLoginService.java
index 6a7874a..8c3d68b 100644
--- a/src/main/java/com/ruoyi/framework/security/service/SysLoginService.java
+++ b/src/main/java/com/ruoyi/framework/security/service/SysLoginService.java
@@ -1,25 +1,10 @@
 package com.ruoyi.framework.security.service;
 
-import javax.annotation.Resource;
-
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.mapper.SysUserMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
 import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.exception.user.BlackListException;
-import com.ruoyi.common.exception.user.CaptchaException;
-import com.ruoyi.common.exception.user.CaptchaExpireException;
-import com.ruoyi.common.exception.user.UserNotExistsException;
-import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.exception.user.*;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.MessageUtils;
 import com.ruoyi.common.utils.StringUtils;
@@ -30,10 +15,18 @@
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.security.context.AuthenticationContextHolder;
 import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.system.service.ISysConfigService;
 import com.ruoyi.project.system.service.ISysUserService;
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -43,22 +36,19 @@
  * @author ruoyi
  */
 @Component
+@RequiredArgsConstructor
 public class SysLoginService
 {
-    @Autowired
-    private TokenService tokenService;
+    private final TokenService tokenService;
 
     @Resource
     private AuthenticationManager authenticationManager;
 
-    @Autowired
-    private RedisCache redisCache;
+    private final RedisCache redisCache;
+    private final ISysUserService userService;
+    private final ISysConfigService configService;
+    private final SysUserMapper sysUserMapper;
 
-    @Autowired
-    private ISysUserService userService;
-
-    @Autowired
-    private ISysConfigService configService;
 
     /**
      * 鐧诲綍楠岃瘉
@@ -219,8 +209,6 @@
         return loginUser.getUserId();
     }
 
-    @Autowired
-    private SysUserMapper sysUserMapper;
 
     /**
      * 鐧诲綍楠岃瘉
diff --git a/src/main/java/com/ruoyi/framework/security/service/SysPasswordService.java b/src/main/java/com/ruoyi/framework/security/service/SysPasswordService.java
index 97c3518..608bfef 100644
--- a/src/main/java/com/ruoyi/framework/security/service/SysPasswordService.java
+++ b/src/main/java/com/ruoyi/framework/security/service/SysPasswordService.java
@@ -1,10 +1,5 @@
 package com.ruoyi.framework.security.service;
 
-import java.util.concurrent.TimeUnit;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.security.core.Authentication;
-import org.springframework.stereotype.Component;
 import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
 import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
@@ -12,6 +7,12 @@
 import com.ruoyi.framework.redis.RedisCache;
 import com.ruoyi.framework.security.context.AuthenticationContextHolder;
 import com.ruoyi.project.system.domain.SysUser;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
 
 /**
  * 鐧诲綍瀵嗙爜鏂规硶
@@ -19,10 +20,10 @@
  * @author ruoyi
  */
 @Component
+@RequiredArgsConstructor
 public class SysPasswordService
 {
-    @Autowired
-    private RedisCache redisCache;
+    private final RedisCache redisCache;
 
     @Value(value = "${user.password.maxRetryCount}")
     private int maxRetryCount;
diff --git a/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java b/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java
index ca3fb91..34cb1a4 100644
--- a/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java
+++ b/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java
@@ -1,17 +1,18 @@
 package com.ruoyi.framework.security.service;
 
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.project.system.domain.SysRole;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.service.ISysMenuService;
 import com.ruoyi.project.system.service.ISysRoleService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 /**
  * 鐢ㄦ埛鏉冮檺澶勭悊
@@ -19,13 +20,11 @@
  * @author ruoyi
  */
 @Component
+@RequiredArgsConstructor
 public class SysPermissionService
 {
-    @Autowired
-    private ISysRoleService roleService;
-
-    @Autowired
-    private ISysMenuService menuService;
+    private final ISysRoleService roleService;
+    private final ISysMenuService menuService;
 
     /**
      * 鑾峰彇瑙掕壊鏁版嵁鏉冮檺
diff --git a/src/main/java/com/ruoyi/framework/security/service/SysRegisterService.java b/src/main/java/com/ruoyi/framework/security/service/SysRegisterService.java
index 17274eb..e139835 100644
--- a/src/main/java/com/ruoyi/framework/security/service/SysRegisterService.java
+++ b/src/main/java/com/ruoyi/framework/security/service/SysRegisterService.java
@@ -1,7 +1,5 @@
 package com.ruoyi.framework.security.service;
 
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
 import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.UserConstants;
@@ -17,6 +15,8 @@
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.service.ISysConfigService;
 import com.ruoyi.project.system.service.ISysUserService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
 
 /**
  * 娉ㄥ唽鏍¢獙鏂规硶
@@ -24,16 +24,12 @@
  * @author ruoyi
  */
 @Component
+@RequiredArgsConstructor
 public class SysRegisterService
 {
-    @Autowired
-    private ISysUserService userService;
-
-    @Autowired
-    private ISysConfigService configService;
-
-    @Autowired
-    private RedisCache redisCache;
+    private final ISysUserService userService;
+    private final ISysConfigService configService;
+    private final RedisCache redisCache;
 
     /**
      * 娉ㄥ唽
diff --git a/src/main/java/com/ruoyi/framework/security/service/TokenService.java b/src/main/java/com/ruoyi/framework/security/service/TokenService.java
index 7d09431..35802db 100644
--- a/src/main/java/com/ruoyi/framework/security/service/TokenService.java
+++ b/src/main/java/com/ruoyi/framework/security/service/TokenService.java
@@ -1,20 +1,6 @@
 package com.ruoyi.framework.security.service;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import javax.servlet.http.HttpServletRequest;
-
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.project.system.domain.SysUserDept;
-import com.ruoyi.project.system.mapper.SysUserDeptMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
 import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.utils.ServletUtils;
@@ -24,11 +10,27 @@
 import com.ruoyi.common.utils.uuid.IdUtils;
 import com.ruoyi.framework.redis.RedisCache;
 import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.project.system.domain.SysRole;
+import com.ruoyi.project.system.domain.SysUserDept;
+import com.ruoyi.project.system.mapper.SysUserDeptMapper;
 import eu.bitwalker.useragentutils.UserAgent;
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.security.Keys;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
+
+import javax.crypto.SecretKey;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 /**
  * token楠岃瘉澶勭悊
@@ -36,6 +38,7 @@
  * @author ruoyi
  */
 @Component
+@RequiredArgsConstructor
 public class TokenService
 {
     private static final Logger log = LoggerFactory.getLogger(TokenService.class);
@@ -58,8 +61,7 @@
 
     private static final Long MILLIS_MINUTE_TWENTY = 20 * 60 * 1000L;
 
-    @Autowired
-    private RedisCache redisCache;
+    private final RedisCache redisCache;
 
     /**
      * 鑾峰彇鐢ㄦ埛韬唤淇℃伅
@@ -147,8 +149,7 @@
         }
     }
 
-    @Autowired
-    private SysUserDeptMapper sysUserDeptMapper;
+    private final SysUserDeptMapper sysUserDeptMapper;
 
     /**
      * 鍒锋柊浠ょ墝鏈夋晥鏈�
@@ -160,10 +161,70 @@
         loginUser.setLoginTime(System.currentTimeMillis());
         loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
         loginUser.setDeptIds(getDeptIdsByUserId(loginUser.getUserId()));
-        loginUser.setCurrentDeptId(loginUser.getDeptIds()[0]);
+        if (loginUser.getDeptIds() != null && loginUser.getDeptIds().length > 0)
+        {
+            loginUser.setCurrentDeptId(loginUser.getDeptIds()[0]);
+        }
+        loginUser.setDataScope(resolveDataScope(loginUser));
         // 鏍规嵁uuid灏唋oginUser缂撳瓨
         String userKey = getTokenKey(loginUser.getToken());
         redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
+    }
+
+    public String resolveDataScope(LoginUser loginUser)
+    {
+        if (loginUser == null || loginUser.getUser() == null || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
+        {
+            return null;
+        }
+        boolean hasCustom = false;
+        boolean hasDeptAndChild = false;
+        boolean hasDept = false;
+        boolean hasSelf = false;
+        for (SysRole role : loginUser.getUser().getRoles())
+        {
+            if (role == null || !"0".equals(role.getStatus()))
+            {
+                continue;
+            }
+            if ("1".equals(role.getDataScope()))
+            {
+                return "1";
+            }
+            if ("2".equals(role.getDataScope()))
+            {
+                hasCustom = true;
+            }
+            else if ("4".equals(role.getDataScope()))
+            {
+                hasDeptAndChild = true;
+            }
+            else if ("3".equals(role.getDataScope()))
+            {
+                hasDept = true;
+            }
+            else if ("5".equals(role.getDataScope()))
+            {
+                hasSelf = true;
+            }
+        }
+        if (hasCustom)
+        {
+            return "2";
+        }
+        if (hasDeptAndChild)
+        {
+            return "4";
+        }
+        if (hasDept)
+        {
+            return "3";
+        }
+        if (hasSelf)
+        {
+            return "5";
+        }
+        return null;
     }
 
     public Long[] getDeptIdsByUserId(Long userId){
@@ -191,6 +252,11 @@
         loginUser.setOs(userAgent.getOperatingSystem().getName());
     }
 
+    private SecretKey getSigningKey() {
+        byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
+        return Keys.hmacShaKeyFor(keyBytes);
+    }
+
     /**
      * 浠庢暟鎹0鏄庣敓鎴愪护鐗�
      *
@@ -199,10 +265,10 @@
      */
     private String createToken(Map<String, Object> claims)
     {
-        String token = Jwts.builder()
-                .setClaims(claims)
-                .signWith(SignatureAlgorithm.HS512, secret).compact();
-        return token;
+        return Jwts.builder()
+                .claims(claims) // 娉ㄦ剰锛氭柊鐗堟柟娉曞悕鍙樹簡锛屼笉鍐嶆槸 setClaims
+                .signWith(getSigningKey(), Jwts.SIG.HS512) // 浣跨敤鏂扮殑绛惧悕甯搁噺
+                .compact();
     }
 
     /**
@@ -214,9 +280,10 @@
     private Claims parseToken(String token)
     {
         return Jwts.parser()
-                .setSigningKey(secret)
-                .parseClaimsJws(token)
-                .getBody();
+                .verifyWith(getSigningKey()) // 鏂扮増浣跨敤 verifyWith
+                .build()
+                .parseSignedClaims(token)
+                .getPayload();
     }
 
     /**
diff --git a/src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java b/src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java
index c1b46e0..79fb62c 100644
--- a/src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java
+++ b/src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java
@@ -1,21 +1,21 @@
 package com.ruoyi.framework.security.service;
 
-import com.ruoyi.project.system.mapper.SysDeptMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.stereotype.Service;
 import com.ruoyi.common.enums.UserStatus;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.MessageUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.service.ISysUserService;
+import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.stereotype.Service;
 
 import java.util.Map;
 
@@ -25,21 +25,15 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class UserDetailsServiceImpl implements UserDetailsService
 {
     private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
 
-    @Autowired
-    private ISysUserService userService;
-    
-    @Autowired
-    private SysPasswordService passwordService;
-
-    @Autowired
-    private SysPermissionService permissionService;
-
-    @Autowired
-    private SysDeptMapper deptMapper;
+    private final ISysUserService userService;
+    private final SysPasswordService passwordService;
+    private final SysPermissionService permissionService;
+    private final SysDeptMapper deptMapper;
 
     @Override
     public UserDetails loadUserByUsername(String username)
diff --git a/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
index bcea0a7..f0467b3 100644
--- a/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
+++ b/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
@@ -1,6 +1,6 @@
 package com.ruoyi.framework.web.exception;
 
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.access.AccessDeniedException;
diff --git a/src/main/java/com/ruoyi/home/controller/HomeController.java b/src/main/java/com/ruoyi/home/controller/HomeController.java
index fcdfc16..41ae224 100644
--- a/src/main/java/com/ruoyi/home/controller/HomeController.java
+++ b/src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -1,6 +1,7 @@
 package com.ruoyi.home.controller;
 
 import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.dto.MapDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
@@ -8,10 +9,9 @@
 import com.ruoyi.home.annotation.DefaultType;
 import com.ruoyi.home.dto.*;
 import com.ruoyi.home.service.HomeService;
-import com.ruoyi.dto.MapDto;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -26,45 +26,45 @@
  * @date : 2025/7/25 9:15
  */
 @RestController
-@Api(tags = "棣栭〉缁熻")
+@Tag(name = "棣栭〉缁熻")
 @RequestMapping("/home")
+@AllArgsConstructor
 public class HomeController extends BaseController {
 
-    @Autowired
-    private HomeService homeService;
+    private final HomeService homeService;
 
     /********************************************************鍩虹绫�*****************************************************/
     @GetMapping("/todos")
     @Log(title = "寰呭姙浜嬮」", businessType = BusinessType.OTHER)
-    @ApiOperation("寰呭姙浜嬮」")
+    @Operation(summary = "寰呭姙浜嬮」")
     public AjaxResult todos(ApproveProcess req) throws ParseException {
         List<ApproveProcess> approveProcessList = homeService.todos();
         return AjaxResult.success(approveProcessList);
     }
 
     @GetMapping("/approveAndDeviceTodos")
-    @ApiOperation("瀹℃壒鍗忓悓锛岃澶囨姤淇緟鍔炰簨椤�")
+    @Operation(summary = "瀹℃壒鍗忓悓锛岃澶囨姤淇緟鍔炰簨椤�")
     public AjaxResult approveAndDeviceTodos(){
         Map<String, Object> map = homeService.approveAndDeviceTodos();
         return AjaxResult.success(map);
     }
 
     @GetMapping("/noticesCount")
-    @ApiOperation("鏈繃鏈熺殑鍏憡鏁伴噺")
+    @Operation(summary = "鏈繃鏈熺殑鍏憡鏁伴噺")
     public AjaxResult noticesCount(){
         Long count = homeService.noticesCount();
         return AjaxResult.success(count);
     }
 
     @GetMapping("/deptStaffDistribution")
-    @ApiOperation("鍚勯儴闂ㄤ汉鍛樺垎甯�")
+    @Operation(summary = "鍚勯儴闂ㄤ汉鍛樺垎甯�")
     public AjaxResult deptStaffDistribution() {
         DeptStaffDistributionDto dto = homeService.deptStaffDistribution();
         return AjaxResult.success(dto);
     }
 
     @GetMapping("/summaryStatistics")
-    @ApiOperation("鍛樺伐-瀹㈡埛-渚涘簲鍟嗘�绘暟")
+    @Operation(summary = "鍛樺伐-瀹㈡埛-渚涘簲鍟嗘�绘暟")
     public AjaxResult summaryStatistics() {
         HomeSummaryDto homeSummaryDto = homeService.summaryStatistics();
         return AjaxResult.success(homeSummaryDto);
@@ -72,35 +72,35 @@
 
     /********************************************************钀ラ攢閲囪喘绫�**************************************************/
     @GetMapping("/supplierPurchaseRanking")
-    @ApiOperation("渚涘簲鍟嗛噰璐帓鍚�")
+    @Operation(summary = "渚涘簲鍟嗛噰璐帓鍚�")
     public AjaxResult supplierPurchaseRanking(@DefaultType Integer type) {
         List<SupplierPurchaseRankingDto> list = homeService.supplierPurchaseRanking(type);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/customerRevenueAnalysis")
-    @ApiOperation("瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋�")
+    @Operation(summary = "瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋�")
     public AjaxResult customerRevenueAnalysis(Long customerId, @DefaultType Integer type) {
         CustomerRevenueAnalysisDto dto = homeService.customerRevenueAnalysis(customerId, type);
         return AjaxResult.success(dto);
     }
 
     @GetMapping("/customerContributionRanking")
-    @ApiOperation("瀹㈡埛閲戦璐$尞鎺掑悕")
+    @Operation(summary = "瀹㈡埛閲戦璐$尞鎺掑悕")
     public AjaxResult customerContributionRanking(@DefaultType Integer type) {
         List<CustomerContributionRankingDto> list = homeService.customerContributionRanking(type);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/productSalesAnalysis")
-    @ApiOperation("鍚勪骇鍝侀攢鍞噾棰濆垎鏋�")
+    @Operation(summary = "鍚勪骇鍝侀攢鍞噾棰濆垎鏋�")
     public AjaxResult productSalesAnalysis() {
         List<MapDto> list = homeService.productSalesAnalysis();
         return AjaxResult.success(list);
     }
 
     @GetMapping("/rawMaterialPurchaseAmountRatio")
-    @ApiOperation("鍘熸潗鏂欓噰璐噾棰濆崰姣�")
+    @Operation(summary = "鍘熸潗鏂欓噰璐噾棰濆崰姣�")
     public AjaxResult rawMaterialPurchaseAmountRatio(){
         List<MapDto> list = homeService.rawMaterialPurchaseAmountRatio();
         return AjaxResult.success(list);
@@ -108,7 +108,7 @@
 
     @GetMapping("/business")
     @Log(title = "閿�鍞�-閲囪喘-搴撳瓨鏁版嵁", businessType = BusinessType.OTHER)
-    @ApiOperation("閿�鍞�-閲囪喘-搴撳瓨鏁版嵁")
+    @Operation(summary = "閿�鍞�-閲囪喘-搴撳瓨鏁版嵁")
     public AjaxResult business(HomeBusinessDto req) {
         HomeBusinessDto homeBusinessDto = homeService.business();
         return AjaxResult.success(homeBusinessDto);
@@ -116,7 +116,7 @@
 
     @GetMapping("/analysisCustomerContractAmounts")
     @Log(title = "瀹㈡埛鍚堝悓閲戦鍒嗘瀽", businessType = BusinessType.OTHER)
-    @ApiOperation("瀹㈡埛鍚堝悓閲戦鍒嗘瀽")
+    @Operation(summary = "瀹㈡埛鍚堝悓閲戦鍒嗘瀽")
     public AjaxResult analysisCustomerContractAmounts(AnalysisCustomerContractAmountsDto req) {
         AnalysisCustomerContractAmountsDto analysisCustomerContractAmounts = homeService.analysisCustomerContractAmounts();
         return AjaxResult.success(analysisCustomerContractAmounts);
@@ -124,55 +124,55 @@
 
     /********************************************************鐢熶骇绫�*****************************************************/
     @GetMapping("/inputOutputAnalysis")
-    @ApiOperation("鎶曞叆浜у嚭鍒嗘瀽")
+    @Operation(summary = "鎶曞叆浜у嚭鍒嗘瀽")
     public AjaxResult inputOutputAnalysis(@DefaultType Integer type){
       List<InputOutputAnalysisDto> list = homeService.inputOutputAnalysis(type);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/processOutputAnalysis")
-    @ApiOperation("宸ュ簭浜у嚭鍒嗘瀽")
+    @Operation(summary = "宸ュ簭浜у嚭鍒嗘瀽")
     public AjaxResult processOutputAnalysis(@DefaultType Integer type){
         List<MapDto> list = homeService.processOutputAnalysis(type);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/workOrderEfficiencyAnalysis")
-    @ApiOperation("宸ュ崟鎵ц鏁堢巼鍒嗘瀽")
+    @Operation(summary = "宸ュ崟鎵ц鏁堢巼鍒嗘瀽")
     public AjaxResult workOrderEfficiencyAnalysis(@DefaultType Integer type){
         List<WorkOrderEfficiencyDto> list = homeService.workOrderEfficiencyAnalysis(type);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/productionAccountingAnalysis")
-    @ApiOperation("鐢熶骇鏍哥畻鍒嗘瀽")
+    @Operation(summary = "鐢熶骇鏍哥畻鍒嗘瀽")
     public AjaxResult productionAccountingAnalysis(@DefaultType Integer type){
         List<ProductionAccountingDto> list   = homeService.productionAccountingAnalysis(type);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/orderCount")
-    @ApiOperation("璁㈠崟鏁�")
+    @Operation(summary = "璁㈠崟鏁�")
     public AjaxResult orderCount(){
         return AjaxResult.success(homeService.orderCount());
     }
 
     @GetMapping("/progressStatistics")
-    @ApiOperation("鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻")
+    @Operation(summary = "鍚勭敓浜ц鍗曠殑瀹屾垚杩涘害缁熻")
     public AjaxResult progressStatistics(){
         ProductionProgressDto productionProgressDto = homeService.productionProgress();
         return AjaxResult.success(productionProgressDto);
     }
 
     @GetMapping("/workInProcessTurnover")
-    @ApiOperation("鍦ㄥ埗鍝佸懆杞儏鍐�")
+    @Operation(summary = "鍦ㄥ埗鍝佸懆杞儏鍐�")
     public AjaxResult workInProcessTurnover(){
         ProductionTurnoverDto productionTurnoverDto = homeService.workInProcessTurnover();
         return AjaxResult.success(productionTurnoverDto);
     }
 
     @GetMapping("/processDataProductionStatistics")
-    @ApiOperation("宸ュ簭鏁版嵁鐢熶骇缁熻鏁版嵁")
+    @Operation(summary = "宸ュ簭鏁版嵁鐢熶骇缁熻鏁版嵁")
     public AjaxResult processDataProductionStatistics(@DefaultType Integer type,@RequestParam(required = false) List<Long> processIds) {
         List<processDataProductionStatisticsDto> list = homeService.processDataProductionStatistics(type, processIds);
         return AjaxResult.success(list);
@@ -180,53 +180,53 @@
 
     /********************************************************璐ㄩ噺绫�*****************************************************/
     @GetMapping("/rawMaterialDetection")
-    @ApiOperation("鍘熸潗鏂欐娴�")
+    @Operation(summary = "鍘熸潗鏂欐娴�")
     public AjaxResult rawMaterialDetection(@DefaultType Integer type){
         return AjaxResult.success(homeService.rawMaterialDetection(type));
     }
 
     @GetMapping("/processDetection")
-    @ApiOperation("杩囩▼妫�娴�")
+    @Operation(summary = "杩囩▼妫�娴�")
     public AjaxResult processDetection(@DefaultType Integer type){
         return AjaxResult.success(homeService.processDetection(type));
     }
 
     @GetMapping("/factoryDetection")
-    @ApiOperation("鎴愬搧鍑哄巶妫�娴�")
+    @Operation(summary = "鎴愬搧鍑哄巶妫�娴�")
     public AjaxResult factoryDetection(@DefaultType Integer type){
         return AjaxResult.success(homeService.factoryDetection(type));
     }
 
     @GetMapping("/qualityInspectionCount")
-    @ApiOperation("璐ㄩ噺妫�楠屾暟閲�")
+    @Operation(summary = "璐ㄩ噺妫�楠屾暟閲�")
     public AjaxResult qualityInspectionCount(){
         QualityInspectionCountDto qualityInspectionCountDto = homeService.qualityInspectionCount();
         return AjaxResult.success(qualityInspectionCountDto);
     }
 
     @GetMapping("/nonComplianceWarning")
-    @ApiOperation("涓嶅悎鏍奸璀�")
+    @Operation(summary = "涓嶅悎鏍奸璀�")
     public AjaxResult nonComplianceWarning(){
         NonComplianceWarningDto nonComplianceWarningDto = homeService.nonComplianceWarning();
         return AjaxResult.success(nonComplianceWarningDto);
     }
 
     @GetMapping("/completedInspectionCount")
-    @ApiOperation("瀹屾垚妫�楠屾暟")
+    @Operation(summary = "瀹屾垚妫�楠屾暟")
     public AjaxResult completedInspectionCount(){
         List<CompletedInspectionCountDto> list = homeService.completedInspectionCount();
         return AjaxResult.success(list);
     }
 
     @GetMapping("/unqualifiedProductRanking")
-    @ApiOperation("涓嶅悎鏍间骇鍝佹帓鍚�")
+    @Operation(summary = "涓嶅悎鏍间骇鍝佹帓鍚�")
     public AjaxResult unqualifiedProductRanking(){
         List<UnqualifiedProductRankDto> list = homeService.unqualifiedProductRanking();
         return AjaxResult.success(list);
     }
 
     @GetMapping("/unqualifiedProductProcessingAnalysis")
-    @ApiOperation("涓嶅悎鏍兼鍝佸鐞嗗垎鏋�")
+    @Operation(summary = "涓嶅悎鏍兼鍝佸鐞嗗垎鏋�")
     public AjaxResult unqualifiedProductProcessingAnalysis(){
         List<MapDto> list = homeService.unqualifiedProductProcessingAnalysis();
         return AjaxResult.success(list);
@@ -234,14 +234,14 @@
 
     @GetMapping("/qualityStatistics")
     @Log(title = "璐ㄩ噺鍒嗘瀽", businessType = BusinessType.OTHER)
-    @ApiOperation("璐ㄩ噺鍒嗘瀽")
+    @Operation(summary = "璐ㄩ噺鍒嗘瀽")
     public AjaxResult qualityStatistics(QualityStatisticsDto req) {
         QualityStatisticsDto qualityStatisticsDto = homeService.qualityStatistics();
         return AjaxResult.success(qualityStatisticsDto);
     }
 
     @GetMapping("/qualityInspectionStatistics")
-    @ApiOperation("璐ㄩ噺缁熻")
+    @Operation(summary = "璐ㄩ噺缁熻")
     public AjaxResult qualityInspectionStatistics(@DefaultType Integer type) {
        QualityStatisticsDto  dto = homeService.qualityInspectionStatistics(type);
         return AjaxResult.success(dto);
@@ -249,35 +249,35 @@
 
     /********************************************************璐㈠姟绫�*****************************************************/
     @GetMapping("/incomeExpenseAnalysis")
-    @ApiOperation("鏀敹瀵规瘮鍒嗘瀽")
+    @Operation(summary = "鏀敹瀵规瘮鍒嗘瀽")
     public AjaxResult incomeExpenseAnalysis(@DefaultType Integer type) {
         List<Map<String, Object>> result = homeService.incomeExpenseAnalysis(type);
         return AjaxResult.success(result);
     }
 
     @GetMapping("/profitTrendAnalysis")
-    @ApiOperation("鍒╂鼎瓒嬪娍鍒嗘瀽")
+    @Operation(summary = "鍒╂鼎瓒嬪娍鍒嗘瀽")
     public AjaxResult profitTrendAnalysis(){
         List<MapDto> list = homeService.profitTrendAnalysis();
         return AjaxResult.success(list);
     }
 
     @GetMapping("/expenseCompositionAnalysis")
-    @ApiOperation("鏋勬垚鍒嗘瀽")
+    @Operation(summary = "鏋勬垚鍒嗘瀽")
     public AjaxResult expenseCompositionAnalysis(@DefaultType Integer type) {
         List<MapDto> list = homeService.expenseCompositionAnalysis(type);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/monthlyIncome")
-    @ApiOperation("鏈堝害鏀跺叆")
+    @Operation(summary = "鏈堝害鏀跺叆")
     public AjaxResult monthlyIncome(){
         MonthlyIncomeDto dto = homeService.monthlyIncome();
         return AjaxResult.success(dto);
     }
 
     @GetMapping("/monthlyExpenditure")
-    @ApiOperation("鏈堝害鏀嚭")
+    @Operation(summary = "鏈堝害鏀嚭")
     public AjaxResult monthlyExpenditure(){
         MonthlyExpenditureDto dto = homeService.monthlyExpenditure();
         return AjaxResult.success(dto);
@@ -285,7 +285,7 @@
 
     @GetMapping("/statisticsReceivablePayable")
     @Log(title = "搴旀敹搴斾粯缁熻", businessType = BusinessType.OTHER)
-    @ApiOperation("搴旀敹搴斾粯缁熻")
+    @Operation(summary = "搴旀敹搴斾粯缁熻")
     public AjaxResult statisticsReceivablePayable(StatisticsReceivablePayableDto req, @DefaultType Integer type ) {
         StatisticsReceivablePayableDto statisticsReceivablePayable = homeService.statisticsReceivablePayable(type);
         return AjaxResult.success(statisticsReceivablePayable);
@@ -294,28 +294,28 @@
     /********************************************************浠撳偍绫�*****************************************************/
 
     @GetMapping("/productCategoryDistribution")
-    @ApiOperation("浜у搧澶х被鍒嗗竷")
+    @Operation(summary = "浜у搧澶х被鍒嗗竷")
     public AjaxResult productCategoryDistribution() {
         ProductCategoryDistributionDto dto = homeService.productCategoryDistribution();
         return AjaxResult.success(dto);
     }
 
     @GetMapping("/salesPurchaseStorageProductCount")
-    @ApiOperation("閿�鍞�-閲囪喘-鍌ㄥ瓨浜у搧鏁�")
+    @Operation(summary = "閿�鍞�-閲囪喘-鍌ㄥ瓨浜у搧鏁�")
     public AjaxResult salesPurchaseStorageProductCount(){
         List<MapDto> list = homeService.salesPurchaseStorageProductCount();
         return AjaxResult.success(list);
     }
 
     @GetMapping("/productInOutAnalysis")
-    @ApiOperation("浜у搧鍑哄叆搴撳垎鏋�")
+    @Operation(summary = "浜у搧鍑哄叆搴撳垎鏋�")
     public AjaxResult productInOutAnalysis(@DefaultType Integer type){
         List<Map<String, Object>> result = homeService.productInOutAnalysis(type);
         return AjaxResult.success(result);
     }
 
     @GetMapping("/productTurnoverDays")
-    @ApiOperation("浜у搧鍛ㄨ浆澶╂暟")
+    @Operation(summary = "浜у搧鍛ㄨ浆澶╂暟")
     public AjaxResult productTurnoverDays(){
         List<MapDto> list = homeService.productTurnoverDays();
         return AjaxResult.success(list);
diff --git a/src/main/java/com/ruoyi/home/dto/AnalysisCustomerContractAmountsDto.java b/src/main/java/com/ruoyi/home/dto/AnalysisCustomerContractAmountsDto.java
index e126ff0..709dd7c 100644
--- a/src/main/java/com/ruoyi/home/dto/AnalysisCustomerContractAmountsDto.java
+++ b/src/main/java/com/ruoyi/home/dto/AnalysisCustomerContractAmountsDto.java
@@ -1,8 +1,7 @@
 package com.ruoyi.home.dto;
 
 import com.ruoyi.dto.MapDto;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -13,16 +12,16 @@
  * @date : 2025/7/25 10:31
  */
 @Data
-@ApiModel
+@Schema
 public class AnalysisCustomerContractAmountsDto {
 
-    @ApiModelProperty(value = "鍚堝悓鎬婚噾棰�")
+    @Schema(description = "鍚堝悓鎬婚噾棰�")
     private String sum;
 
-    @ApiModelProperty(value = "鏃ョ幆姣�")
+    @Schema(description = "鏃ョ幆姣�")
     private String chain;
 
-    @ApiModelProperty(value = "鍛ㄥ悓姣�")
+    @Schema(description = "鍛ㄥ悓姣�")
     private String yny;
 
    private List<MapDto> item;
diff --git a/src/main/java/com/ruoyi/home/dto/CustomerContributionRankingDto.java b/src/main/java/com/ruoyi/home/dto/CustomerContributionRankingDto.java
index 2b6468d..1d174ba 100644
--- a/src/main/java/com/ruoyi/home/dto/CustomerContributionRankingDto.java
+++ b/src/main/java/com/ruoyi/home/dto/CustomerContributionRankingDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -10,12 +9,12 @@
  * 瀹㈡埛閲戦璐$尞鎺掑悕DTO
  */
 @Data
-@ApiModel("瀹㈡埛閲戦璐$尞鎺掑悕")
+@Schema(name = "瀹㈡埛閲戦璐$尞鎺掑悕")
 public class CustomerContributionRankingDto {
 
-    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
-    @ApiModelProperty("鍚堝悓鎬婚噾棰�")
+    @Schema(description = "鍚堝悓鎬婚噾棰�")
     private BigDecimal totalAmount;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/CustomerRevenueAnalysisDto.java b/src/main/java/com/ruoyi/home/dto/CustomerRevenueAnalysisDto.java
index 1bad069..c5fc3d5 100644
--- a/src/main/java/com/ruoyi/home/dto/CustomerRevenueAnalysisDto.java
+++ b/src/main/java/com/ruoyi/home/dto/CustomerRevenueAnalysisDto.java
@@ -1,8 +1,7 @@
 package com.ruoyi.home.dto;
 
 import com.ruoyi.dto.MapDto;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.List;
@@ -11,9 +10,9 @@
  * 瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋怐TO
  */
 @Data
-@ApiModel("瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋�")
+@Schema(name = "瀹㈡埛钀ユ敹璐$尞鏁板�煎垎鏋�")
 public class CustomerRevenueAnalysisDto {
 
-    @ApiModelProperty("鍒嗘瀽鏉$洰鍒楄〃")
+    @Schema(description = "鍒嗘瀽鏉$洰鍒楄〃")
     private List<MapDto> items;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/DeptStaffDistributionDto.java b/src/main/java/com/ruoyi/home/dto/DeptStaffDistributionDto.java
index 4ead293..5d61df3 100644
--- a/src/main/java/com/ruoyi/home/dto/DeptStaffDistributionDto.java
+++ b/src/main/java/com/ruoyi/home/dto/DeptStaffDistributionDto.java
@@ -1,8 +1,7 @@
 package com.ruoyi.home.dto;
 
 import com.ruoyi.dto.MapDto;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.List;
@@ -11,12 +10,12 @@
  * 閮ㄩ棬浜哄憳鍒嗗竷缁熻DTO
  */
 @Data
-@ApiModel("閮ㄩ棬浜哄憳鍒嗗竷缁熻")
+@Schema(name = "閮ㄩ棬浜哄憳鍒嗗竷缁熻")
 public class DeptStaffDistributionDto {
 
-    @ApiModelProperty("閮ㄩ棬鎬讳汉鏁�")
+    @Schema(description = "閮ㄩ棬鎬讳汉鏁�")
     private Long total;
 
-    @ApiModelProperty("閮ㄩ棬鍒嗗竷鍒楄〃")
+    @Schema(description = "閮ㄩ棬鍒嗗竷鍒楄〃")
     private List<MapDto> items;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java b/src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java
index 6c5a20a..6e968a0 100644
--- a/src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java
+++ b/src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -11,25 +10,25 @@
  * @date : 2025/7/25 9:25
  */
 @Data
-@ApiModel
+@Schema
 public class HomeBusinessDto {
 
-    @ApiModelProperty("鏈湀閿�鍞噾棰�")
+    @Schema(description = "鏈湀閿�鍞噾棰�")
     private String monthSaleMoney = "0.00";
 
-    @ApiModelProperty("鏈湀閿�鍞湭寮�绁ㄩ噾棰�")
+    @Schema(description = "鏈湀閿�鍞湭寮�绁ㄩ噾棰�")
     private String monthSaleHaveMoney = "0.00";
 
-    @ApiModelProperty("鏈湀閲囪喘閲戦")
+    @Schema(description = "鏈湀閲囪喘閲戦")
     private String monthPurchaseMoney = "0.00";
 
-    @ApiModelProperty("鏈湀閲囪喘鏈紑绁ㄩ噾棰�")
+    @Schema(description = "鏈湀閲囪喘鏈紑绁ㄩ噾棰�")
     private String monthPurchaseHaveMoney = "0.00";
 
-    @ApiModelProperty("褰撳墠搴撳瓨鏁伴噺")
+    @Schema(description = "褰撳墠搴撳瓨鏁伴噺")
     private String inventoryNum = "0.00";
 
-    @ApiModelProperty("浠婃棩搴撳瓨鏁伴噺")
+    @Schema(description = "浠婃棩搴撳瓨鏁伴噺")
     private String todayInventoryNum = "0.00";
 
 }
diff --git a/src/main/java/com/ruoyi/home/dto/HomeSummaryDto.java b/src/main/java/com/ruoyi/home/dto/HomeSummaryDto.java
index 9d8863b..42d3262 100644
--- a/src/main/java/com/ruoyi/home/dto/HomeSummaryDto.java
+++ b/src/main/java/com/ruoyi/home/dto/HomeSummaryDto.java
@@ -1,31 +1,30 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
  * 棣栭〉姹囨�荤粺璁TO
  */
 @Data
-@ApiModel("棣栭〉姹囨�荤粺璁�")
+@Schema(name = "棣栭〉姹囨�荤粺璁�")
 public class HomeSummaryDto {
 
-    @ApiModelProperty("鎬诲伐浣滀汉鍛�")
+    @Schema(description = "鎬诲伐浣滀汉鍛�")
     private Long totalStaff;
 
-    @ApiModelProperty("鎬诲伐浣滀汉鍛樺悓姣斿闀跨巼")
+    @Schema(description = "鎬诲伐浣滀汉鍛樺悓姣斿闀跨巼")
     private String staffGrowthRate;
 
-    @ApiModelProperty("鎬诲鎴锋暟")
+    @Schema(description = "鎬诲鎴锋暟")
     private Long totalCustomer;
 
-    @ApiModelProperty("鎬诲鎴峰悓姣斿闀跨巼")
+    @Schema(description = "鎬诲鎴峰悓姣斿闀跨巼")
     private String customerGrowthRate;
 
-    @ApiModelProperty("鎬讳緵搴斿晢鏁�")
+    @Schema(description = "鎬讳緵搴斿晢鏁�")
     private Long totalSupplier;
 
-    @ApiModelProperty("鎬讳緵搴斿晢鍚屾瘮澧為暱鐜�")
+    @Schema(description = "鎬讳緵搴斿晢鍚屾瘮澧為暱鐜�")
     private String supplierGrowthRate;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/ProductCategoryDistributionDto.java b/src/main/java/com/ruoyi/home/dto/ProductCategoryDistributionDto.java
index 5b11452..cc4359a 100644
--- a/src/main/java/com/ruoyi/home/dto/ProductCategoryDistributionDto.java
+++ b/src/main/java/com/ruoyi/home/dto/ProductCategoryDistributionDto.java
@@ -1,8 +1,7 @@
 package com.ruoyi.home.dto;
 
 import com.ruoyi.dto.MapDto;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.List;
@@ -11,39 +10,39 @@
  * 浜у搧澶х被鍒嗗竷缁熻DTO
  */
 @Data
-@ApiModel("浜у搧澶х被鍒嗗竷缁熻")
+@Schema(name = "浜у搧澶х被鍒嗗竷缁熻")
 public class ProductCategoryDistributionDto {
 
-    @ApiModelProperty("澶х被鍒嗗竷鍒楄〃")
+    @Schema(description = "澶х被鍒嗗竷鍒楄〃")
     private List<MajorCategoryDto> items;
 
     @Data
     public static class MajorCategoryDto {
-        @ApiModelProperty("澶х被鍚嶇О")
+        @Schema(description = "澶х被鍚嶇О")
         private String name;
 
-        @ApiModelProperty("搴撳瓨鎬绘暟")
+        @Schema(description = "搴撳瓨鎬绘暟")
         private String value;
 
-        @ApiModelProperty("鍗犳瘮")
+        @Schema(description = "鍗犳瘮")
         private String rate;
 
-        @ApiModelProperty("灏忕被鍒嗗竷璇︽儏")
+        @Schema(description = "灏忕被鍒嗗竷璇︽儏")
         private List<MinorCategoryDto> children;
     }
 
     @Data
     public static class MinorCategoryDto {
-        @ApiModelProperty("灏忕被鍚嶇О")
+        @Schema(description = "灏忕被鍚嶇О")
         private String name;
 
-        @ApiModelProperty("搴撳瓨鏁伴噺")
+        @Schema(description = "搴撳瓨鏁伴噺")
         private String value;
 
-        @ApiModelProperty("鍗犳瘮")
+        @Schema(description = "鍗犳瘮")
         private String rate;
 
-        @ApiModelProperty("鍨嬪彿鍒嗗竷璇︽儏")
+        @Schema(description = "鍨嬪彿鍒嗗竷璇︽儏")
         private List<MapDto> children;
     }
 }
diff --git a/src/main/java/com/ruoyi/home/dto/ProductionProgressDto.java b/src/main/java/com/ruoyi/home/dto/ProductionProgressDto.java
index 88fe4b6..852bbf8 100644
--- a/src/main/java/com/ruoyi/home/dto/ProductionProgressDto.java
+++ b/src/main/java/com/ruoyi/home/dto/ProductionProgressDto.java
@@ -1,25 +1,21 @@
 package com.ruoyi.home.dto;
-
-import com.ruoyi.production.dto.ProductOrderDto;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import java.math.BigDecimal;
 import java.util.List;
 
 @Data
-@ApiModel
+@Schema
 public class ProductionProgressDto {
-    @ApiModelProperty("鎬昏鍗曟暟")
+    @Schema(description = "鎬昏鍗曟暟")
     private Long totalOrderCount;
 
-    @ApiModelProperty("宸插畬鎴愯鍗曟暟")
+    @Schema(description = "宸插畬鎴愯鍗曟暟")
     private Long completedOrderCount;
-    @ApiModelProperty("鏈畬鎴愯鍗曟暟")
+    @Schema(description = "鏈畬鎴愯鍗曟暟")
     private Long uncompletedOrderCount;
-    @ApiModelProperty("閮ㄥ垎瀹屾垚璁㈠崟鏁�")
+    @Schema(description = "閮ㄥ垎瀹屾垚璁㈠崟鏁�")
     private Long partialCompletedOrderCount;
-    @ApiModelProperty("璁㈠崟璇︽儏")
-    private List<ProductOrderDto> completedOrderDetails;
+    @Schema(description = "璁㈠崟璇︽儏")
+    private List<ProductionProgressOrderDto> completedOrderDetails;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/ProductionProgressOrderDto.java b/src/main/java/com/ruoyi/home/dto/ProductionProgressOrderDto.java
new file mode 100644
index 0000000..b53bfb3
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/ProductionProgressOrderDto.java
@@ -0,0 +1,57 @@
+package com.ruoyi.home.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+public class ProductionProgressOrderDto {
+
+    @Schema(description = "鐢熶骇璁㈠崟鍙�")
+    private String npsNo;
+
+    @Schema(description = "閿�鍞悎鍚屽彿")
+    private String salesContractNo;
+
+    @Schema(description = "椤圭洰鍚嶇О")
+    private String projectName;
+
+    @Schema(description = "瀹㈡埛鍚嶇О")
+    private String customerName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productCategory;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String specificationModel;
+
+    @Schema(description = "宸ヨ壓璺嚎缂栧彿")
+    private String processRouteCode;
+
+    @Schema(description = "闇�姹傛暟閲�")
+    private BigDecimal quantity;
+
+    @Schema(description = "瀹屾垚鏁伴噺")
+    private BigDecimal completeQuantity;
+
+    @Schema(description = "瀹屾垚杩涘害")
+    private BigDecimal completionStatus;
+
+    @Schema(description = "BOM缂栧彿")
+    private String bomNo;
+
+    @Schema(description = "浜ゆ湡鍋忓樊")
+    private Integer deliveryDaysDiff;
+
+    @Schema(description = "浜ゆ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate deliveryDate;
+
+    @Schema(description = "鏄惁鍙戣揣")
+    private Boolean isFh;
+}
diff --git a/src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java b/src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java
new file mode 100644
index 0000000..28949d7
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/ProductionTaskStatisticsDto.java
@@ -0,0 +1,50 @@
+package com.ruoyi.home.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+public class ProductionTaskStatisticsDto {
+
+    @Schema(description = "宸ュ崟ID")
+    private Long id;
+
+    @Schema(description = "宸ュ崟缂栧彿")
+    private String workOrderNo;
+
+    @Schema(description = "璁″垝寮�濮嬫椂闂�")
+    private LocalDate planStartTime;
+
+    @Schema(description = "璁″垝缁撴潫鏃堕棿")
+    private LocalDate planEndTime;
+
+    @Schema(description = "瀹為檯寮�濮嬫椂闂�")
+    private LocalDate actualStartTime;
+
+    @Schema(description = "瀹為檯缁撴潫鏃堕棿")
+    private LocalDate actualEndTime;
+
+    @Schema(description = "璁″垝鏁伴噺")
+    private BigDecimal planQuantity;
+
+    @Schema(description = "瀹屾垚鏁伴噺")
+    private BigDecimal completeQuantity;
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String processName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鐢熶骇璁㈠崟鍙�")
+    private String productOrderNpsNo;
+}
diff --git a/src/main/java/com/ruoyi/home/dto/ProductionTurnoverDto.java b/src/main/java/com/ruoyi/home/dto/ProductionTurnoverDto.java
index 41ad82b..02fdcd3 100644
--- a/src/main/java/com/ruoyi/home/dto/ProductionTurnoverDto.java
+++ b/src/main/java/com/ruoyi/home/dto/ProductionTurnoverDto.java
@@ -1,27 +1,24 @@
 package com.ruoyi.home.dto;
-
-import com.ruoyi.production.dto.ProductOrderDto;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
 import java.util.List;
 
 @Data
-@ApiModel
+@Schema
 public class ProductionTurnoverDto {
-    @ApiModelProperty("鎬诲湪鍒舵暟閲�")
+    @Schema(description = "鎬诲湪鍒舵暟閲�")
     private Long totalOrderCount;
 
-    @ApiModelProperty("骞冲潎鍛ㄨ浆澶╂暟")
+    @Schema(description = "骞冲潎鍛ㄨ浆澶╂暟")
     private BigDecimal averageTurnoverDays;
-    @ApiModelProperty("鍛ㄨ浆鏁堢巼")
+    @Schema(description = "鍛ㄨ浆鏁堢巼")
     private BigDecimal turnoverEfficiency;
 
-    @ApiModelProperty("宸ュ簭璇︽儏")
+    @Schema(description = "宸ュ簭璇︽儏")
     private List<String> processDetails;
 
-    @ApiModelProperty("宸ュ簭瀵瑰簲鐨勬暟閲忚鎯�")
+    @Schema(description = "宸ュ簭瀵瑰簲鐨勬暟閲忚鎯�")
     private List<Long> processQuantityDetails;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/QualityStatisticsDto.java b/src/main/java/com/ruoyi/home/dto/QualityStatisticsDto.java
index 970449a..16850b5 100644
--- a/src/main/java/com/ruoyi/home/dto/QualityStatisticsDto.java
+++ b/src/main/java/com/ruoyi/home/dto/QualityStatisticsDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -12,16 +11,16 @@
  * @date : 2025/7/25 11:22
  */
 @Data
-@ApiModel
+@Schema
 public class QualityStatisticsDto {
 
-    @ApiModelProperty(value = "鍘熸潗鏂欏凡妫�娴嬫暟")
+    @Schema(description = "鍘熸潗鏂欏凡妫�娴嬫暟")
     private BigDecimal supplierNum;
 
-    @ApiModelProperty(value = "鍑哄巶宸叉娴嬫暟")
+    @Schema(description = "鍑哄巶宸叉娴嬫暟")
     private BigDecimal factoryNum;
 
-    @ApiModelProperty(value = "杩囩▼宸叉娴嬫暟")
+    @Schema(description = "杩囩▼宸叉娴嬫暟")
     private BigDecimal processNum;
 
     private List<QualityStatisticsItem> item;
diff --git a/src/main/java/com/ruoyi/home/dto/QualityStatisticsItem.java b/src/main/java/com/ruoyi/home/dto/QualityStatisticsItem.java
index 38ca74a..35bc14a 100644
--- a/src/main/java/com/ruoyi/home/dto/QualityStatisticsItem.java
+++ b/src/main/java/com/ruoyi/home/dto/QualityStatisticsItem.java
@@ -1,7 +1,6 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -11,16 +10,16 @@
  * @date : 2025/7/25 11:27
  */
 @Data
-@ApiModel
+@Schema
 public class QualityStatisticsItem {
 
-    @ApiModelProperty(value = "鍘熸潗鏂欎笉鍚堟牸鏁�")
+    @Schema(description = "鍘熸潗鏂欎笉鍚堟牸鏁�")
     private BigDecimal supplierNum;
 
-    @ApiModelProperty(value = "鍑哄巶涓嶅悎鏍兼暟")
+    @Schema(description = "鍑哄巶涓嶅悎鏍兼暟")
     private BigDecimal factoryNum;
 
-    @ApiModelProperty(value = "杩囩▼涓嶅悎鏍兼暟")
+    @Schema(description = "杩囩▼涓嶅悎鏍兼暟")
     private BigDecimal processNum;
 
     private String date;
diff --git a/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java b/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
index c929543..a16390c 100644
--- a/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
+++ b/src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -11,19 +10,19 @@
  * @date : 2025/7/25 13:34
  */
 @Data
-@ApiModel
+@Schema
 public class StatisticsReceivablePayableDto {
 
-    @ApiModelProperty("搴旀敹閲戦")
+    @Schema(description = "搴旀敹閲戦")
     private BigDecimal receivableMoney;
 
-    @ApiModelProperty("搴斾粯閲戦")
+    @Schema(description = "搴斾粯閲戦")
     private BigDecimal payableMoney;
 
-    @ApiModelProperty("棰勬敹閲戦")
+    @Schema(description = "棰勬敹閲戦")
     private BigDecimal advanceMoney;
 
-    @ApiModelProperty("棰勪粯閲戦")
+    @Schema(description = "棰勪粯閲戦")
     private BigDecimal prepayMoney;
 
 }
diff --git a/src/main/java/com/ruoyi/home/dto/SupplierPurchaseRankingDto.java b/src/main/java/com/ruoyi/home/dto/SupplierPurchaseRankingDto.java
index db9c370..a397b24 100644
--- a/src/main/java/com/ruoyi/home/dto/SupplierPurchaseRankingDto.java
+++ b/src/main/java/com/ruoyi/home/dto/SupplierPurchaseRankingDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -10,12 +9,12 @@
  * 渚涘簲鍟嗛噰璐帓鍚岲TO
  */
 @Data
-@ApiModel("渚涘簲鍟嗛噰璐帓鍚�")
+@Schema(name = "渚涘簲鍟嗛噰璐帓鍚�")
 public class SupplierPurchaseRankingDto {
 
-    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    @Schema(description = "渚涘簲鍟嗗悕绉�")
     private String supplierName;
 
-    @ApiModelProperty("閲囪喘鎬婚噾棰�")
+    @Schema(description = "閲囪喘鎬婚噾棰�")
     private BigDecimal totalAmount;
 }
diff --git a/src/main/java/com/ruoyi/home/dto/WorkOrderEfficiencyDto.java b/src/main/java/com/ruoyi/home/dto/WorkOrderEfficiencyDto.java
index b9eb5fb..012a097 100644
--- a/src/main/java/com/ruoyi/home/dto/WorkOrderEfficiencyDto.java
+++ b/src/main/java/com/ruoyi/home/dto/WorkOrderEfficiencyDto.java
@@ -1,24 +1,23 @@
 package com.ruoyi.home.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
 
 @Data
-@ApiModel("宸ュ崟鎵ц鏁堢巼鍒嗘瀽Dto")
+@Schema(name = "宸ュ崟鎵ц鏁堢巼鍒嗘瀽Dto")
 public class WorkOrderEfficiencyDto {
 
-    @ApiModelProperty(value = "鏃ユ湡")
+    @Schema(description = "鏃ユ湡")
     private String date;
 
-    @ApiModelProperty(value = "寮�宸ユ暟閲�")
+    @Schema(description = "寮�宸ユ暟閲�")
     private BigDecimal startQuantity;
 
-    @ApiModelProperty(value = "瀹屽伐鏁伴噺")
+    @Schema(description = "瀹屽伐鏁伴噺")
     private BigDecimal finishQuantity;
 
-    @ApiModelProperty(value = "鑹搧鐜�")
+    @Schema(description = "鑹搧鐜�")
     private String yieldRate;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
index 2d3e608..e01927c 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3,16 +3,13 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.mapper.AccountExpenseMapper;
 import com.ruoyi.account.mapper.AccountIncomeMapper;
 import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.home.mapper.HomeMapper;
-import com.ruoyi.account.mapper.AccountExpenseMapper;
 import com.ruoyi.approve.mapper.ApproveProcessMapper;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.basic.mapper.CustomerMapper;
 import com.ruoyi.basic.mapper.ProductMapper;
-import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.mapper.SupplierManageMapper;
 import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.pojo.Product;
@@ -27,20 +24,10 @@
 import com.ruoyi.dto.MapDto;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.home.dto.*;
+import com.ruoyi.home.mapper.HomeMapper;
 import com.ruoyi.home.service.HomeService;
-import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
-import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
-import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.dto.ProductOrderDto;
-import com.ruoyi.production.dto.ProductWorkOrderDto;
-import com.ruoyi.production.mapper.ProductOrderMapper;
-import com.ruoyi.production.mapper.ProductProcessMapper;
-import com.ruoyi.production.mapper.ProductWorkOrderMapper;
-import com.ruoyi.production.mapper.ProductionProductInputMapper;
-import com.ruoyi.production.mapper.ProductionProductOutputMapper;
-import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper;
-import com.ruoyi.production.pojo.ProductProcess;
-import com.ruoyi.production.pojo.ProductWorkOrder;
+import com.ruoyi.production.bean.dto.ProductionProductOutputDto;
+import com.ruoyi.production.mapper.*;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
@@ -60,8 +47,8 @@
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.StaffOnJob;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
@@ -81,76 +68,56 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class HomeServiceImpl implements HomeService {
 
-    @Autowired
-    private SalesLedgerMapper salesLedgerMapper;
+    private final SalesLedgerMapper salesLedgerMapper;
 
-    @Autowired
-    private PurchaseLedgerMapper purchaseLedgerMapper;
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
 
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
 
-    @Autowired
-    private StockInventoryMapper stockInventoryMapper;
+    private final StockInventoryMapper stockInventoryMapper;
 
-    @Autowired
-    private QualityInspectMapper qualityStatisticsMapper;
+    private final QualityInspectMapper qualityStatisticsMapper;
 
-    @Autowired
-    private ApproveProcessMapper approveProcessMapper;
+    private final ApproveProcessMapper approveProcessMapper;
 
-    @Autowired
-    private ReceiptPaymentMapper receiptPaymentMapper;
+    private final ReceiptPaymentMapper receiptPaymentMapper;
 
-    @Autowired
-    private PaymentRegistrationMapper paymentRegistrationMapper;
+    private final PaymentRegistrationMapper paymentRegistrationMapper;
 
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
+    private final SysDeptMapper sysDeptMapper;
 
-    @Autowired
-    private NoticeMapper noticeMapper;
+    private final NoticeMapper noticeMapper;
 
-    @Autowired
-    private ProductOrderMapper productOrderMapper;
+    private final ProductionOrderMapper productionOrderMapper;
 
-    @Autowired
-    private ProductWorkOrderMapper productWorkOrderMapper;
+    private final ProductMapper productMapper;
 
-    @Autowired
-    private ProductMapper productMapper;
+    private final StaffOnJobMapper staffOnJobMapper;
 
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
+    private final CustomerMapper customerMapper;
 
-    @Autowired
-    private CustomerMapper customerMapper;
+    private final SupplierManageMapper supplierManageMapper;
 
-    @Autowired
-    private SupplierManageMapper supplierManageMapper;
+    private final HomeMapper homeMapper;
 
-    @Autowired
-    private HomeMapper homeMapper;
+    private final ProductionProductOutputMapper productionProductOutputMapper;
 
-    @Autowired
-    private ProductionProductOutputMapper productionProductOutputMapper;
+    private final QualityInspectMapper qualityInspectMapper;
 
-    @Autowired
-    private QualityInspectMapper qualityInspectMapper;
+    private final QualityUnqualifiedMapper qualityUnqualifiedMapper;
 
-    @Autowired
-    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
+    private final ProductionOperationTaskMapper productionOperationTaskMapper;
 
-    @Autowired
-    private ProductProcessMapper productProcessMapper;
-    
-    @Autowired
-    private AccountExpenseMapper accountExpenseMapper;
+    private final AccountExpenseMapper accountExpenseMapper;
 
-    @Autowired
-    private AccountIncomeMapper accountIncomeMapper;
+    private final AccountIncomeMapper accountIncomeMapper;
+
+    private final ProductionAccountMapper productionAccountMapper;
+
+    private final ProductionProductInputMapper productionProductInputMapper;
 
     @Override
     public HomeBusinessDto business() {
@@ -527,7 +494,7 @@
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
     }
 
-    @Autowired
+
     private DeviceRepairMapper deviceRepairMapper;
 
     @Override
@@ -560,18 +527,15 @@
     @Override
     public ProductionProgressDto productionProgress() {
         ProductionProgressDto productionProgressDto = new ProductionProgressDto();
-        ProductOrderDto orderDto = new ProductOrderDto();
-        orderDto.setStartTime(LocalDateTime.now().minusMonths(1));
-        orderDto.setEndTime(LocalDateTime.now());
-        List<ProductOrderDto> productOrderDtos = productOrderMapper.pageProductOrder(new Page<>(1, -1), orderDto)
-                .getRecords();
-        productionProgressDto.setCompletedOrderDetails(productOrderDtos);
-        long totalCount = productOrderDtos.size();
-        long count = productOrderDtos.stream().filter(
-                        productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(productOrderDto.getQuantity()) >= 0)
+        List<ProductionProgressOrderDto> orderDetails = productionOrderMapper.selectProgressOrders(
+                LocalDateTime.now().minusMonths(1), LocalDateTime.now());
+        productionProgressDto.setCompletedOrderDetails(orderDetails);
+        long totalCount = orderDetails.size();
+        long count = orderDetails.stream().filter(
+                        item -> defaultDecimal(item.getCompleteQuantity()).compareTo(defaultDecimal(item.getQuantity())) >= 0)
                 .count();
-        long count2 = productOrderDtos.stream()
-                .filter(productOrderDto -> productOrderDto.getCompleteQuantity().compareTo(BigDecimal.ZERO) == 0)
+        long count2 = orderDetails.stream()
+                .filter(item -> defaultDecimal(item.getCompleteQuantity()).compareTo(BigDecimal.ZERO) == 0)
                 .count();
         productionProgressDto.setTotalOrderCount(totalCount);
         productionProgressDto.setCompletedOrderCount(count);
@@ -583,15 +547,11 @@
     @Override
     public ProductionTurnoverDto workInProcessTurnover() {
         ProductionTurnoverDto productionTurnoverDto = new ProductionTurnoverDto();
-        ProductWorkOrderDto workOrder = new ProductWorkOrderDto();
-        workOrder.setPlanStartTime(LocalDate.now().minusMonths(1));
-        workOrder.setPlanEndTime(LocalDate.now());
-        List<ProductWorkOrderDto> productWorkOrders = productWorkOrderMapper
-                .pageProductWorkOrder(new Page<>(1, -1), workOrder).getRecords();
-        long sum = productWorkOrders.stream()
-                .filter(productWorkOrder -> productWorkOrder.getPlanQuantity()
-                        .compareTo(productWorkOrder.getCompleteQuantity()) > 0)
-                .map(ProductWorkOrder::getPlanQuantity)
+        List<ProductionTaskStatisticsDto> taskList = productionOperationTaskMapper
+                .selectTaskStatisticsByDate(LocalDate.now().minusMonths(1), LocalDate.now());
+        long sum = taskList.stream()
+                .filter(task -> defaultDecimal(task.getPlanQuantity()).compareTo(defaultDecimal(task.getCompleteQuantity())) > 0)
+                .map(ProductionTaskStatisticsDto::getPlanQuantity)
                 .mapToLong(BigDecimal::longValue)
                 .sum();
         if (sum == 0)
@@ -600,23 +560,21 @@
         productionTurnoverDto.setAverageTurnoverDays(BigDecimal.valueOf(sum).divide(
                 BigDecimal.valueOf(ChronoUnit.DAYS.between(LocalDateTime.now().minusMonths(1), LocalDateTime.now())), 2,
                 RoundingMode.HALF_UP));
-        long completeQuantity = productWorkOrders.stream()
-                .filter(productWorkOrder -> productWorkOrder.getCompleteQuantity()
-                        .compareTo(productWorkOrder.getPlanQuantity()) >= 0)
-                .map(ProductWorkOrder::getCompleteQuantity)
+        long completeQuantity = taskList.stream()
+                .filter(task -> defaultDecimal(task.getCompleteQuantity()).compareTo(defaultDecimal(task.getPlanQuantity())) >= 0)
+                .map(ProductionTaskStatisticsDto::getCompleteQuantity)
                 .mapToLong(BigDecimal::longValue)
                 .sum();
         productionTurnoverDto.setTurnoverEfficiency(
                 BigDecimal.valueOf(completeQuantity).divide(BigDecimal.valueOf(sum), 2, RoundingMode.HALF_UP));
-        Map<String, List<ProductWorkOrderDto>> map = productWorkOrders.stream()
-                .filter(productWorkOrder -> productWorkOrder.getPlanQuantity()
-                        .compareTo(productWorkOrder.getCompleteQuantity()) > 0)
-                .collect(Collectors.groupingBy(ProductWorkOrderDto::getProcessName));
+        Map<String, List<ProductionTaskStatisticsDto>> map = taskList.stream()
+                .filter(task -> defaultDecimal(task.getPlanQuantity()).compareTo(defaultDecimal(task.getCompleteQuantity())) > 0)
+                .collect(Collectors.groupingBy(ProductionTaskStatisticsDto::getProcessName));
         List<String> strings = new ArrayList<>();
         List<Long> processQuantityDetails = new ArrayList<>();
         map.entrySet().stream().forEach(entry -> {
             String key = entry.getKey();
-            long completeSum = entry.getValue().stream().map(ProductWorkOrderDto::getCompleteQuantity)
+            long completeSum = entry.getValue().stream().map(ProductionTaskStatisticsDto::getCompleteQuantity)
                     .mapToLong(BigDecimal::longValue).sum();
             strings.add(key);
             processQuantityDetails.add(completeSum);
@@ -1511,9 +1469,6 @@
         return dto;
     }
 
-    @Autowired
-    private ProductionProductInputMapper productionProductInputMapper;
-
     @Override
     public List<InputOutputAnalysisDto> inputOutputAnalysis(Integer type) {
         LocalDate today = LocalDate.now();
@@ -1544,7 +1499,8 @@
         String endStr = endDate.atStartOfDay()
                 .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
 
-        List<Map<String, Object>> inputList = productionProductInputMapper.selectInputStats(startStr, endStr);
+//        List<Map<String, Object>> inputList = productionProductInputMapper.selectInputStats(startStr, endStr);
+        List<Map<String, Object>> inputList = null;
         List<Map<String, Object>> outputList = productionProductOutputMapper.selectDailyOutputStats(startStr, endStr);
 
         Map<String, InputOutputAnalysisDto> dateMap = new HashMap<>();
@@ -1610,12 +1566,7 @@
                 break;
         }
 
-        ProductWorkOrderDto queryDto = new ProductWorkOrderDto();
-        queryDto.setPlanStartTime(startDate);
-        queryDto.setPlanEndTime(endDate);
-
-        List<ProductWorkOrderDto> list = productWorkOrderMapper.pageProductWorkOrder(new Page<>(1, -1), queryDto)
-                .getRecords();
+        List<ProductionTaskStatisticsDto> list = productionOperationTaskMapper.selectTaskStatisticsByDate(startDate, endDate);
 
         if (CollectionUtils.isEmpty(list)) {
             return new ArrayList<>();
@@ -1624,9 +1575,9 @@
         Map<String, BigDecimal> processOutputMap = list.stream()
                 .filter(item -> item.getProcessName() != null && item.getCompleteQuantity() != null)
                 .collect(Collectors.groupingBy(
-                        ProductWorkOrderDto::getProcessName,
+                        ProductionTaskStatisticsDto::getProcessName,
                         Collectors.reducing(BigDecimal.ZERO,
-                                ProductWorkOrderDto::getCompleteQuantity,
+                                ProductionTaskStatisticsDto::getCompleteQuantity,
                                 BigDecimal::add)));
 
         BigDecimal total = processOutputMap.values().stream()
@@ -1680,17 +1631,17 @@
         String startStr = startDate.atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
         String endStr = endDate.atTime(LocalTime.MAX).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
 
-        List<ProductWorkOrderDto> startList = productWorkOrderMapper.selectWorkOrderStartStats(startStr, endStr);
+        List<ProductionTaskStatisticsDto> startList = productionOperationTaskMapper.selectTaskStartStats(startStr, endStr);
 
-        List<com.ruoyi.production.dto.ProductionProductOutputDto> outputList = productionProductOutputMapper
+        List<ProductionProductOutputDto> outputList = productionProductOutputMapper
                 .selectOutputStats(startStr, endStr);
 
         Map<String, WorkOrderEfficiencyDto> dateMap = new HashMap<>();
 
         if (!CollectionUtils.isEmpty(startList)) {
-            for (ProductWorkOrderDto item : startList) {
-                if (item.getPlanStartTime() != null) {
-                    String date = item.getPlanStartTime().toString();
+            for (ProductionTaskStatisticsDto item : startList) {
+                if (item.getActualStartTime() != null) {
+                    String date = item.getActualStartTime().toString();
                     WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto());
                     dto.setDate(date);
                     BigDecimal qty = item.getPlanQuantity() != null ? item.getPlanQuantity() : BigDecimal.ZERO;
@@ -1702,7 +1653,7 @@
 
         // 瀹屽伐鏁伴噺鍜岃壇鍝佺巼
         if (!CollectionUtils.isEmpty(outputList)) {
-            for (com.ruoyi.production.dto.ProductionProductOutputDto item : outputList) {
+            for (ProductionProductOutputDto item : outputList) {
                 if (item.getCreateTime() != null) {
                     String date = item.getCreateTime().toLocalDate().toString();
                     WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto());
@@ -1775,8 +1726,6 @@
                 .collect(Collectors.toList());
     }
 
-    @Autowired
-    private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
 
     @Override
     public List<ProductionAccountingDto> productionAccountingAnalysis(Integer type) {
@@ -1805,7 +1754,7 @@
 
         String endStr = endDate.plusDays(1).atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
 
-        List<Map<String, Object>> wagesList = salesLedgerProductionAccountingMapper.selectDailyWagesStats(startStr,
+        List<Map<String, Object>> wagesList = productionAccountMapper.selectDailyWagesStats(startStr,
                 endStr);
 
         if (CollectionUtils.isEmpty(wagesList)) {
@@ -1841,16 +1790,16 @@
         String lastEnd = lastMonthDate.withDayOfMonth(lastMonthDate.lengthOfMonth()).atTime(LocalTime.MAX)
                 .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
 
-        int currentCreated = productOrderMapper.countCreated(currentStart, currentEnd);
-        int lastCreated = productOrderMapper.countCreated(lastStart, lastEnd);
+        int currentCreated = productionOrderMapper.countCreated(currentStart, currentEnd);
+        int lastCreated = productionOrderMapper.countCreated(lastStart, lastEnd);
         MapDto createdDto = createOrderCountDto("鐢熶骇璁㈠崟鏁�", currentCreated, lastCreated);
 
-        int currentCompleted = productOrderMapper.countCompleted(currentStart, currentEnd);
-        int lastCompleted = productOrderMapper.countCompleted(lastStart, lastEnd);
+        int currentCompleted = productionOrderMapper.countCompleted(currentStart, currentEnd);
+        int lastCompleted = productionOrderMapper.countCompleted(lastStart, lastEnd);
         MapDto completedDto = createOrderCountDto("宸插畬鎴愯鍗曟暟", currentCompleted, lastCompleted);
 
-        int currentPending = productOrderMapper.countPending(currentStart, currentEnd);
-        int lastPending = productOrderMapper.countPending(lastStart, lastEnd);
+        int currentPending = productionOrderMapper.countPending(currentStart, currentEnd);
+        int lastPending = productionOrderMapper.countPending(lastStart, lastEnd);
         MapDto pendingDto = createOrderCountDto("寰呯敓浜ц鍗曟暟", currentPending, lastPending);
 
         return Arrays.asList(createdDto, completedDto, pendingDto);
@@ -2510,6 +2459,10 @@
         LocalDateTime startDateTime = startDate.atStartOfDay();
         LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);
 
-        return productProcessMapper.calculateProductionStatistics(startDateTime, endDateTime, userId, processIds);
+        return productionOperationTaskMapper.calculateProductionStatistics(startDateTime, endDateTime, userId, processIds);
+    }
+
+    private BigDecimal defaultDecimal(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value;
     }
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java b/src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java
index 40445d1..be8dda5 100644
--- a/src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java
@@ -8,13 +8,13 @@
 import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
 import com.ruoyi.inspectiontask.pojo.InspectionTask;
 import com.ruoyi.inspectiontask.service.InspectionTaskService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 /**
@@ -22,20 +22,20 @@
  * @date : 2025/9/19 10:52
  */
 @RestController
-@Api(tags = "宸℃浠诲姟璁板綍")
+@Tag(name = "宸℃浠诲姟璁板綍")
 @RequestMapping("/inspectionTask")
+@AllArgsConstructor
 public class InspectionTaskController extends BaseController {
 
-    @Autowired
     private InspectionTaskService inspectionTaskService;
 
     /**
      * 宸℃浠诲姟琛ㄨ〃鏌ヨ
      */
     @GetMapping("/list")
-    @ApiOperation("宸℃浠诲姟琛ㄨ〃鏌ヨ")
+    @Operation(summary = "宸℃浠诲姟琛ㄨ〃鏌ヨ")
     public R<IPage<InspectionTaskDto>> list(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
-        IPage<InspectionTaskDto> list = inspectionTaskService.selectInspectionTaskList(page,inspectionTaskDto);
+        IPage<InspectionTaskDto> list = inspectionTaskService.selectInspectionTaskList(page, inspectionTaskDto);
         return R.ok(list);
     }
 
@@ -44,11 +44,11 @@
      * 瀵煎嚭
      */
     @PostMapping("/export")
-    @ApiOperation(value = "瀵煎嚭瀹氭椂浠诲姟璁板綍")
+    @Operation(summary = "瀵煎嚭瀹氭椂浠诲姟璁板綍")
     public void export(HttpServletResponse response) {
-        Page page = new Page<>(-1,-1);
+        Page page = new Page<>(-1, -1);
         InspectionTaskDto timingTask = new InspectionTaskDto();
-        IPage<InspectionTaskDto> list = inspectionTaskService.selectInspectionTaskList(page,timingTask);
+        IPage<InspectionTaskDto> list = inspectionTaskService.selectInspectionTaskList(page, timingTask);
         ExcelUtil<InspectionTaskDto> util = new ExcelUtil<>(InspectionTaskDto.class);
         util.exportExcel(response, list.getRecords(), "瀵煎嚭瀹氭椂浠诲姟璁板綍");
     }
@@ -57,9 +57,9 @@
      * 宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
      */
     @PostMapping("/addOrEditInspectionTask")
-    @ApiOperation("宸℃浠诲姟琛ㄦ柊澧炰慨鏀�")
+    @Operation(summary = "宸℃浠诲姟琛ㄦ柊澧炰慨鏀�")
     @Transactional(rollbackFor = Exception.class)
-    public R addOrEditInspectionTask(@RequestBody InspectionTaskDto inspectionTaskDto) throws IOException {
+    public R addOrEditInspectionTask(@RequestBody InspectionTaskDto inspectionTaskDto) {
         return R.ok(inspectionTaskService.addOrEditInspectionTask(inspectionTaskDto));
     }
 
@@ -67,7 +67,7 @@
      * 宸℃浠诲姟琛ㄥ垹闄�
      */
     @DeleteMapping("/delInspectionTask")
-    @ApiOperation("宸℃浠诲姟琛ㄥ垹闄�")
+    @Operation(summary = "宸℃浠诲姟琛ㄥ垹闄�")
     @Transactional(rollbackFor = Exception.class)
     public R remove(@RequestBody Long[] ids) {
         return R.ok(inspectionTaskService.delByIds(ids));
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java
index 4ebc473..9baaf09 100644
--- a/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java
@@ -7,9 +7,9 @@
 import com.ruoyi.inspectiontask.dto.QrCodeDto;
 import com.ruoyi.inspectiontask.pojo.QrCode;
 import com.ruoyi.inspectiontask.service.QrCodeService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 /**
@@ -17,18 +17,18 @@
  * @date : 2025/9/19 10:52
  */
 @RestController
-@Api(tags = "浜岀淮鐮佺鐞�")
+@Tag(name = "浜岀淮鐮佺鐞�")
 @RequestMapping("/qrCode")
+@AllArgsConstructor
 public class QrCodeController extends BaseController {
 
-    @Autowired
     private QrCodeService qrCodeService;
 
     /**
      * 浜岀淮鐮佺鐞嗚〃鏌ヨ
      */
     @GetMapping("/list")
-    @ApiOperation("浜岀淮鐮佺鐞嗚〃鏌ヨ")
+    @Operation(summary = "浜岀淮鐮佺鐞嗚〃鏌ヨ")
     public R<IPage<QrCode>> list(Page page, QrCodeDto qrCodeDto) {
         IPage<QrCode> list = qrCodeService.selectQrCodeList(page, qrCodeDto);
         return R.ok(list);
@@ -38,7 +38,7 @@
      * 浜岀淮鐮佺鐞嗚〃鏂板淇敼
      */
     @PostMapping("/addOrEditQrCode")
-    @ApiOperation("浜岀淮鐮佺鐞嗚〃鏂板淇敼")
+    @Operation(summary = "浜岀淮鐮佺鐞嗚〃鏂板淇敼")
     public R<Long> addOrEditQrCode(@RequestBody QrCodeDto qrCodeDto) {
         return R.ok(qrCodeService.addOrEditQrCode(qrCodeDto));
     }
@@ -47,7 +47,7 @@
      * 浜岀淮鐮佺鐞嗚〃鍒犻櫎
      */
     @DeleteMapping("/delQrCode")
-    @ApiOperation("浜岀淮鐮佺鐞嗚〃鍒犻櫎")
+    @Operation(summary = "浜岀淮鐮佺鐞嗚〃鍒犻櫎")
     public R remove(@RequestBody Long[] ids) {
         return R.ok(qrCodeService.delByIds(ids));
     }
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java
index d2cee17..f597205 100644
--- a/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java
@@ -7,8 +7,9 @@
 import com.ruoyi.inspectiontask.dto.QrCodeScanRecordDto;
 import com.ruoyi.inspectiontask.pojo.QrCodeScanRecord;
 import com.ruoyi.inspectiontask.service.QrCodeScanRecordService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -17,18 +18,18 @@
  * @date : 2025/9/19 10:53
  */
 @RestController
-@Api(tags = "浜岀淮鐮佹壂鎻忚褰曠鐞�")
+@Tag(name = "浜岀淮鐮佹壂鎻忚褰曠鐞�")
 @RequestMapping("/qrCodeScanRecord")
+@AllArgsConstructor
 public class QrCodeScanRecordController extends BaseController {
 
-    @Autowired
     private QrCodeScanRecordService qrCodeScanRecordService;
 
     /**
      * 浜岀淮鐮佹壂鐮佽褰曡〃鏌ヨ
      */
     @GetMapping("/list")
-    @ApiOperation("浜岀淮鐮佹壂鐮佽褰曡〃鏌ヨ")
+    @Operation(summary = "浜岀淮鐮佹壂鐮佽褰曡〃鏌ヨ")
     public R<IPage<QrCodeScanRecordDto>> list(Page<QrCodeScanRecord> page, QrCodeScanRecordDto qrCodeScanRecordDto) {
         IPage<QrCodeScanRecordDto> list = qrCodeScanRecordService.selectQrCodeScanRecordList(page, qrCodeScanRecordDto);
         return R.ok(list);
@@ -38,7 +39,7 @@
      * 浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼
      */
     @PostMapping("/addOrEditQrCodeRecord")
-    @ApiOperation("浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼")
+    @Operation(summary = "浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼")
     public R addOrEditQrCodeRecord(@RequestBody QrCodeScanRecordDto qrCodeScanRecordDto) {
         return R.ok(qrCodeScanRecordService.addOrEditQrCodeRecord(qrCodeScanRecordDto));
     }
@@ -47,7 +48,7 @@
      * 浜岀淮鐮佹壂鐮佽褰曡〃鍒犻櫎
      */
     @DeleteMapping("/delSalesRecord")
-    @ApiOperation("浜岀淮鐮佹壂鐮佽褰曡〃鍒犻櫎")
+    @Operation(summary = "浜岀淮鐮佹壂鐮佽褰曡〃鍒犻櫎")
     public R remove(@RequestBody Long[] ids) {
         return R.ok(qrCodeScanRecordService.delByIds(ids));
     }
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java b/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
index ccaf969..ad2e338 100644
--- a/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
@@ -10,32 +10,30 @@
 import com.ruoyi.inspectiontask.dto.TimingTaskDto;
 import com.ruoyi.inspectiontask.pojo.TimingTask;
 import com.ruoyi.inspectiontask.service.TimingTaskService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.quartz.SchedulerException;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletResponse;
 
 /**
  * @author :yys
  * @date : 2025/9/19 10:53
  */
 @RestController
-@Api(tags = "宸℃绠$悊")
+@Tag(name = "宸℃绠$悊")
 @RequestMapping("/timingTask")
+@AllArgsConstructor
 public class TimingTaskController extends BaseController {
 
-
-    @Autowired
     private TimingTaskService timingTaskService;
 
     /**
      * 瀹氭椂宸℃浠诲姟琛ㄦ煡璇�
      */
     @GetMapping("/list")
-    @ApiOperation(value = "瀹氭椂浠诲姟鍒楄〃")
+    @Operation(summary = "瀹氭椂浠诲姟鍒楄〃")
     public R<IPage<TimingTaskDto>> list(Page<TimingTask> page, TimingTask timingTask) {
         IPage<TimingTaskDto> list = timingTaskService.selectTimingTaskList(page,timingTask);
         return R.ok(list);
@@ -45,7 +43,7 @@
      * 瀵煎嚭
      */
     @PostMapping("/export")
-    @ApiOperation(value = "瀵煎嚭瀹氭椂浠诲姟")
+    @Operation(summary = "瀵煎嚭瀹氭椂浠诲姟")
     public void export(HttpServletResponse response) {
         Page page = new Page<>(-1,-1);
         TimingTaskDto timingTask = new TimingTaskDto();
@@ -58,7 +56,7 @@
      * 瀹氭椂宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
      */
     @PostMapping("/addOrEditTimingTask")
-    @ApiOperation(value = "鏂板淇敼瀹氭椂浠诲姟")
+    @Operation(summary = "鏂板淇敼瀹氭椂浠诲姟")
     @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
     public R addOrEditTimingTask(@RequestBody TimingTaskDto timingTaskDto) throws SchedulerException {
         return R.ok(timingTaskService.addOrEditTimingTask(timingTaskDto));
@@ -68,7 +66,7 @@
      * 瀹氭椂宸℃浠诲姟琛ㄥ垹闄�
      */
     @DeleteMapping("/delTimingTask")
-    @ApiOperation(value = "鍒犻櫎瀹氭椂浠诲姟")
+    @Operation(summary = "鍒犻櫎瀹氭椂浠诲姟")
     @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
     public R remove(@RequestBody Long[] ids) {
         return R.ok(timingTaskService.delByIds(ids));
diff --git a/src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java b/src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java
index 87e3e61..a207cde 100644
--- a/src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java
+++ b/src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java
@@ -1,9 +1,8 @@
 package com.ruoyi.inspectiontask.dto;
 
 import com.ruoyi.basic.dto.StorageBlobDTO;
-import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.inspectiontask.pojo.InspectionTask;
-import com.ruoyi.sales.pojo.CommonFile;
 import lombok.Data;
 
 import java.util.List;
@@ -18,9 +17,12 @@
 //
 //    private List<StorageAttachment> attachments;
 
-    private List<String> tempFileIds;
-    private List<CommonFile> commonFileList; //鐢熶骇涓�
-    private List<CommonFile> commonFileListAfter;  //鐢熶骇鍚�
-    private List<CommonFile> commonFileListBefore; //鐢熶骇鍓�
+    private List<StorageBlobDTO> commonFileListDTO; //鐢熶骇涓�
+    private List<StorageBlobDTO> commonFileListAfterDTO; //鐢熶骇鍚�
+    private List<StorageBlobDTO> commonFileListBeforeDTO; //鐢熶骇鍓�
+
+    private List<StorageBlobVO> commonFileListVO; //鐢熶骇涓�
+    private List<StorageBlobVO> commonFileListAfterVO; //鐢熶骇鍚�
+    private List<StorageBlobVO> commonFileListBeforeVO; //鐢熶骇鍓�
 
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java b/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java
index 4247330..6e5fd22 100644
--- a/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java
+++ b/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java
@@ -1,7 +1,7 @@
 package com.ruoyi.inspectiontask.dto;
 
 
-import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.inspectiontask.pojo.QrCode;
 import com.ruoyi.inspectiontask.pojo.QrCodeScanRecord;
 import lombok.Data;
@@ -15,6 +15,6 @@
 
     private String scanner;
 
-    private List<StorageBlobDTO> storageBlobDTO;
+    private List<StorageBlobVO> storageBlobVO;
 
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java b/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
index 4d95a96..c41d626 100644
--- a/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -15,7 +14,7 @@
  * @date : 2025/9/19 10:25
  */
 @Data
-@ApiModel
+@Schema
 @TableName("inspection_task")
 public class InspectionTask {
 
@@ -27,68 +26,71 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "宸℃浠诲姟鍚嶇О")
     private String taskName;
 
-    @ApiModelProperty(value = "璁惧id")
+    @Schema(description = "璁惧id")
     private Integer taskId;
 
-    @ApiModelProperty(value = "宸℃浜篒D")
+    @Schema(description = "宸℃浜篒D")
     private String inspectorId;
 
-    @ApiModelProperty(value = "鎵ц宸℃鐨勪汉鍛樺鍚�")
+    @Schema(description = "鎵ц宸℃鐨勪汉鍛樺鍚�")
     @Excel(name = "鎵ц宸℃浜哄憳")
     private String inspector;
 
-    @ApiModelProperty(value = "浠诲姟闄勫姞璇存槑鎴栫壒娈婃儏鍐佃褰�")
+    @Schema(description = "浠诲姟闄勫姞璇存槑鎴栫壒娈婃儏鍐佃褰�")
     @Excel(name = "澶囨敞")
     private String remarks;
 
-    @ApiModelProperty(value = "浠诲姟鐧昏浜篒D")
+    @Schema(description = "浠诲姟鐧昏浜篒D")
     private Long registrantId;
 
-    @ApiModelProperty(value = "浠诲姟鐧昏浜哄鍚�")
+    @Schema(description = "浠诲姟鐧昏浜哄鍚�")
     @Excel(name = "鐧昏浜�")
     private String registrant;
 
-    @ApiModelProperty(value = "棰戞")
+    @Schema(description = "棰戞")
     @Excel(name = "棰戞")
     private String frequencyType;
 
-    @ApiModelProperty(value = "鏃堕棿缁嗚妭")
+    @Schema(description = "鏃堕棿缁嗚妭")
     @Excel(name = "寮�濮嬫棩鏈熶笌鏃堕棿")
     private String frequencyDetail;
 
-    @ApiModelProperty(value = "宸℃鍦扮偣璇︾粏鎻忚堪")
+    @Schema(description = "宸℃鍦扮偣璇︾粏鎻忚堪")
     private String inspectionLocation;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @Schema(description = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
-    @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+    @Schema(description = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+    @Schema(description = "璁板綍鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "鐧昏鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+    @Schema(description = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+    @Schema(description = "璁板綍鏈�鍚庢洿鏂版椂闂�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "绉熸埛")
+    @Schema(description = "绉熸埛")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
     @TableField(exist = false)
     private String dateStr;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java
index 2065e2e..6c3ef6b 100644
--- a/src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java
@@ -1,12 +1,12 @@
 package com.ruoyi.inspectiontask.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -17,7 +17,7 @@
  * @date : 2025/9/19 10:29
  */
 @Data
-@ApiModel
+@Schema
 @TableName("qr_code")
 public class QrCode {
 
@@ -29,35 +29,38 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     private String deviceName;
 
-    @ApiModelProperty(value = "鎵�鍦ㄤ綅缃弿杩�")
+    @Schema(description = "鎵�鍦ㄤ綅缃弿杩�")
     private String location;
 
-    @ApiModelProperty(value = "绉熸埛ID锛岀敤浜庡绉熸埛闅旂")
+    @Schema(description = "绉熸埛ID锛岀敤浜庡绉熸埛闅旂")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @Schema(description = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
-    @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+    @Schema(description = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+    @Schema(description = "璁板綍鍒涘缓鏃堕棿")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+    @Schema(description = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+    @Schema(description = "璁板綍鏈�鍚庢洿鏂版椂闂�")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java
index 6bc1b4b..86e5c7b 100644
--- a/src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java
@@ -2,8 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -15,7 +14,7 @@
  */
 @Data
 @TableName("qr_code_scan_record")
-@ApiModel
+@Schema
 public class QrCodeScanRecord {
 
     private static final long serialVersionUID = 1L;
@@ -26,19 +25,19 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鍏宠仈鐨勪簩缁寸爜ID")
+    @Schema(description = "鍏宠仈鐨勪簩缁寸爜ID")
     private Long qrCodeId;
 
-    @ApiModelProperty(value = "鎵爜浜虹敤鎴稩D")
+    @Schema(description = "鎵爜浜虹敤鎴稩D")
     private Long scannerId;
 
-    @ApiModelProperty(value = "璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     private String deviceName;
 
-    @ApiModelProperty(value = "璁惧id")
+    @Schema(description = "璁惧id")
     private Integer deviceId;
 
-    @ApiModelProperty(value = "瀹為檯鎵爜鏃堕棿")
+    @Schema(description = "瀹為檯鎵爜鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime scanTime;
@@ -49,25 +48,28 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @Schema(description = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
-    @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+    @Schema(description = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+    @Schema(description = "璁板綍鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+    @Schema(description = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+    @Schema(description = "璁板綍鏈�鍚庢洿鏂版椂闂�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
index fb852be..2d8722e 100644
--- a/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
@@ -1,12 +1,12 @@
 package com.ruoyi.inspectiontask.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDate;
@@ -17,7 +17,7 @@
  * @date : 2025/9/19 10:27
  */
 @Data
-@ApiModel
+@Schema
 @TableName("timing_task")
 public class TimingTask {
 
@@ -29,81 +29,84 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "宸℃浠诲姟鍚嶇О")
     private String taskName;
 
-    @ApiModelProperty(value = "璁惧id")
+    @Schema(description = "璁惧id")
     private Integer taskId;
 
-    @ApiModelProperty(value = "宸℃浜�")
+    @Schema(description = "宸℃浜�")
     @Excel(name = "鎵ц宸℃浜�")
     private String inspectorIds;
 
-    @ApiModelProperty(value = "宸℃鍦扮偣")
+    @Schema(description = "宸℃鍦扮偣")
     private String inspectionLocation;
 
-    @ApiModelProperty(value = "棰戞")
+    @Schema(description = "棰戞")
     @Excel(name = "棰戞")
     private String frequencyType;
 
-    @ApiModelProperty(value = "棰戞璇︽儏")
+    @Schema(description = "棰戞璇︽儏")
     @Excel(name = "寮�濮嬫棩鏈熶笌鏃堕棿")
     private String frequencyDetail;
 
-    @ApiModelProperty(value = "涓嬫鎵ц鏃堕棿")
+    @Schema(description = "涓嬫鎵ц鏃堕棿")
     private LocalDateTime nextExecutionTime;
 
-    @ApiModelProperty(value = "鏈�鍚庢墽琛屾椂闂�")
+    @Schema(description = "鏈�鍚庢墽琛屾椂闂�")
     private LocalDateTime lastExecutionTime;
 
-    @ApiModelProperty(value = "鏄惁婵�娲�")
+    @Schema(description = "鏄惁婵�娲�")
     private boolean isActive;
 
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     @Excel(name = "澶囨敞")
     private String remarks;
 
-    @ApiModelProperty(value = "鐧昏浜篿d")
+    @Schema(description = "鐧昏浜篿d")
     private Long registrantId;
 
-    @ApiModelProperty(value = "鐧昏浜�")
+    @Schema(description = "鐧昏浜�")
     @Excel(name = "鐧昏浜�")
     private String registrant;
 
-    @ApiModelProperty(value = "鐧昏鏃ユ湡")
+    @Schema(description = "鐧昏鏃ユ湡")
     @Excel(name = "鐧昏鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private LocalDate registrationDate;
 
-    @ApiModelProperty(value = "鐘舵��")
+    @Schema(description = "鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @Schema(description = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
     @TableField(exist = false)
     private String dateStr;
 
-    @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+    @Schema(description = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+    @Schema(description = "璁板綍鍒涘缓鏃堕棿")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
 //    @JsonFormat(pattern = "yyyy-MM-dd")
 //    @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+    @Schema(description = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+    @Schema(description = "璁板綍鏈�鍚庢洿鏂版椂闂�")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java b/src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java
index 72ca5e4..de175f2 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java
@@ -6,8 +6,6 @@
 import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
 import com.ruoyi.inspectiontask.pojo.InspectionTask;
 
-import java.io.IOException;
-
 /**
  * @author :yys
  * @date : 2025/9/19 10:49
@@ -16,7 +14,7 @@
 
     IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto);
 
-    int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto) throws IOException;
+    int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto);
 
     int delByIds(Long[] ids);
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
index 8c30cb3..410336e 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
@@ -5,14 +5,9 @@
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.dto.StorageBlobDTO;
-import com.ruoyi.basic.mapper.StorageAttachmentMapper;
-import com.ruoyi.basic.mapper.StorageBlobMapper;
-import com.ruoyi.basic.pojo.StorageAttachment;
-import com.ruoyi.basic.pojo.StorageBlob;
-import com.ruoyi.basic.service.StorageAttachmentService;
-import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.common.utils.MinioUtils;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
@@ -22,22 +17,15 @@
 import com.ruoyi.inspectiontask.service.InspectionTaskService;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
-import com.ruoyi.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.pojo.CommonFile;
-import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.io.IOException;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-
-import static com.ruoyi.common.constant.StorageAttachmentConstants.StorageAttachmentFile;
-import static com.ruoyi.common.enums.StorageAttachmentRecordType.InspectionTasks;
 
 /**
  * @author :yys
@@ -45,32 +33,15 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class InspectionTaskServiceImpl extends ServiceImpl<InspectionTaskMapper, InspectionTask> implements InspectionTaskService {
 
 
-    @Autowired
-    private InspectionTaskMapper inspectionTaskMapper;
+    private final InspectionTaskMapper inspectionTaskMapper;
 
-    @Autowired
-    private StorageAttachmentService storageAttachmentService;
+    private final SysUserMapper sysUserMapper;
 
-    @Autowired
-    private StorageBlobMapper storageBlobMapper;
-
-    @Autowired
-    private StorageAttachmentMapper storageAttachmentMapper;
-
-    @Autowired
-    private MinioUtils minioUtils;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private CommonFileMapper commonFileMapper;
-
-    @Autowired
-    private CommonFileServiceImpl commonFileService;
+    private final FileUtil fileUtil;
 
     @Override
     public IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
@@ -124,16 +95,6 @@
                         SysUser::getUserId,
                         SysUser::getNickName,
                         (existing, replacement) -> existing));
-
-        //澶勭悊闄勪欢
-        List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
-                .in(CommonFile::getCommonId, ids)
-                .in(CommonFile::getType, Arrays.asList(FileNameType.INSPECTION.getValue(), FileNameType.INSPECTION_PRODUCTION_BEFORE.getValue(), FileNameType.INSPECTION_PRODUCTION_AFTER.getValue())));
-        if(commonFiles == null){
-            commonFiles = new ArrayList<>();
-        }
-        List<CommonFile> finalCommonFiles = commonFiles;
-
         List<InspectionTaskDto> dtoList = entityPage.getRecords().stream().map(inspectionTask -> {
             InspectionTaskDto dto = new InspectionTaskDto();
             BeanUtils.copyProperties(inspectionTask, dto);  // 澶嶅埗涓诲璞″睘鎬�
@@ -160,11 +121,10 @@
             }
 
             dto.setDateStr(inspectionTask.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-
             // 鍒濆鍖栦笁涓檮浠跺垪琛�
-            dto.setCommonFileList(finalCommonFiles.stream().filter(commonFile -> commonFile.getType().equals(FileNameType.INSPECTION.getValue())).collect(Collectors.toList()));
-            dto.setCommonFileListAfter(finalCommonFiles.stream().filter(commonFile -> commonFile.getType().equals(FileNameType.INSPECTION_PRODUCTION_AFTER.getValue())).collect(Collectors.toList()));
-            dto.setCommonFileListBefore(finalCommonFiles.stream().filter(commonFile -> commonFile.getType().equals(FileNameType.INSPECTION_PRODUCTION_BEFORE.getValue())).collect(Collectors.toList()));
+            dto.setCommonFileListVO(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId()));
+            dto.setCommonFileListAfterVO(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.AFTER_FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId()));
+            dto.setCommonFileListBeforeVO(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.BEFORE_FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId()));
 
 
             return dto;
@@ -177,31 +137,9 @@
         return resultPage;
     }
 
-    // 鎻愬彇鍒涘缓BlobDTO鐨勫叕鍏辨柟娉�
-    private StorageBlobDTO createBlobDto(StorageBlob blob) {
-        StorageBlobDTO dto = new StorageBlobDTO();
-        BeanUtils.copyProperties(blob, dto);
-
-        // 璁剧疆URL
-        dto.setUrl(minioUtils.getPreviewUrls(
-                blob.getBucketFilename(),
-                blob.getBucketName(),
-                true
-        ));
-
-        // 璁剧疆涓嬭浇URL
-        dto.setDownloadUrl(minioUtils.getDownloadUrls(
-                blob.getBucketFilename(),
-                blob.getBucketName(),
-                blob.getOriginalFilename(),
-                true
-        ));
-        return dto;
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto) throws IOException {
+    public int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto) {
         InspectionTask inspectionTask = new InspectionTask();
         BeanUtils.copyProperties(inspectionTaskDto, inspectionTask);
         inspectionTask.setRegistrantId(SecurityUtils.getLoginUser().getUserId());
@@ -212,7 +150,11 @@
         } else {
             i = inspectionTaskMapper.updateById(inspectionTask);
         }
-        commonFileService.migrateTempFilesToFormal(inspectionTask.getId(),inspectionTaskDto.getTempFileIds());
+        // 淇濆瓨鏂囦欢
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId(), inspectionTaskDto.getCommonFileListDTO());
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.AFTER_FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId(), inspectionTaskDto.getCommonFileListAfterDTO());
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.BEFORE_FILE, RecordTypeEnum.INSPECTION_TASK, inspectionTask.getId(), inspectionTaskDto.getCommonFileListBeforeDTO());
+
         return i;
     }
 
@@ -223,9 +165,10 @@
         if (ids == null || ids.length == 0) {
             return 0;
         }
-        commonFileService.deleteByBusinessIds(Arrays.asList(ids),FileNameType.INSPECTION.getValue());
-        commonFileService.deleteByBusinessIds(Arrays.asList(ids),FileNameType.INSPECTION_PRODUCTION_BEFORE.getValue());
-        commonFileService.deleteByBusinessIds(Arrays.asList(ids),FileNameType.INSPECTION_PRODUCTION_AFTER.getValue());
+        // 鍒犻櫎鏂囦欢
+        fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.FILE, RecordTypeEnum.INSPECTION_TASK, Arrays.asList(ids));
+        fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.AFTER_FILE, RecordTypeEnum.INSPECTION_TASK, Arrays.asList(ids));
+        fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.BEFORE_FILE, RecordTypeEnum.INSPECTION_TASK, Arrays.asList(ids));
         return inspectionTaskMapper.deleteBatchIds(Arrays.asList(ids));
     }
 
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java
index 00ece03..acc30a7 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java
@@ -6,12 +6,15 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.basic.mapper.StorageAttachmentMapper;
 import com.ruoyi.basic.mapper.StorageBlobMapper;
 import com.ruoyi.basic.pojo.StorageAttachment;
 import com.ruoyi.basic.pojo.StorageBlob;
 import com.ruoyi.basic.service.StorageAttachmentService;
-import com.ruoyi.common.utils.MinioUtils;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.inspectiontask.dto.QrCodeScanRecordDto;
 import com.ruoyi.inspectiontask.mapper.QrCodeMapper;
@@ -21,8 +24,8 @@
 import com.ruoyi.inspectiontask.service.QrCodeScanRecordService;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
@@ -38,28 +41,23 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class QrCodeScanRecordServiceImpl extends ServiceImpl<QrCodeScanRecordMapper, QrCodeScanRecord> implements QrCodeScanRecordService {
 
-    @Autowired
-    private QrCodeScanRecordMapper qrCodeScanRecordMapper;
+    private final QrCodeScanRecordMapper qrCodeScanRecordMapper;
 
-    @Autowired
-    private QrCodeMapper qrCodeMapper;
+    private final QrCodeMapper qrCodeMapper;
 
-    @Autowired
-    private StorageAttachmentService storageAttachmentService;
+    private final StorageAttachmentService storageAttachmentService;
 
-    @Autowired
-    private StorageBlobMapper storageBlobMapper;
+    private final StorageBlobMapper storageBlobMapper;
 
-    @Autowired
-    private StorageAttachmentMapper storageAttachmentMapper;
+    private final StorageAttachmentMapper storageAttachmentMapper;
 
-    @Autowired
-    private MinioUtils minioUtils;
 
-    @Autowired
-    private SysUserMapper sysUserMapper;
+    private final SysUserMapper sysUserMapper;
+
+    private final FileUtil fileUtil;
 
     @Override
     public IPage<QrCodeScanRecordDto> selectQrCodeScanRecordList(Page<QrCodeScanRecord> page, QrCodeScanRecordDto qrCodeScanRecordDto) {
@@ -127,23 +125,24 @@
                     });
 
             // 6.2 璁剧疆闄勪欢淇℃伅
-            dto.setStorageBlobDTO(
-                    Optional.ofNullable(attachmentsMap.get(record.getId()))
-                            .orElse(Collections.emptyList())
-                            .stream()
-                            .map(att -> {
-                                StorageBlobDTO blobDTO = new StorageBlobDTO();
-                                Optional.ofNullable(blobMap.get(att.getStorageBlobId()))
-                                        .ifPresent(blob -> {
-                                            BeanUtils.copyProperties(blob, blobDTO);
-                                            blobDTO.setUrl(minioUtils.getPreviewUrls(blob.getBucketFilename(), blob.getBucketName(), true));
-                                            blobDTO.setDownloadUrl(minioUtils.getDownloadUrls(blob.getBucketFilename(),blob.getBucketName(),blob.getOriginalFilename(),true));
-                                        });
-                                return blobDTO;
-                            })
-                            .filter(blobDTO -> blobDTO.getId() != null) // 杩囨护鏃犳晥闄勪欢
-                            .collect(Collectors.toList())
-            );
+            // todo fileChange
+//            dto.setStorageBlobDTO(
+//                    Optional.ofNullable(attachmentsMap.get(record.getId()))
+//                            .orElse(Collections.emptyList())
+//                            .stream()
+//                            .map(att -> {
+//                                StorageBlobDTO blobDTO = new StorageBlobDTO();
+//                                Optional.ofNullable(blobMap.get(att.getStorageBlobId()))
+//                                        .ifPresent(blob -> {
+//                                            BeanUtils.copyProperties(blob, blobDTO);
+//                                            blobDTO.setUrl(minioUtils.getPreviewUrls(blob.getBucketFilename(), blob.getBucketName(), true));
+//                                            blobDTO.setDownloadUrl(minioUtils.getDownloadUrls(blob.getBucketFilename(),blob.getBucketName(),blob.getOriginalFilename(),true));
+//                                        });
+//                                return blobDTO;
+//                            })
+//                            .filter(blobDTO -> blobDTO.getId() != null) // 杩囨护鏃犳晥闄勪欢
+//                            .collect(Collectors.toList())
+//            );
             return dto;
         }).collect(Collectors.toList());
 
@@ -166,19 +165,16 @@
             i = qrCodeScanRecordMapper.updateById(qrCodeScanRecord);
         }
 
-        if (qrCodeScanRecordDto.getStorageBlobDTO() != null && !qrCodeScanRecordDto.getStorageBlobDTO().isEmpty()) {
-            List<StorageAttachment> attachments = new ArrayList<>();
-
-            for (StorageBlobDTO storageBlobDTO : qrCodeScanRecordDto.getStorageBlobDTO()) {
-                StorageAttachment storageAttachment = new StorageAttachment(
-                        StorageAttachmentFile,
-                        (long) QrCodeScanRecords.ordinal(),
-                        qrCodeScanRecord.getId()
-                );
-                storageAttachment.setStorageBlobDTO(storageBlobDTO);
-                attachments.add(storageAttachment);
+        if (qrCodeScanRecordDto.getStorageBlobVO() != null && !qrCodeScanRecordDto.getStorageBlobVO().isEmpty()) {
+            // vo 杞� dto
+            List<StorageBlobDTO> storageBlobDTOs = new ArrayList<>();
+            for (StorageBlobVO storageBlobVO : qrCodeScanRecordDto.getStorageBlobVO()) {
+                StorageBlobDTO storageBlobDTO = new StorageBlobDTO();
+                BeanUtils.copyProperties(storageBlobVO, storageBlobDTO);
+                storageBlobDTOs.add(storageBlobDTO);
             }
-            storageAttachmentService.saveStorageAttachment(attachments, qrCodeScanRecord.getId(), QrCodeScanRecords, StorageAttachmentFile);
+
+            fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.QR_CODE_SCAN_RECORDS, qrCodeScanRecord.getId(), storageBlobDTOs);
         }
         return i;
     }
@@ -188,4 +184,4 @@
         return qrCodeScanRecordMapper.deleteBatchIds(Arrays.asList(ids));
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java
index e88a5d1..2d1bc30 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java
@@ -9,8 +9,8 @@
 import com.ruoyi.inspectiontask.mapper.QrCodeMapper;
 import com.ruoyi.inspectiontask.pojo.QrCode;
 import com.ruoyi.inspectiontask.service.QrCodeService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Arrays;
@@ -22,10 +22,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class QrCodeServiceImpl extends ServiceImpl<QrCodeMapper, QrCode> implements QrCodeService {
 
-    @Autowired
-    private QrCodeMapper qrCodeMapper;
+    private final QrCodeMapper qrCodeMapper;
 
     @Override
     public IPage<QrCode> selectQrCodeList(Page page, QrCodeDto qrCodeDto) {
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java
index 83fc99d..1644033 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java
@@ -1,8 +1,8 @@
 package com.ruoyi.inspectiontask.service.impl;
 
+import lombok.RequiredArgsConstructor;
 import org.quartz.Scheduler;
 import org.quartz.spi.TriggerFiredBundle;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
@@ -13,14 +13,14 @@
 
 import javax.sql.DataSource;
 
+
 @Configuration
+@RequiredArgsConstructor
 public class QuartzConfig {
-    @Autowired
-    private ApplicationContext applicationContext;
+    private final ApplicationContext applicationContext;
 
     // 鍋囪宸查厤缃悕涓篸ataSource鐨勬暟鎹簮Bean
-    @Autowired
-    private DataSource dataSource;
+    private final DataSource dataSource;
 
     @Bean
     public SchedulerFactoryBean schedulerFactoryBean() {
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
index b8ffdf5..389eda9 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
@@ -1,12 +1,10 @@
 package com.ruoyi.inspectiontask.service.impl;
 
 import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
-import com.ruoyi.inspectiontask.mapper.TimingTaskMapper;
 import com.ruoyi.inspectiontask.pojo.InspectionTask;
 import com.ruoyi.inspectiontask.pojo.TimingTask;
-import com.ruoyi.inspectiontask.service.TimingTaskService;
+import lombok.RequiredArgsConstructor;
 import org.quartz.*;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Component;
@@ -22,20 +20,12 @@
 
 @Component
 @DisallowConcurrentExecution // 绂佹骞跺彂鎵ц鍚屼竴涓狫ob
+@RequiredArgsConstructor
 public class TimingTaskJob implements Job, Serializable {
     private static final long serialVersionUID = 1L; // 蹇呴』瀹氫箟搴忓垪鍖朓D
 
-    @Autowired
-    private TimingTaskMapper timingTaskMapper;
-
-    @Autowired
-    private TimingTaskService timingTaskService;
-
-    @Autowired
-    private InspectionTaskMapper inspectionTaskMapper;
-
-    @Autowired
-    private JdbcTemplate jdbcTemplate;
+    private final InspectionTaskMapper inspectionTaskMapper;
+    private final JdbcTemplate jdbcTemplate;
 
     @Override
     public void execute(JobExecutionContext context) throws JobExecutionException {
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
index 125f311..a6179f6 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
@@ -1,8 +1,8 @@
 package com.ruoyi.inspectiontask.service.impl;
 
 import com.ruoyi.inspectiontask.pojo.TimingTask;
+import lombok.RequiredArgsConstructor;
 import org.quartz.*;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalTime;
@@ -13,10 +13,10 @@
 import java.util.stream.Collectors;
 
 @Service
+@RequiredArgsConstructor
 public class TimingTaskScheduler {
 
-    @Autowired
-    private Scheduler scheduler;
+    private final Scheduler scheduler;
 
     /**
      * 娣诲姞鏂颁换鍔″埌璋冨害鍣�
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
index 6607d68..8772f48 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -7,15 +7,14 @@
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.inspectiontask.dto.TimingTaskDto;
-import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
 import com.ruoyi.inspectiontask.mapper.TimingTaskMapper;
 import com.ruoyi.inspectiontask.pojo.TimingTask;
 import com.ruoyi.inspectiontask.service.TimingTaskService;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.SchedulerException;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -30,19 +29,12 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class TimingTaskServiceImpl extends ServiceImpl<TimingTaskMapper, TimingTask> implements TimingTaskService {
 
-    @Autowired
-    private TimingTaskMapper timingTaskMapper;
-
-    @Autowired
-    private InspectionTaskMapper inspectionTaskMapper;
-
-    @Autowired
-    private TimingTaskScheduler timingTaskScheduler;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
+    private final TimingTaskMapper timingTaskMapper;
+    private final TimingTaskScheduler timingTaskScheduler;
+    private final SysUserMapper sysUserMapper;
 
 
     @Override
diff --git a/src/main/java/com/ruoyi/lavorissue/controller/LavorIssueController.java b/src/main/java/com/ruoyi/lavorissue/controller/LavorIssueController.java
index f0c861a..9b4779e 100644
--- a/src/main/java/com/ruoyi/lavorissue/controller/LavorIssueController.java
+++ b/src/main/java/com/ruoyi/lavorissue/controller/LavorIssueController.java
@@ -18,14 +18,15 @@
 import com.ruoyi.lavorissue.service.LavorIssueService;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.io.UnsupportedEncodingException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
@@ -39,22 +40,18 @@
  * @date : 2025/8/13 11:19
  */
 @RestController
-@Api(tags = "鍔充繚鍙戞斁")
+@Tag(name = "鍔充繚鍙戞斁")
 @RequestMapping("/lavorIssue")
+@AllArgsConstructor
 public class LavorIssueController extends BaseController {
 
-    @Autowired
     private LavorIssueService laborIssueService;
-
-    @Autowired
     private LavorIssueMapper lavorIssueMapper;
-
-    @Autowired
     private SysDeptMapper sysDeptMapper;
 
     @GetMapping("/listPage")
     @Log(title = "鍔充繚鍙戞斁-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("鍔充繚鍙戞斁-鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍔充繚鍙戞斁-鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, LaborIssue laborIssue){
         IPage<LaborIssue> listPage = laborIssueService.listPage(page, laborIssue);
         return AjaxResult.success(listPage);
@@ -62,7 +59,7 @@
 
     @GetMapping("/statisticsList")
     @Log(title = "鍔充繚鍙戞斁-缁熻鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("鍔充繚鍙戞斁-缁熻鏌ヨ")
+    @Operation(summary = "鍔充繚鍙戞斁-缁熻鏌ヨ")
     public AjaxResult statisticsList(LaborIssue laborIssue){
         List<Map<String, Object>> listPage = laborIssueService.statisticsList(laborIssue);
         return AjaxResult.success(listPage);
@@ -70,7 +67,7 @@
 
     @PostMapping("/add")
     @Log(title = "鍔充繚鍙戞斁-娣诲姞", businessType = BusinessType.INSERT)
-    @ApiOperation("鍔充繚鍙戞斁-娣诲姞")
+    @Operation(summary = "鍔充繚鍙戞斁-娣诲姞")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody LaborIssue laborIssue){
         String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
@@ -92,7 +89,7 @@
 
     @PostMapping("/update")
     @Log(title = "鍔充繚鍙戞斁-淇敼", businessType = BusinessType.UPDATE)
-    @ApiOperation("鍔充繚鍙戞斁-淇敼")
+    @Operation(summary = "鍔充繚鍙戞斁-淇敼")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody LaborIssue laborIssue){
         boolean update = laborIssueService.updateById(laborIssue);
@@ -101,7 +98,7 @@
 
     @DeleteMapping("/delete")
     @Log(title = "鍔充繚鍙戞斁-鍒犻櫎", businessType = BusinessType.DELETE)
-    @ApiOperation("鍔充繚鍙戞斁-鍒犻櫎")
+    @Operation(summary = "鍔充繚鍙戞斁-鍒犻櫎")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids){
         boolean delete = laborIssueService.removeBatchByIds(ids);
@@ -109,7 +106,7 @@
     }
 
     @GetMapping("/statistics")
-    @ApiOperation("鍔充繚鍙戞斁-缁熻")
+    @Operation(summary = "鍔充繚鍙戞斁-缁熻")
     public AjaxResult statistics(StatisticsLaborIssue req) throws Exception {
         StatisticsLaborIssue statisticsLaborIssue = laborIssueService.statistics(req);
         return AjaxResult.success(statisticsLaborIssue);
@@ -122,7 +119,7 @@
      */
     @Log(title = "鍔充繚鍙戞斁-瀵煎嚭", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("鍔充繚鍙戞斁-瀵煎嚭")
+    @Operation(summary = "鍔充繚鍙戞斁-瀵煎嚭")
     public void export(HttpServletResponse response) {
         Long tenantId = SecurityUtils.getLoginUser().getTenantId();
         ExcelUtil<LaborIssue> util = new ExcelUtil<LaborIssue>(LaborIssue.class);
@@ -142,7 +139,7 @@
      */
     @Log(title = "鍔充繚鍙戞斁-瀵煎嚭", businessType = BusinessType.EXPORT)
     @PostMapping("/exportCopy")
-    @ApiOperation("鍔充繚鍙戞斁-瀵煎嚭")
+    @Operation(summary = "鍔充繚鍙戞斁-瀵煎嚭")
     public void exportCopy(HttpServletResponse response,LaborIssue laborIssue) throws UnsupportedEncodingException {
         laborIssueService.exportCopy(response,laborIssue);
     }
diff --git a/src/main/java/com/ruoyi/lavorissue/dto/StatisticsLaborIssue.java b/src/main/java/com/ruoyi/lavorissue/dto/StatisticsLaborIssue.java
index 7e7a4a2..bd733e6 100644
--- a/src/main/java/com/ruoyi/lavorissue/dto/StatisticsLaborIssue.java
+++ b/src/main/java/com/ruoyi/lavorissue/dto/StatisticsLaborIssue.java
@@ -1,6 +1,6 @@
 package com.ruoyi.lavorissue.dto;
 
-import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -11,7 +11,7 @@
  * @date : 2025/8/14 11:53
  */
 @Data
-@ApiModel
+@Schema
 public class StatisticsLaborIssue {
 
     private Integer season;
diff --git a/src/main/java/com/ruoyi/lavorissue/pojo/LaborIssue.java b/src/main/java/com/ruoyi/lavorissue/pojo/LaborIssue.java
index 3994833..af9dd0e 100644
--- a/src/main/java/com/ruoyi/lavorissue/pojo/LaborIssue.java
+++ b/src/main/java/com/ruoyi/lavorissue/pojo/LaborIssue.java
@@ -4,8 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.approve.utils.StartAndEndDateDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,7 +17,7 @@
  */
 @Data
 @TableName("labor_issue")
-@ApiModel
+@Schema
 public class LaborIssue extends StartAndEndDateDto {
 
     private static final long serialVersionUID = 1L;
@@ -27,7 +26,7 @@
     private Long id;
 
     @TableField(exist = false)
-    @ApiModelProperty("1-宸查鍙栧姵淇濇暟閲� 2-鏈鍙栧姵淇濇暟閲� 3-瓒呮椂宸查鍙栧姵淇濇暟閲� 4-瓒呮椂鏈鍙栧姵淇濇暟閲�")
+    @Schema(description = "1-宸查鍙栧姵淇濇暟閲� 2-鏈鍙栧姵淇濇暟閲� 3-瓒呮椂宸查鍙栧姵淇濇暟閲� 4-瓒呮椂鏈鍙栧姵淇濇暟閲�")
     private Integer status;
 
     @TableField(exist = false)
@@ -36,7 +35,7 @@
     /**
      * 閮ㄩ棬鍚嶇О
      */
-    @ApiModelProperty("閮ㄩ棬鍚嶇О")
+    @Schema(description = "閮ㄩ棬鍚嶇О")
     @Excel(name = "閮ㄩ棬鍚嶇О")
     @TableField(exist = false)
     private String deptName;
@@ -44,20 +43,20 @@
     /**
      * 鍔充繚鍗曞彿
      */
-    @ApiModelProperty("鍔充繚鍗曞彿")
+    @Schema(description = "鍔充繚鍗曞彿")
     @Excel(name = "鍔充繚鍗曞彿")
     private String orderNo;
 
     /**
      * 鍛樺伐id
      */
-    @ApiModelProperty("鍛樺伐id")
+    @Schema(description = "鍛樺伐id")
     private Long staffId;
 
     /**
      * 鍛樺伐鍚嶇О
      */
-    @ApiModelProperty("鍛樺伐鍚嶇О")
+    @Schema(description = "鍛樺伐鍚嶇О")
     @Excel(name = "鍛樺伐鍚嶇О")
     @TableField(exist = false)
     private String staffName;
@@ -65,7 +64,7 @@
     /**
      * 鍛樺伐缂栧彿
      */
-    @ApiModelProperty("鍛樺伐缂栧彿")
+    @Schema(description = "鍛樺伐缂栧彿")
     @Excel(name = "鍛樺伐缂栧彿")
     @TableField(exist = false)
     private String staffNo;
@@ -73,13 +72,13 @@
     /**
      * 鍔充繚绫诲瀷-瀛楀吀
      */
-    @ApiModelProperty("鍔充繚绫诲瀷-瀛楀吀")
+    @Schema(description = "鍔充繚绫诲瀷-瀛楀吀")
     private String dictType;
 
     /**
      * 鍔充繚绫诲瀷
      */
-    @ApiModelProperty("鍔充繚绫诲瀷")
+    @Schema(description = "鍔充繚绫诲瀷")
     @Excel(name = "鍔充繚绫诲瀷")
     @TableField(exist = false)
     private String dictTypeName;
@@ -87,13 +86,13 @@
     /**
      * 闃插叿鍚嶇О-瀛楀吀
      */
-    @ApiModelProperty("闃插叿鍚嶇О-瀛楀吀")
+    @Schema(description = "闃插叿鍚嶇О-瀛楀吀")
     private String dictId;
 
     /**
      * 闃插叿鍚嶇О
      */
-    @ApiModelProperty("闃插叿鍚嶇О")
+    @Schema(description = "闃插叿鍚嶇О")
     @Excel(name = "闃插叿鍚嶇О")
     @TableField(exist = false)
     private String dictName;
@@ -101,14 +100,14 @@
     /**
      * 棰嗙敤鏁伴噺
      */
-    @ApiModelProperty("棰嗙敤鏁伴噺")
+    @Schema(description = "棰嗙敤鏁伴噺")
     @Excel(name = "棰嗙敤鏁伴噺")
     private Long num;
 
     /**
      * 杩涘巶鏃ユ湡
      */
-    @ApiModelProperty("杩涘巶鏃ユ湡")
+    @Schema(description = "杩涘巶鏃ユ湡")
     @Excel(name = "杩涘巶鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -117,7 +116,7 @@
     /**
      * 鍙戞斁鏃ユ湡
      */
-    @ApiModelProperty("鍙戞斁鏃ユ湡")
+    @Schema(description = "鍙戞斁鏃ユ湡")
     @Excel(name = "鍙戞斁鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -126,7 +125,7 @@
     /**
      * 棰嗙敤鏃ユ湡
      */
-    @ApiModelProperty("棰嗙敤鏃ユ湡")
+    @Schema(description = "棰嗙敤鏃ユ湡")
     @Excel(name = "棰嗙敤鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -169,4 +168,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/lavorissue/service/LavorIssueService.java b/src/main/java/com/ruoyi/lavorissue/service/LavorIssueService.java
index a0fd247..d31a48e 100644
--- a/src/main/java/com/ruoyi/lavorissue/service/LavorIssueService.java
+++ b/src/main/java/com/ruoyi/lavorissue/service/LavorIssueService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.lavorissue.dto.StatisticsLaborIssue;
 import com.ruoyi.lavorissue.pojo.LaborIssue;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.io.UnsupportedEncodingException;
 import java.util.List;
 import java.util.Map;
diff --git a/src/main/java/com/ruoyi/lavorissue/service/impl/LavorIssueServiceImpl.java b/src/main/java/com/ruoyi/lavorissue/service/impl/LavorIssueServiceImpl.java
index 9e66121..3f4ffed 100644
--- a/src/main/java/com/ruoyi/lavorissue/service/impl/LavorIssueServiceImpl.java
+++ b/src/main/java/com/ruoyi/lavorissue/service/impl/LavorIssueServiceImpl.java
@@ -9,7 +9,6 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.approve.utils.StartAndEndDateDto;
 import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.excel.ConfigurableMergeStrategy;
 import com.ruoyi.common.utils.excel.CustomCellStyleHandler;
 import com.ruoyi.lavorissue.dto.StatisticsLaborIssue;
@@ -20,14 +19,14 @@
 import com.ruoyi.project.system.domain.SysDictData;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.mapper.SysDictDataMapper;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
@@ -42,10 +41,13 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class LavorIssueServiceImpl extends ServiceImpl<LavorIssueMapper, LaborIssue> implements LavorIssueService {
 
-    @Autowired
-    private LavorIssueMapper lavorIssueMapper;
+    private final LavorIssueMapper lavorIssueMapper;
+    private final SysDictDataMapper sysDictDataMapper;
+    private final SysDeptMapper sysDeptMapper;
+
 
     @Override
     public IPage<LaborIssue> listPage(Page page, LaborIssue laborIssue) {
@@ -56,7 +58,7 @@
     }
 
     @Override
-    public List<Map<String, Object>> statisticsList(LaborIssue laborIssue){
+    public List<Map<String, Object>> statisticsList(LaborIssue laborIssue) {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
         StartAndEndDateDto startAndEndDateDto = getStartAndEndDateDto(laborIssue.getSeason(), laborIssue.getIssueDate());
         laborIssue.setStartDate(startAndEndDateDto.getStartDate());
@@ -93,14 +95,14 @@
         return records;
     }
 
-    public StartAndEndDateDto getStartAndEndDateDto(Integer season,Date payDate){
+    public StartAndEndDateDto getStartAndEndDateDto(Integer season, Date payDate) {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
         StartAndEndDateDto startAndEndDateDto = new StartAndEndDateDto();
         Calendar calendar = Calendar.getInstance();
         int currentYear = calendar.get(Calendar.YEAR);
         startAndEndDateDto.setYear(currentYear);
-        if(season != null){
-            switch (season){
+        if (season != null) {
+            switch (season) {
                 case 1:
                     startAndEndDateDto.setStartDate(currentYear + "-01-01");
                     startAndEndDateDto.setEndDate(currentYear + "-03-31");
@@ -127,7 +129,7 @@
                     break;
             }
         }
-        if(payDate != null){
+        if (payDate != null) {
             Date lastDayOfMonth = getLastDayOfMonth(payDate);
             Date firstDayOfMonth = getFirstDayOfMonth(payDate);
             startAndEndDateDto.setStartDate(sdf.format(firstDayOfMonth));
@@ -139,17 +141,17 @@
     }
 
     @Override
-    public StatisticsLaborIssue statistics(StatisticsLaborIssue req) throws Exception{
+    public StatisticsLaborIssue statistics(StatisticsLaborIssue req) throws Exception {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
         StatisticsLaborIssue statisticsLaborIssue = new StatisticsLaborIssue();
         StartAndEndDateDto startAndEndDateDto = getStartAndEndDateDto(req.getSeason(), req.getIssueDate());
         LambdaQueryWrapper<LaborIssue> laborIssueLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        if(req.getSeason() != null || req.getIssueDate() != null){
+        if (req.getSeason() != null || req.getIssueDate() != null) {
             laborIssueLambdaQueryWrapper.ge(LaborIssue::getIssueDate, startAndEndDateDto.getStartDate())
                     .le(LaborIssue::getIssueDate, startAndEndDateDto.getEndDate());
         }
         List<LaborIssue> laborIssues = lavorIssueMapper.selectList(laborIssueLambdaQueryWrapper);
-        if(!CollectionUtils.isEmpty(laborIssues)){
+        if (!CollectionUtils.isEmpty(laborIssues)) {
             Long sum = laborIssues.stream()
                     .filter(laborIssue -> laborIssue.getAdoptedDate() != null)
                     .mapToLong(LaborIssue::getNum)
@@ -177,13 +179,10 @@
         return statisticsLaborIssue;
     }
 
-    @Autowired
-    private SysDictDataMapper sysDictDataMapper;
-
     @Override
     public void exportCopy(HttpServletResponse response, LaborIssue laborIssue) throws UnsupportedEncodingException {
         List<SysDictData> sys_lavor_issue = sysDictDataMapper.selectDictDataByType("sys_lavor_issue");
-        if(CollectionUtils.isEmpty(sys_lavor_issue)){
+        if (CollectionUtils.isEmpty(sys_lavor_issue)) {
             throw new RuntimeException("瀛楀吀鏁版嵁涓虹┖");
         }
         StartAndEndDateDto startAndEndDateDto = getStartAndEndDateDto(laborIssue.getSeason(), laborIssue.getIssueDate());
@@ -204,10 +203,10 @@
             //鏂板缓ExcelWriter
             ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                     .registerWriteHandler(new CustomCellStyleHandler())
-                    .registerWriteHandler(new ConfigurableMergeStrategy(exportExternalPackingListGetMerge(4,sys_lavor_issue.size(),laborIssueMap.size())))
+                    .registerWriteHandler(new ConfigurableMergeStrategy(exportExternalPackingListGetMerge(4, sys_lavor_issue.size(), laborIssueMap.size())))
                     .build();
 
-            List<List<List<String>>> data = completeExternalPackingList(laborIssueMap, sys_lavor_issue,laborIssue);
+            List<List<List<String>>> data = completeExternalPackingList(laborIssueMap, sys_lavor_issue, laborIssue);
 
             for (int i = 0; i < data.size(); i++) {
                 List<List<String>> list = data.get(i);
@@ -225,12 +224,8 @@
         }
     }
 
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
-
-
-//     澶勭悊澶栭儴瑁呯鍗曟暟鎹�
-    private List<List<List<String>>> completeExternalPackingList(Map<String, List<LaborIssue>> listMap,List<SysDictData> sys_lavor_issue,LaborIssue obj) {
+    //     澶勭悊澶栭儴瑁呯鍗曟暟鎹�
+    private List<List<List<String>>> completeExternalPackingList(Map<String, List<LaborIssue>> listMap, List<SysDictData> sys_lavor_issue, LaborIssue obj) {
         List<List<List<String>>> data = new ArrayList<>();
         int num = sys_lavor_issue.size();
 
@@ -240,8 +235,8 @@
         list.add("");
         list.add("浼佷笟绠$悊绉�");
         list.add("");
-        list.add("浼佷笟绠$悊绉�" + obj.getYear() + "骞�" + obj.getStartMonth() + "鏈�-" + obj.getYear() + "骞�" + obj.getEndMonth() +"鏈堝姵淇濆彂鏀捐鍒掕〃");
-        for (int i = 1; i <= num; i++){
+        list.add("浼佷笟绠$悊绉�" + obj.getYear() + "骞�" + obj.getStartMonth() + "鏈�-" + obj.getYear() + "骞�" + obj.getEndMonth() + "鏈堝姵淇濆彂鏀捐鍒掕〃");
+        for (int i = 1; i <= num; i++) {
             list.add("");
         }
         item.add(list);
@@ -251,7 +246,7 @@
         list1.add("");
         list1.add("缁撴潫骞�/鏈�");
         list1.add("");
-        for (int i = 0; i <= num; i++){
+        for (int i = 0; i <= num; i++) {
             list1.add("");
         }
         item.add(list1);
@@ -261,7 +256,7 @@
         list2.add(obj.getStartMonth().toString());
         list2.add(obj.getYear().toString());
         list2.add(obj.getEndMonth().toString());
-        for (int i = 0; i <= num; i++){
+        for (int i = 0; i <= num; i++) {
             list.add("");
         }
         item.add(list2);
@@ -293,13 +288,13 @@
                         .mapToLong(LaborIssue::getNum)
                         .sum()
                         + "");
-                if(i.get() == 0){
+                if (i.get() == 0) {
                     sumList.add(value.stream().filter(laborIssue -> laborIssue.getDictId().equals(sysDictData.getDictValue()))
                             .mapToLong(LaborIssue::getNum)
                             .sum()
                             + "");
-                }else {
-                    sumList.set(j,(Long.parseLong(sumList.get(j)) + value.stream().filter(laborIssue -> laborIssue.getDictId().equals(sysDictData.getDictValue()))
+                } else {
+                    sumList.set(j, (Long.parseLong(sumList.get(j)) + value.stream().filter(laborIssue -> laborIssue.getDictId().equals(sysDictData.getDictValue()))
                             .mapToLong(LaborIssue::getNum)
                             .sum())
                             + "");
@@ -314,7 +309,7 @@
         list5.add("");
         list5.add("");
         list5.add("");
-        for (int h = 0; h < sumList.size(); h++){
+        for (int h = 0; h < sumList.size(); h++) {
             list5.add(sumList.get(h));
         }
         item.add(list5);
@@ -327,7 +322,7 @@
      *
      * @return
      */
-    private List<CellRangeAddress> exportExternalPackingListGetMerge(Integer rowNum,Integer num,Integer listSize) {
+    private List<CellRangeAddress> exportExternalPackingListGetMerge(Integer rowNum, Integer num, Integer listSize) {
         List<CellRangeAddress> mergeRegions = new ArrayList<>();
         mergeRegions.add(new CellRangeAddress(0, 0, 0, 1)); // 鍚堝苟A1:Q2
         mergeRegions.add(new CellRangeAddress(0, 0, 2, 3)); // 鍚堝苟A4:Q4
@@ -352,6 +347,7 @@
 
     /**
      * 鑾峰彇褰撴湀绗竴澶�
+     *
      * @param date
      * @return
      */
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java
index b166c89..e092741 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java
@@ -14,14 +14,14 @@
 import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerService;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.List;
 
@@ -30,22 +30,18 @@
  * @date : 2025/8/5 9:27
  */
 @RestController
-@Api(tags = "璁¢噺鍣ㄥ叿鍙拌处")
+@Tag(name = "璁¢噺鍣ㄥ叿鍙拌处")
 @RequestMapping("/measuringInstrumentLedger")
+@AllArgsConstructor
 public class MeasuringInstrumentLedgerController extends BaseController {
 
-    @Autowired
-    private MeasuringInstrumentLedgerService measuringInstrumentLedgerService;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper;
+    private final MeasuringInstrumentLedgerService measuringInstrumentLedgerService;
+    private final SysUserMapper sysUserMapper;
+    private final MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper;
 
 
     @GetMapping("/listPage")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处-鍒嗛〉鏌ヨ")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处-鍒嗛〉鏌ヨ")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, MeasuringInstrumentLedger measuringInstrumentLedger) {
         IPage<MeasuringInstrumentLedger> listPage = measuringInstrumentLedgerService.listPage(page, measuringInstrumentLedger);
@@ -54,7 +50,7 @@
 
 
     @PostMapping("/add")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处-鏂板")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处-鏂板")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处-鏂板", businessType = BusinessType.INSERT)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody MeasuringInstrumentLedger measuringInstrumentLedger) throws IOException {
@@ -66,7 +62,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处-淇敼")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处-淇敼")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处-淇敼", businessType = BusinessType.UPDATE)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody MeasuringInstrumentLedger measuringInstrumentLedger) {
@@ -83,7 +79,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处-鍒犻櫎")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处-鍒犻櫎")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处-鍒犻櫎", businessType = BusinessType.DELETE)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids) {
@@ -104,7 +100,7 @@
     }
 
     @PostMapping("/verifying")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处-妫�瀹�")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处-妫�瀹�")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处-妫�瀹�", businessType = BusinessType.UPDATE)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult verifying(@RequestBody MeasuringInstrumentLedgerDto measuringInstrumentLedger) throws IOException {
@@ -117,7 +113,7 @@
      */
     @Log(title = "瀵煎嚭璁¢噺鍣ㄥ叿鍙拌处", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭璁¢噺鍣ㄥ叿鍙拌处")
+    @Operation(summary = "瀵煎嚭璁¢噺鍣ㄥ叿鍙拌处")
     public void export(HttpServletResponse response) {
         measuringInstrumentLedgerService.export( response);
     }
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java
index 8c7116e..370d41d 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java
@@ -9,13 +9,14 @@
 import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
 import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerRecordService;
 import io.jsonwebtoken.lang.Collections;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.List;
 
@@ -24,16 +25,16 @@
  * @date : 2025/8/5 9:28
  */
 @RestController
-@Api(tags = "璁¢噺鍣ㄥ叿鍙拌处璁板綍")
+@Tag(name = "璁¢噺鍣ㄥ叿鍙拌处璁板綍")
 @RequestMapping("/measuringInstrumentLedgerRecord")
+@AllArgsConstructor
 public class MeasuringInstrumentLedgerRecordController extends BaseController {
 
-    @Autowired
     private MeasuringInstrumentLedgerRecordService measuringInstrumentLedgerRecordService;
 
 
     @GetMapping("/listPage")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处璁板綍-鍒嗛〉鏌ヨ")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-鍒嗛〉鏌ヨ")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord){
         IPage<MeasuringInstrumentLedgerRecord> listPage = measuringInstrumentLedgerRecordService.listPage(page, measuringInstrumentLedgerRecord);
@@ -41,7 +42,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处璁板綍-淇敼")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-淇敼")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-淇敼", businessType = BusinessType.UPDATE)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) throws IOException {
@@ -53,7 +54,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处璁板綍-鍒犻櫎")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-鍒犻櫎")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if(Collections.isEmpty(ids)) return AjaxResult.error("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
@@ -63,7 +64,7 @@
     /**
      * 瀵煎嚭璁¢噺鍣ㄥ叿鍙拌处
      */
-    @ApiOperation("璁¢噺鍣ㄥ叿鍙拌处璁板綍-瀵煎嚭")
+    @Operation(summary = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-瀵煎嚭")
     @Log(title = "璁¢噺鍣ㄥ叿鍙拌处璁板綍-瀵煎嚭", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response) {
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java
index 599c116..5a328c1 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java
@@ -9,8 +9,9 @@
 import com.ruoyi.measuringinstrumentledger.dto.SparePartsDto;
 import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
 import com.ruoyi.measuringinstrumentledger.service.SparePartsService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -18,41 +19,41 @@
 
 @RestController
 @RequestMapping("/spareParts")
-@Api(tags = "澶囦欢鍒嗙被鎺ュ彛")
+@Tag(name = "澶囦欢鍒嗙被鎺ュ彛")
+@AllArgsConstructor
 public class SparePartsController {
-    @Autowired
     private SparePartsService sparePartsService;
     @GetMapping("/getTree")
-    @ApiOperation("澶囦欢鍒嗙被-鏍戠粨鏋�")
+    @Operation(summary = "澶囦欢鍒嗙被-鏍戠粨鏋�")
     public AjaxResult getTree(){
         List<SparePartsDto> tree = sparePartsService.getTree();
         return AjaxResult.success(tree);
     }
     @GetMapping("/listPage")
-    @ApiOperation("澶囦欢鍒嗙被-鍒嗛〉鏌ヨ")
+    @Operation(summary = "澶囦欢鍒嗙被-鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, SpareParts spareParts){
         IPage<SparePartsDto> listPage = sparePartsService.listPage(page, spareParts);
         return AjaxResult.success(listPage);
     }
 //    @GetMapping("/list")
-//    @ApiOperation("澶囦欢鍒嗙被-鏌ヨ鎵�鏈�")
+//    @Operation(summary = "澶囦欢鍒嗙被-鏌ヨ鎵�鏈�")
 //    public AjaxResult list(){
 //        return AjaxResult.success(sparePartsService.list());
 //    }
     @PostMapping("/add")
-    @ApiOperation("澶囦欢鍒嗙被-娣诲姞")
+    @Operation(summary = "澶囦欢鍒嗙被-娣诲姞")
     @Log(title = "澶囦欢鍒嗙被-娣诲姞", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody SpareParts spareParts){
         return AjaxResult.success(sparePartsService.save(spareParts));
     }
     @PostMapping("/update")
-    @ApiOperation("澶囦欢鍒嗙被-鏇存柊")
+    @Operation(summary = "澶囦欢鍒嗙被-鏇存柊")
     @Log(title = "澶囦欢鍒嗙被-鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody SpareParts spareParts){
         return AjaxResult.success(sparePartsService.updateById(spareParts));
     }
     @DeleteMapping("/delete/{id}")
-    @ApiOperation("澶囦欢鍒嗙被-鍒犻櫎")
+    @Operation(summary = "澶囦欢鍒嗙被-鍒犻櫎")
     @Log(title = "澶囦欢鍒嗙被-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@PathVariable Long id){
         return AjaxResult.success(sparePartsService.removeById(id));
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsRequisitionRecordController.java b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsRequisitionRecordController.java
new file mode 100644
index 0000000..26195a4
--- /dev/null
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsRequisitionRecordController.java
@@ -0,0 +1,36 @@
+package com.ruoyi.measuringinstrumentledger.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto;
+import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-02 03:59:56
+ */
+@RestController
+@RequestMapping("/sparePartsRequisitionRecord")
+@Tag(name = "澶囦欢棰嗙敤璁板綍鎺ュ彛")
+@AllArgsConstructor
+public class SparePartsRequisitionRecordController {
+    private SparePartsRequisitionRecordService sparePartsRequisitionRecordService;
+
+    @GetMapping("/listPage")
+    @Operation(summary = "澶囦欢鍒嗙被-鍒嗛〉鏌ヨ")
+    public AjaxResult listPage(Page page, SparePartsRequisitionRecordDto sparePartsRequisitionRecordDto){
+        IPage<SparePartsRequisitionRecordDto> listPage = sparePartsRequisitionRecordService.listPage(page, sparePartsRequisitionRecordDto);
+        return AjaxResult.success(listPage);
+    }
+}
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java b/src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java
index 2da314d..648db49 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java
@@ -1,8 +1,7 @@
 package com.ruoyi.measuringinstrumentledger.dto;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -14,30 +13,30 @@
  * @date : 2025/8/5 9:50
  */
 @Data
-@ApiModel
+@Schema
 public class MeasuringInstrumentLedgerDto {
 
-    @ApiModelProperty("ID")
+    @Schema(description = "ID")
     private Long id;
 
-    @ApiModelProperty("闄勪欢id")
+    @Schema(description = "闄勪欢id")
     private List<String> tempFileIds;
 
-    @ApiModelProperty("妫�瀹氭棩鏈�")
+    @Schema(description = "妫�瀹氭棩鏈�")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd", iso = DateTimeFormat.ISO.DATE)
     private Date recordDate;
 
-    @ApiModelProperty("褰曞叆鏃ユ湡")
+    @Schema(description = "褰曞叆鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd", iso = DateTimeFormat.ISO.DATE)
     private Date entryDate;
 
 
-    @ApiModelProperty("鏈夋晥鏈�")
+    @Schema(description = "鏈夋晥鏈�")
     private Integer valid;
 
-    @ApiModelProperty("妫�瀹氫汉")
+    @Schema(description = "妫�瀹氫汉")
     private Long userId;
 
 
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsRequisitionRecordDto.java b/src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsRequisitionRecordDto.java
new file mode 100644
index 0000000..59b9517
--- /dev/null
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsRequisitionRecordDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.measuringinstrumentledger.dto;
+
+import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord;
+import lombok.Data;
+
+@Data
+public class SparePartsRequisitionRecordDto extends SparePartsRequisitionRecord {
+    private String sparePartsName;
+
+    private String deviceName;
+
+    private String sourceText;
+
+    private String operator;
+}
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/mapper/SparePartsRequisitionRecordMapper.java b/src/main/java/com/ruoyi/measuringinstrumentledger/mapper/SparePartsRequisitionRecordMapper.java
new file mode 100644
index 0000000..3b67162
--- /dev/null
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/mapper/SparePartsRequisitionRecordMapper.java
@@ -0,0 +1,23 @@
+package com.ruoyi.measuringinstrumentledger.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto;
+import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ *  Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-02 03:59:56
+ */
+@Mapper
+public interface SparePartsRequisitionRecordMapper extends BaseMapper<SparePartsRequisitionRecord> {
+    IPage<SparePartsRequisitionRecordDto> listPage(Page page, @Param("params") SparePartsRequisitionRecordDto sparePartsRequisitionRecordDto);
+
+}
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java
index 96803c5..cd1a2d5 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java
@@ -4,8 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.CommonFile;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,55 +18,55 @@
  */
 @Data
 @TableName("measuring_instrument_ledger")
-@ApiModel
+@Schema
 public class MeasuringInstrumentLedger {
 
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("闄勪欢id")
+    @Schema(description = "闄勪欢id")
     @TableField(exist = false)
     private List<String> tempFileIds;
 
     @TableField(exist = false)
-    @ApiModelProperty("闄勪欢鍒楄〃")
+    @Schema(description = "闄勪欢鍒楄〃")
     private List<CommonFile> commonFiles;
 
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("褰曞叆浜篿d")
+    @Schema(description = "褰曞叆浜篿d")
     private Long userId;
 
-    @ApiModelProperty("褰曞叆浜哄悕绉�")
+    @Schema(description = "褰曞叆浜哄悕绉�")
     @Excel(name = "褰曞叆浜哄悕绉�")
     private String userName;
 
     /**
      * 璁¢噺鍣ㄥ叿缂栧彿
      */
-    @ApiModelProperty("璁¢噺鍣ㄥ叿缂栧彿")
+    @Schema(description = "璁¢噺鍣ㄥ叿缂栧彿")
     @Excel(name = "璁¢噺鍣ㄥ叿缂栧彿")
     private String code;
 
     /**
      * 璁¢噺鍣ㄥ叿鍚嶇О
      */
-    @ApiModelProperty("璁¢噺鍣ㄥ叿鍚嶇О")
+    @Schema(description = "璁¢噺鍣ㄥ叿鍚嶇О")
     @Excel(name = "璁¢噺鍣ㄥ叿鍚嶇О")
     private String name;
 
     /**
      * 瑙勬牸鍨嬪彿
      */
-    @ApiModelProperty("瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     @Excel(name = "瑙勬牸鍨嬪彿")
     private String model;
 
     /**
      * 鏈�杩戜竴娆℃瀹氭棩鏈�
      */
-    @ApiModelProperty("鏈�杩戜竴娆℃瀹氭棩鏈�")
+    @Schema(description = "鏈�杩戜竴娆℃瀹氭棩鏈�")
     @Excel(name = "鏈�杩戜竴娆℃瀹氭棩鏈�", width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -77,14 +76,14 @@
     /**
      * 妫�瀹氭湁鏁堟湡
      */
-    @ApiModelProperty("妫�瀹氭湁鏁堟湡")
+    @Schema(description = "妫�瀹氭湁鏁堟湡")
     @Excel(name = "妫�瀹氭湁鏁堟湡")
     private Integer valid;
 
     /**
      * 棰勮涓嬫妫�瀹氭棩鏈�
      */
-    @ApiModelProperty("棰勮涓嬫妫�瀹氭棩鏈�")
+    @Schema(description = "棰勮涓嬫妫�瀹氭棩鏈�")
     @Excel(name = "棰勮涓嬫妫�瀹氭棩鏈�" , width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -93,7 +92,7 @@
     /**
      * 褰曞叆鏃ユ湡
      */
-    @ApiModelProperty("褰曞叆鏃ユ湡")
+    @Schema(description = "褰曞叆鏃ユ湡")
     @Excel(name = "褰曞叆鏃ユ湡" , width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -103,7 +102,7 @@
     /**
      * 鐘舵�侊紙1-鏈夋晥 2-閫炬湡锛�
      */
-    @ApiModelProperty("鐘舵�侊紙1-鏈夋晥 2-閫炬湡锛�")
+    @Schema(description = "鐘舵�侊紙1-鏈夋晥 2-閫炬湡锛�")
     @Excel(name = "鐘舵��", readConverterExp = "1=鏈夋晥,2=閫炬湡")
     private Integer status;
 
@@ -138,13 +137,14 @@
     private Long tenantId;
 
 
-    @ApiModelProperty("鍗曚綅")
+    @Schema(description = "鍗曚綅")
     private String unit;
 
-    @ApiModelProperty("閮ㄩ棬id")
+    @Schema(description = "閮ㄩ棬id")
+    @TableField(fill = FieldFill.INSERT)
     private Long deptId;
 
-    @ApiModelProperty("瀹夎浣嶇疆")
+    @Schema(description = "瀹夎浣嶇疆")
     private String instationLocation;
 
     private String cycle;
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedgerRecord.java b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedgerRecord.java
index 75eed76..8ca16d8 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedgerRecord.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedgerRecord.java
@@ -4,8 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.CommonFile;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,58 +18,58 @@
  */
 @Data
 @TableName("measuring_instrument_ledger_record")
-@ApiModel
+@Schema
 public class MeasuringInstrumentLedgerRecord {
 
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("璁¢噺鍣ㄥ叿缂栧彿")
+    @Schema(description = "璁¢噺鍣ㄥ叿缂栧彿")
     @TableField(exist = false)
     @Excel(name = "璁¢噺鍣ㄥ叿缂栧彿")
     private String code;
 
-    @ApiModelProperty("鍚嶇О")
+    @Schema(description = "鍚嶇О")
     @TableField(exist = false)
     @Excel(name = "鍚嶇О")
     private String name;
 
-    @ApiModelProperty("璁¢噺鍣ㄥ叿鍚嶇О")
+    @Schema(description = "璁¢噺鍣ㄥ叿鍚嶇О")
     @TableField(exist = false)
     @Excel(name = "璁¢噺鍣ㄥ叿鍚嶇О")
     private String model;
 
-    @ApiModelProperty("闄勪欢id")
+    @Schema(description = "闄勪欢id")
     @TableField(exist = false)
     private List<String> tempFileIds;
 
     @TableField(exist = false)
-    @ApiModelProperty("闄勪欢鍒楄〃")
+    @Schema(description = "闄勪欢鍒楄〃")
     private List<CommonFile> commonFiles;
 
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("璁¢噺鍣ㄥ叿鍙拌处id")
+    @Schema(description = "璁¢噺鍣ㄥ叿鍙拌处id")
     private Long measuringInstrumentLedgerId;
 
-    @ApiModelProperty("妫�瀹氫汉id")
+    @Schema(description = "妫�瀹氫汉id")
     private Long userId;
 
-    @ApiModelProperty("妫�瀹氫汉鍚嶇О")
+    @Schema(description = "妫�瀹氫汉鍚嶇О")
     @Excel(name = "妫�瀹氫汉鍚嶇О")
     private String userName;
 
     /**
      * 妫�瀹氭棩鏈�
      */
-    @ApiModelProperty("妫�瀹氭棩鏈�")
+    @Schema(description = "妫�瀹氭棩鏈�")
     @Excel(name = "妫�瀹氭棩鏈�" , width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date recordDate;
 
-    @ApiModelProperty("褰曞叆鏃ユ湡")
+    @Schema(description = "褰曞叆鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @Excel(name = "褰曞叆鏃ユ湡" , width = 30, dateFormat = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd", iso = DateTimeFormat.ISO.DATE)
@@ -79,14 +78,14 @@
     /**
      * 鏈夋晥鏈燂紙鍗曚綅澶╋級
      */
-    @ApiModelProperty("鏈夋晥鏈燂紙鍗曚綅澶╋級")
+    @Schema(description = "鏈夋晥鏈燂紙鍗曚綅澶╋級")
     private Integer valid;
 
 
     /**
      * 鐘舵�侊紙1-鏈夋晥 2-閫炬湡锛�
      */
-    @ApiModelProperty("鐘舵�侊紙1-鏈夋晥 2-閫炬湡锛�")
+    @Schema(description = "鐘舵�侊紙1-鏈夋晥 2-閫炬湡锛�")
     private Integer status;
 
     /**
@@ -119,4 +118,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java
index 7eb0e68..13a9229 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java
@@ -2,7 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -53,27 +53,30 @@
      * 澶囦欢鍒嗙被鎻忚堪
      */
     private String description;
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SparePartsRequisitionRecord.java b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SparePartsRequisitionRecord.java
new file mode 100644
index 0000000..672812b
--- /dev/null
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SparePartsRequisitionRecord.java
@@ -0,0 +1,69 @@
+package com.ruoyi.measuringinstrumentledger.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-02 03:59:56
+ */
+@Getter
+@Setter
+@TableName("spare_parts_requisition_record")
+@Schema(name = "SparePartsRequisitionRecord瀵硅薄", description = "")
+public class SparePartsRequisitionRecord implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鏉ユ簮绫诲瀷(0 缁翠慨 1 淇濆吇)")
+    private Integer sourceType;
+
+    @Schema(description = "鏉ユ簮id")
+    private Long sourceId;
+
+    @Schema(description = "璁惧id")
+    private Long deviceLedgerId;
+
+    @Schema(description = "澶囦欢id")
+    private Long sparePartsId;
+
+    @Schema(description = "鏁伴噺")
+    private Integer quantity;
+
+    @Schema(description = "鍒涘缓浜�")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @Schema(description = "绉熸埛id")
+    @TableField(fill = FieldFill.INSERT)
+    private Long tenantId;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java b/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java
index e8038da..2d7d38c 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java
@@ -4,9 +4,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
-
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * @author :yys
@@ -25,5 +23,5 @@
 
     void export(HttpServletResponse response);
 
-    boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) throws IOException;
+    boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord);
 }
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java b/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java
index 7ca300d..c28fe83 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerDto;
 import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.io.IOException;
 
 /**
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/service/SparePartsRequisitionRecordService.java b/src/main/java/com/ruoyi/measuringinstrumentledger/service/SparePartsRequisitionRecordService.java
new file mode 100644
index 0000000..2306a3a
--- /dev/null
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/service/SparePartsRequisitionRecordService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.measuringinstrumentledger.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto;
+import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord;
+
+/**
+ * <p>
+ *  鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-02 03:59:56
+ */
+public interface SparePartsRequisitionRecordService extends IService<SparePartsRequisitionRecord> {
+    IPage<SparePartsRequisitionRecordDto> listPage(Page page, SparePartsRequisitionRecordDto sparePartsRequisitionRecordDto);
+}
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java
index c4ab40c..7104c1a 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java
@@ -5,35 +5,21 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper;
 import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerRecordMapper;
 import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
 import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
 import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerRecordService;
-import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.other.pojo.TempFile;
 import com.ruoyi.sales.mapper.CommonFileMapper;
 import com.ruoyi.sales.pojo.CommonFile;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
 import java.util.Date;
 import java.util.List;
-import java.util.UUID;
 
 /**
  * @author :yys
@@ -41,22 +27,12 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class MeasuringInstrumentLedgerRecordServiceImpl extends ServiceImpl<MeasuringInstrumentLedgerRecordMapper, MeasuringInstrumentLedgerRecord> implements MeasuringInstrumentLedgerRecordService {
 
-    @Autowired
-    private MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper;
-
-    @Autowired
-    private MeasuringInstrumentLedgerMapper measuringInstrumentLedgerMapper;
-
-    @Autowired
-    private CommonFileMapper commonFileMapper;
-
-    @Autowired
-    private TempFileMapper tempFileMapper;
-
-    @Value("${file.upload-dir}")
-    private String uploadDir;
+    private final MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper;
+    private final MeasuringInstrumentLedgerMapper measuringInstrumentLedgerMapper;
+    private final CommonFileMapper commonFileMapper;
 
     @Override
     public IPage<MeasuringInstrumentLedgerRecord> listPage(Page page, MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) {
@@ -79,7 +55,7 @@
     }
 
     @Override
-    public boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) throws IOException {
+    public boolean updateMeasuringInstrumentLedgerRecord(MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord) {
         MeasuringInstrumentLedgerRecord measuringInstrumentLedgerRecord1 = measuringInstrumentLedgerRecordMapper.selectById(measuringInstrumentLedgerRecord.getId());
         if (measuringInstrumentLedgerRecord1 == null) {
             return false;
@@ -94,83 +70,6 @@
             measuringInstrumentLedgerMapper.updateById(measuringInstrumentLedger);
         }
         measuringInstrumentLedgerRecordMapper.updateById(measuringInstrumentLedgerRecord);
-        // 璁板綍闄勪欢缁戝畾
-        migrateTempFilesToFormal(measuringInstrumentLedgerRecord.getId(), measuringInstrumentLedgerRecord.getTempFileIds(), FileNameType.MEASURINGRecord.getValue());
         return true;
-    }
-
-
-    /**
-     * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
-     *
-     * @param businessId  涓氬姟ID锛堥攢鍞彴璐D锛�
-     * @param tempFileIds 涓存椂鏂囦欢ID鍒楄〃
-     * @throws IOException 鏂囦欢鎿嶄綔寮傚父
-     */
-    private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds,Integer fileType) throws IOException {
-        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(tempFileIds)) {
-            return;
-        }
-
-        // 鏋勫缓姝e紡鐩綍璺緞锛堟寜涓氬姟绫诲瀷鍜屾棩鏈熷垎缁勶級
-        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
-
-        Path formalDirPath = Paths.get(formalDir);
-
-        // 纭繚姝e紡鐩綍瀛樺湪锛堥�掑綊鍒涘缓锛�
-        if (!Files.exists(formalDirPath)) {
-            Files.createDirectories(formalDirPath);
-        }
-
-        for (String tempFileId : tempFileIds) {
-            // 鏌ヨ涓存椂鏂囦欢璁板綍
-            TempFile tempFile = tempFileMapper.selectById(tempFileId);
-            if (tempFile == null) {
-                log.warn("涓存椂鏂囦欢涓嶅瓨鍦紝璺宠繃澶勭悊: {}", tempFileId);
-                continue;
-            }
-
-            // 鏋勫缓姝e紡鏂囦欢鍚嶏紙鍖呭惈涓氬姟ID鍜屾椂闂存埑锛岄伩鍏嶅啿绐侊級
-            String originalFilename = tempFile.getOriginalName();
-            String fileExtension = FilenameUtils.getExtension(originalFilename);
-            String formalFilename = businessId + "_" +
-                    System.currentTimeMillis() + "_" +
-                    UUID.randomUUID().toString().substring(0, 8) +
-                    (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
-
-            Path formalFilePath = formalDirPath.resolve(formalFilename);
-
-            try {
-                // 鎵ц鏂囦欢杩佺Щ锛堜娇鐢ㄥ師瀛愭搷浣滅‘淇濆畨鍏ㄦ�э級
-//                Files.move(
-//                        Paths.get(tempFile.getTempPath()),
-//                        formalFilePath,
-//                        StandardCopyOption.REPLACE_EXISTING,
-//                        StandardCopyOption.ATOMIC_MOVE
-//                );
-                // 鍘熷瓙绉诲姩澶辫触锛屼娇鐢ㄥ鍒�+鍒犻櫎
-                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
-                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-
-                // 鏇存柊鏂囦欢璁板綍锛堝叧鑱斿埌涓氬姟ID锛�
-                CommonFile fileRecord = new CommonFile();
-                fileRecord.setCommonId(businessId);
-                fileRecord.setName(originalFilename);
-                fileRecord.setUrl(formalFilePath.toString());
-                fileRecord.setCreateTime(LocalDateTime.now());
-                fileRecord.setType(fileType);
-                commonFileMapper.insert(fileRecord);
-
-                // 鍒犻櫎涓存椂鏂囦欢璁板綍
-                tempFileMapper.deleteById(tempFile);
-
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-            } catch (IOException e) {
-                log.error("鏂囦欢杩佺Щ澶辫触: {}", tempFile.getTempPath(), e);
-                // 鍙�夋嫨鍥炴粴浜嬪姟鎴栬褰曞け璐ユ枃浠�
-                throw new IOException("鏂囦欢杩佺Щ寮傚父", e);
-            }
-        }
     }
 }
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java
index fbaad14..4025d75 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java
@@ -6,7 +6,6 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.enums.FileNameType;
-import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerDto;
 import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper;
@@ -14,31 +13,19 @@
 import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
 import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
 import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerService;
-import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.other.pojo.TempFile;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.sales.mapper.CommonFileMapper;
 import com.ruoyi.sales.pojo.CommonFile;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.UUID;
 import java.util.stream.Collectors;
 
 /**
@@ -47,25 +34,12 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class MeasuringInstrumentLedgerServiceImpl extends ServiceImpl<MeasuringInstrumentLedgerMapper, MeasuringInstrumentLedger> implements MeasuringInstrumentLedgerService {
 
-    @Autowired
-    private MeasuringInstrumentLedgerMapper measuringInstrumentLedgerMapper;
-
-    @Autowired
-    private MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper;
-
-    @Autowired
-    private TempFileMapper tempFileMapper;
-
-    @Autowired
-    private CommonFileMapper commonFileMapper;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Value("${file.upload-dir}")
-    private String uploadDir;
+    private final MeasuringInstrumentLedgerMapper measuringInstrumentLedgerMapper;
+    private final MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper;
+    private final SysUserMapper sysUserMapper;
 
     @Override
     public IPage<MeasuringInstrumentLedger> listPage(Page page, MeasuringInstrumentLedger measuringInstrumentLedger) {
@@ -82,12 +56,6 @@
                 collect = measuringInstrumentLedgerRecords.stream().map(MeasuringInstrumentLedgerRecord::getId).collect(Collectors.toList());
             }
             collect.add(item.getId());
-            LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>();
-            salesLedgerFileWrapper.in(CommonFile::getCommonId, collect)
-                    .in(CommonFile::getType,types);
-            List<CommonFile> commonFiles = commonFileMapper.selectList(salesLedgerFileWrapper);
-            item.setCommonFiles(commonFiles);
-
         });
         return measuringInstrumentLedgerIPage;
     }
@@ -115,10 +83,6 @@
 //            if(!CollectionUtils.isEmpty(req.getTempFileIds())){
 //                migrateTempFilesToFormal(measuringInstrumentLedger.getId(), req.getTempFileIds(), FileNameType.MEASURING.getValue());
 //            }
-            // 鍙拌处璁板綍缁戝畾涓�娆�
-            if(!CollectionUtils.isEmpty(req.getTempFileIds())){
-                migrateTempFilesToFormal(measuringInstrumentLedgerRecord.getId(), req.getTempFileIds(), FileNameType.MEASURINGRecord.getValue());
-            }
             return true;
         }
         return false;
@@ -139,84 +103,7 @@
         }
         measuringInstrumentLedger.setUserName(sysUser.getUserName());
         measuringInstrumentLedgerMapper.insert(measuringInstrumentLedger);
-        if(!CollectionUtils.isEmpty(measuringInstrumentLedger.getTempFileIds())){
-            migrateTempFilesToFormal(measuringInstrumentLedger.getId(), measuringInstrumentLedger.getTempFileIds(), FileNameType.MEASURING.getValue());
-        }
         return true;
     }
 
-
-    /**
-     * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
-     *
-     * @param businessId  涓氬姟ID锛堥攢鍞彴璐D锛�
-     * @param tempFileIds 涓存椂鏂囦欢ID鍒楄〃
-     * @throws IOException 鏂囦欢鎿嶄綔寮傚父
-     */
-    private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds,Integer fileType) throws IOException {
-        if (CollectionUtils.isEmpty(tempFileIds)) {
-            return;
-        }
-
-        // 鏋勫缓姝e紡鐩綍璺緞锛堟寜涓氬姟绫诲瀷鍜屾棩鏈熷垎缁勶級
-        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
-
-        Path formalDirPath = Paths.get(formalDir);
-
-        // 纭繚姝e紡鐩綍瀛樺湪锛堥�掑綊鍒涘缓锛�
-        if (!Files.exists(formalDirPath)) {
-            Files.createDirectories(formalDirPath);
-        }
-
-        for (String tempFileId : tempFileIds) {
-            // 鏌ヨ涓存椂鏂囦欢璁板綍
-            TempFile tempFile = tempFileMapper.selectById(tempFileId);
-            if (tempFile == null) {
-                log.warn("涓存椂鏂囦欢涓嶅瓨鍦紝璺宠繃澶勭悊: {}", tempFileId);
-                continue;
-            }
-
-            // 鏋勫缓姝e紡鏂囦欢鍚嶏紙鍖呭惈涓氬姟ID鍜屾椂闂存埑锛岄伩鍏嶅啿绐侊級
-            String originalFilename = tempFile.getOriginalName();
-            String fileExtension = FilenameUtils.getExtension(originalFilename);
-            String formalFilename = businessId + "_" +
-                    System.currentTimeMillis() + "_" +
-                    UUID.randomUUID().toString().substring(0, 8) +
-                    (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
-
-            Path formalFilePath = formalDirPath.resolve(formalFilename);
-
-            try {
-                // 鎵ц鏂囦欢杩佺Щ锛堜娇鐢ㄥ師瀛愭搷浣滅‘淇濆畨鍏ㄦ�э級
-//                Files.move(
-//                        Paths.get(tempFile.getTempPath()),
-//                        formalFilePath,
-//                        StandardCopyOption.REPLACE_EXISTING,
-//                        StandardCopyOption.ATOMIC_MOVE
-//                );
-                // 鍘熷瓙绉诲姩澶辫触锛屼娇鐢ㄥ鍒�+鍒犻櫎
-                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
-                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-
-                // 鏇存柊鏂囦欢璁板綍锛堝叧鑱斿埌涓氬姟ID锛�
-                CommonFile fileRecord = new CommonFile();
-                fileRecord.setCommonId(businessId);
-                fileRecord.setName(originalFilename);
-                fileRecord.setUrl(formalFilePath.toString());
-                fileRecord.setCreateTime(LocalDateTime.now());
-                fileRecord.setType(fileType);
-                commonFileMapper.insert(fileRecord);
-
-                // 鍒犻櫎涓存椂鏂囦欢璁板綍
-                tempFileMapper.deleteById(tempFile);
-
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-            } catch (IOException e) {
-                log.error("鏂囦欢杩佺Щ澶辫触: {}", tempFile.getTempPath(), e);
-                // 鍙�夋嫨鍥炴粴浜嬪姟鎴栬褰曞け璐ユ枃浠�
-                throw new IOException("鏂囦欢杩佺Щ寮傚父", e);
-            }
-        }
-    }
 }
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsRequisitionRecordServiceImpl.java b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsRequisitionRecordServiceImpl.java
new file mode 100644
index 0000000..19746f5
--- /dev/null
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsRequisitionRecordServiceImpl.java
@@ -0,0 +1,38 @@
+package com.ruoyi.measuringinstrumentledger.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.enums.SparePartsRequisitionRecordSourceTypeEnum;
+import com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto;
+import com.ruoyi.measuringinstrumentledger.mapper.SparePartsRequisitionRecordMapper;
+import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord;
+import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-02 03:59:56
+ */
+@Service
+@RequiredArgsConstructor
+public class SparePartsRequisitionRecordServiceImpl extends ServiceImpl<SparePartsRequisitionRecordMapper, SparePartsRequisitionRecord> implements SparePartsRequisitionRecordService {
+    private final SparePartsRequisitionRecordMapper sparePartsRequisitionRecordMapper;
+
+    @Override
+    public IPage<SparePartsRequisitionRecordDto> listPage(Page page, SparePartsRequisitionRecordDto sparePartsRequisitionRecordDto) {
+        IPage<SparePartsRequisitionRecordDto> result = sparePartsRequisitionRecordMapper.listPage(page, sparePartsRequisitionRecordDto);
+        // 澶勭悊鏉ユ簮绫诲瀷鏂囨湰
+        result.getRecords().forEach(record -> {
+            if (record.getSourceType() != null) {
+                record.setSourceText(SparePartsRequisitionRecordSourceTypeEnum.getByCode(record.getSourceType()).getValue());
+            }
+        });
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java
index 5f329e8..a851cce 100644
--- a/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java
+++ b/src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java
@@ -12,7 +12,7 @@
 import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper;
 import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
 import com.ruoyi.measuringinstrumentledger.service.SparePartsService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
@@ -22,12 +22,10 @@
 import java.util.stream.Collectors;
 
 @Service
+@RequiredArgsConstructor
 public class SparePartsServiceImpl extends ServiceImpl<SparePartsMapper, SpareParts> implements SparePartsService {
-    @Autowired
-    private SparePartsMapper sparePartsMapper;
-
-    @Autowired
-    private DeviceLedgerMapper deviceLedgerMapper;
+    private final SparePartsMapper sparePartsMapper;
+    private final DeviceLedgerMapper deviceLedgerMapper;
 
     @Override
     public IPage<SparePartsDto> listPage(Page page, SpareParts spareParts) {
diff --git a/src/main/java/com/ruoyi/oA/controller/OaProjectController.java b/src/main/java/com/ruoyi/oA/controller/OaProjectController.java
index 8862fb5..b7ecc7a 100644
--- a/src/main/java/com/ruoyi/oA/controller/OaProjectController.java
+++ b/src/main/java/com/ruoyi/oA/controller/OaProjectController.java
@@ -3,34 +3,33 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
 import com.ruoyi.oA.dto.OaProjectDto;
 import com.ruoyi.oA.pojo.OaProject;
 import com.ruoyi.oA.service.OaProjectService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.HashMap;
 import java.util.List;
 
-@Api(tags = "oA椤圭洰绠$悊")
+@Tag(name = "oA椤圭洰绠$悊")
 @RestController
+@AllArgsConstructor
 @RequestMapping("/oA/project")
 public class OaProjectController {
-    @Autowired
-    private OaProjectService oaProjectService;
+    private final OaProjectService oaProjectService;
 
-    @ApiOperation("鑾峰彇椤圭洰鍒楄〃")
+    @Operation(summary = "鑾峰彇椤圭洰鍒楄〃")
     @GetMapping("/listPage")
     public AjaxResult listPage(Page page, OaProjectDto oaProjectDto) {
         IPage<OaProjectDto> listPage = oaProjectService.listPage(page, oaProjectDto);
         return AjaxResult.success(listPage);
     }
-    @ApiOperation("鑾峰彇椤圭洰鍒楄〃璇︽儏")
+    @Operation(summary = "鑾峰彇椤圭洰鍒楄〃璇︽儏")
     @GetMapping("/getList")
     public AjaxResult getList(Page page, OaProjectDto oaProjectDto) {
         IPage<OaProjectDto> listPage = oaProjectService.listPage(page, oaProjectDto);
@@ -40,33 +39,33 @@
         });
         return AjaxResult.success(Map);
     }
-    @ApiOperation("澧炴坊椤圭洰")
+    @Operation(summary = "澧炴坊椤圭洰")
     @PostMapping("/add")
     public AjaxResult add(@RequestBody OaProject oaProject) {
         boolean save = oaProjectService.save(oaProject);
         return AjaxResult.success(save);
     }
-    @ApiOperation("鍒犻櫎椤圭洰")
+    @Operation(summary = "鍒犻櫎椤圭洰")
     @DeleteMapping("/delete/{id}")
     public AjaxResult delete(@PathVariable Long id) {
         boolean remove = oaProjectService.deleteById(id);
         return AjaxResult.success(remove);
     }
-    @ApiOperation("鏇存柊椤圭洰")
+    @Operation(summary = "鏇存柊椤圭洰")
     @PostMapping("/update")
     public AjaxResult update(@RequestBody OaProject oaProject) {
         boolean update = oaProjectService.updateById(oaProject);
         return AjaxResult.success(update);
     }
-//    @ApiOperation("鏍规嵁ID鑾峰彇椤圭洰璇︽儏")
+//    @Operation(summary = "鏍规嵁ID鑾峰彇椤圭洰璇︽儏")
 //    @GetMapping("/getById")
 //    public AjaxResult getById(Long id) {
 //        OaProject oaProject = oaProjectService.getById(id);
 //        return AjaxResult.success(oaProject);
 //    }
-    @ApiOperation("瀵煎嚭鎵�閫夐」鐩�")
+    @Operation(summary = "瀵煎嚭鎵�閫夐」鐩�")
     @PostMapping("/export/{ids}")
-    public void export(HttpServletResponse response,@PathVariable("ids") List<Long> ids) {
+    public void export(HttpServletResponse response, @PathVariable("ids") List<Long> ids) {
         if (CollectionUtils.isEmpty(ids)) {
             throw new IllegalArgumentException("瀵煎嚭椤圭洰鍒楄〃涓嶈兘涓虹┖");
         }
diff --git a/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseController.java b/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseController.java
index d857f52..a4a05bb 100644
--- a/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseController.java
+++ b/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseController.java
@@ -3,37 +3,37 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.oA.pojo.OaProjectPhase;
 import com.ruoyi.oA.service.OaProjectPhaseService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-@Api(tags = "oA椤圭洰闃舵绠$悊")
+@Tag(name = "oA椤圭洰闃舵绠$悊")
 @RestController
 @RequestMapping("/oA/projectPhase")
+@AllArgsConstructor
 public class OaProjectPhaseController {
-    @Autowired
-    private OaProjectPhaseService oaProjectPhaseService;
+    private final OaProjectPhaseService oaProjectPhaseService;
 
-    @ApiOperation("鏂板椤圭洰闃舵")
+    @Operation(summary = "鏂板椤圭洰闃舵")
     @PostMapping("/add")
     public AjaxResult add(@RequestBody OaProjectPhase oaProjectPhase) {
         return AjaxResult.success(oaProjectPhaseService.save(oaProjectPhase));
     }
 
-    @ApiOperation("鍒犻櫎椤圭洰闃舵")
+    @Operation(summary = "鍒犻櫎椤圭洰闃舵")
     @DeleteMapping("/delete/{phaseId}")
     public AjaxResult delete(@PathVariable Integer phaseId) {
         return AjaxResult.success(oaProjectPhaseService.deleteById(phaseId));
     }
 
-    @ApiOperation("鏇存柊椤圭洰闃舵")
+    @Operation(summary = "鏇存柊椤圭洰闃舵")
     @PostMapping("/update")
     public AjaxResult update(@RequestBody OaProjectPhase oaProjectPhase) {
         return AjaxResult.success(oaProjectPhaseService.updateById(oaProjectPhase));
     }
 
-    @ApiOperation("鏍规嵁椤圭洰id鏌ヨ椤圭洰闃舵鍒楄〃")
+    @Operation(summary = "鏍规嵁椤圭洰id鏌ヨ椤圭洰闃舵鍒楄〃")
     @GetMapping("/listByProjectId/{projectId}")
     public AjaxResult listByProjectId(@PathVariable Integer projectId) {
         return AjaxResult.success(oaProjectPhaseService.listByProjectId(projectId));
diff --git a/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseTaskController.java b/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseTaskController.java
index c0f7fc1..91a846e 100644
--- a/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseTaskController.java
+++ b/src/main/java/com/ruoyi/oA/controller/OaProjectPhaseTaskController.java
@@ -3,37 +3,37 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.oA.pojo.OaProjectPhaseTask;
 import com.ruoyi.oA.service.OaProjectPhaseTaskService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-@Api(tags = "oA椤圭洰闃舵浠诲姟绠$悊")
+@Tag(name = "oA椤圭洰闃舵浠诲姟绠$悊")
 @RestController
 @RequestMapping("/oA/projectPhaseTask")
+@AllArgsConstructor
 public class OaProjectPhaseTaskController {
-    @Autowired
-    private OaProjectPhaseTaskService oaProjectPhaseTaskService;
+    private final OaProjectPhaseTaskService oaProjectPhaseTaskService;
 
-    @ApiOperation("鏂板椤圭洰闃舵浠诲姟")
+    @Operation(summary = "鏂板椤圭洰闃舵浠诲姟")
     @PostMapping("/add")
     public AjaxResult add(@RequestBody OaProjectPhaseTask oaProjectPhaseTask) {
         return AjaxResult.success(oaProjectPhaseTaskService.save(oaProjectPhaseTask));
     }
 
-    @ApiOperation("鏍规嵁椤圭洰闃舵id鏌ヨ椤圭洰闃舵浠诲姟鍒楄〃")
+    @Operation(summary = "鏍规嵁椤圭洰闃舵id鏌ヨ椤圭洰闃舵浠诲姟鍒楄〃")
     @GetMapping("/listByPhaseId/{phaseId}")
     public AjaxResult listByPhaseId(@PathVariable Integer phaseId) {
         return AjaxResult.success(oaProjectPhaseTaskService.listByPhaseId(phaseId));
     }
 
-    @ApiOperation("鍒犻櫎椤圭洰闃舵浠诲姟")
+    @Operation(summary = "鍒犻櫎椤圭洰闃舵浠诲姟")
     @DeleteMapping("/delete/{taskId}")
     public AjaxResult delete(@PathVariable Integer taskId) {
         return AjaxResult.success(oaProjectPhaseTaskService.removeById(taskId));
     }
 
-    @ApiOperation("鏇存柊椤圭洰闃舵浠诲姟")
+    @Operation(summary = "鏇存柊椤圭洰闃舵浠诲姟")
     @PostMapping("/update")
     public AjaxResult update(@RequestBody OaProjectPhaseTask oaProjectPhaseTask) {
         return AjaxResult.success(oaProjectPhaseTaskService.updateById(oaProjectPhaseTask));
diff --git a/src/main/java/com/ruoyi/oA/pojo/OaProject.java b/src/main/java/com/ruoyi/oA/pojo/OaProject.java
index 376f58f..4a5af5b 100644
--- a/src/main/java/com/ruoyi/oA/pojo/OaProject.java
+++ b/src/main/java/com/ruoyi/oA/pojo/OaProject.java
@@ -104,4 +104,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/oA/pojo/OaProjectPhase.java b/src/main/java/com/ruoyi/oA/pojo/OaProjectPhase.java
index 04326ed..b26bb9d 100644
--- a/src/main/java/com/ruoyi/oA/pojo/OaProjectPhase.java
+++ b/src/main/java/com/ruoyi/oA/pojo/OaProjectPhase.java
@@ -89,4 +89,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/oA/pojo/OaProjectPhaseTask.java b/src/main/java/com/ruoyi/oA/pojo/OaProjectPhaseTask.java
index 8241ce5..1b81069 100644
--- a/src/main/java/com/ruoyi/oA/pojo/OaProjectPhaseTask.java
+++ b/src/main/java/com/ruoyi/oA/pojo/OaProjectPhaseTask.java
@@ -114,4 +114,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/oA/service/OaProjectService.java b/src/main/java/com/ruoyi/oA/service/OaProjectService.java
index 32ba593..9f8e474 100644
--- a/src/main/java/com/ruoyi/oA/service/OaProjectService.java
+++ b/src/main/java/com/ruoyi/oA/service/OaProjectService.java
@@ -2,11 +2,11 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.oA.dto.OaProjectDto;
 import com.ruoyi.oA.pojo.OaProject;
-import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseServiceImpl.java b/src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseServiceImpl.java
index b462f36..640ec42 100644
--- a/src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseServiceImpl.java
+++ b/src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseServiceImpl.java
@@ -1,19 +1,15 @@
 package com.ruoyi.oA.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.oA.dto.OaProjectPhaseDto;
+import com.ruoyi.oA.mapper.OaProjectPhaseMapper;
 import com.ruoyi.oA.pojo.OaProjectPhase;
 import com.ruoyi.oA.pojo.OaProjectPhaseTask;
 import com.ruoyi.oA.service.OaProjectPhaseService;
-import com.ruoyi.oA.mapper.OaProjectPhaseMapper;
 import com.ruoyi.oA.service.OaProjectPhaseTaskService;
-import lombok.val;
-import org.hibernate.validator.constraints.br.TituloEleitoral;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -26,13 +22,12 @@
 * @createDate 2025-09-24 09:18:46
 */
 @Service
+@RequiredArgsConstructor
 @Transactional(rollbackFor = Exception.class)
 public class OaProjectPhaseServiceImpl extends ServiceImpl<OaProjectPhaseMapper, OaProjectPhase>
     implements OaProjectPhaseService{
-    @Autowired
-    private OaProjectPhaseMapper oaProjectPhaseMapper;
-    @Autowired
-    private OaProjectPhaseTaskService oaProjectPhaseTaskService;
+    private final OaProjectPhaseMapper oaProjectPhaseMapper;
+    private final OaProjectPhaseTaskService oaProjectPhaseTaskService;
 
     @Override
     public List<OaProjectPhaseDto> listByProjectId(Integer oaProjectId) {
diff --git a/src/main/java/com/ruoyi/oA/service/impl/OaProjectServiceImpl.java b/src/main/java/com/ruoyi/oA/service/impl/OaProjectServiceImpl.java
index 149c04f..afe125a 100644
--- a/src/main/java/com/ruoyi/oA/service/impl/OaProjectServiceImpl.java
+++ b/src/main/java/com/ruoyi/oA/service/impl/OaProjectServiceImpl.java
@@ -5,18 +5,17 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
 import com.ruoyi.oA.dto.OaProjectDto;
+import com.ruoyi.oA.mapper.OaProjectMapper;
 import com.ruoyi.oA.pojo.OaProject;
 import com.ruoyi.oA.pojo.OaProjectPhase;
 import com.ruoyi.oA.service.OaProjectPhaseService;
 import com.ruoyi.oA.service.OaProjectService;
-import com.ruoyi.oA.mapper.OaProjectMapper;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -26,12 +25,11 @@
 */
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class OaProjectServiceImpl extends ServiceImpl<OaProjectMapper, OaProject>
     implements OaProjectService{
-    @Autowired
-    private OaProjectMapper oaProjectMapper;
-    @Autowired
-    private OaProjectPhaseService oaProjectPhaseService;
+    private final OaProjectMapper oaProjectMapper;
+    private final OaProjectPhaseService oaProjectPhaseService;
 
     @Override
     public IPage<OaProjectDto> listPage(Page page, OaProjectDto oaProjectDto) {
diff --git a/src/main/java/com/ruoyi/officesupplies/controller/OfficeSuppliesController.java b/src/main/java/com/ruoyi/officesupplies/controller/OfficeSuppliesController.java
index 91243f4..3588d6c 100644
--- a/src/main/java/com/ruoyi/officesupplies/controller/OfficeSuppliesController.java
+++ b/src/main/java/com/ruoyi/officesupplies/controller/OfficeSuppliesController.java
@@ -10,14 +10,15 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.officesupplies.pojo.OfficeSupplies;
 import com.ruoyi.officesupplies.service.OfficeSuppliesService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.Date;
@@ -28,21 +29,21 @@
  * @date : 2025/9/4 14:16
  */
 @RestController
-@Api(tags = "鍔炲叕鐗╄祫")
+@Tag(name = "鍔炲叕鐗╄祫")
 @RequestMapping("/officeSupplies")
+@AllArgsConstructor
 public class OfficeSuppliesController extends BaseController {
 
-    @Autowired
     private OfficeSuppliesService officeSuppliesService;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍔炲叕鐗╄祫-鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍔炲叕鐗╄祫-鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, OfficeSupplies officeSupplies) {
         return officeSuppliesService.listPage(page, officeSupplies);
     }
 
     @PostMapping("/add")
-    @ApiOperation("鍔炲叕鐗╄祫-娣诲姞")
+    @Operation(summary = "鍔炲叕鐗╄祫-娣诲姞")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody OfficeSupplies officeSupplies) {
         // 鎸夌収褰撳墠鏃堕棿yyyyMMdd + 褰撳ぉ鏂板鏁伴噺 + 1鐢熸垚缂栧彿
@@ -58,14 +59,14 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("鍔炲叕鐗╄祫-淇敼")
+    @Operation(summary = "鍔炲叕鐗╄祫-淇敼")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody OfficeSupplies officeSupplies) {
         return officeSuppliesService.updateById(officeSupplies) ? success() : error();
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍔炲叕鐗╄祫-鍒犻櫎")
+    @Operation(summary = "鍔炲叕鐗╄祫-鍒犻櫎")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
@@ -77,7 +78,7 @@
      */
     @Log(title = "瀵煎嚭鍔炲叕鐗╄祫", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭鍔炲叕鐗╄祫")
+    @Operation(summary = "瀵煎嚭鍔炲叕鐗╄祫")
     public void export(HttpServletResponse response) {
         ExcelUtil<OfficeSupplies> util = new ExcelUtil<OfficeSupplies>(OfficeSupplies.class);
         List<OfficeSupplies> list = officeSuppliesService.list();
diff --git a/src/main/java/com/ruoyi/officesupplies/pojo/OfficeSupplies.java b/src/main/java/com/ruoyi/officesupplies/pojo/OfficeSupplies.java
index b693c10..7a1f88c 100644
--- a/src/main/java/com/ruoyi/officesupplies/pojo/OfficeSupplies.java
+++ b/src/main/java/com/ruoyi/officesupplies/pojo/OfficeSupplies.java
@@ -4,8 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.CommonFile;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,7 +17,7 @@
  * @date : 2025/9/4 14:02
  */
 @Data
-@ApiModel
+@Schema
 @TableName("office_supplies")
 public class OfficeSupplies {
 
@@ -27,49 +26,49 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("缂栧彿")
+    @Schema(description = "缂栧彿")
     @Excel(name = "缂栧彿")
     private String code;
 
-    @ApiModelProperty("鐗╁搧鍚嶇О")
+    @Schema(description = "鐗╁搧鍚嶇О")
     private String itemName;
 
-    @ApiModelProperty("鐢宠浜�")
+    @Schema(description = "鐢宠浜�")
     @Excel(name = "鐢宠浜�")
     private String applicant;
 
     /**
      * 閮ㄩ棬
      */
-    @ApiModelProperty("閮ㄩ棬")
+    @Schema(description = "閮ㄩ棬")
     @Excel(name = "閮ㄩ棬")
     private String dept;
 
     /**
      * 鐗╄祫绫诲瀷锛�1-鍏朵粬 2-娓呮磥鐢ㄥ搧 3-鐢靛瓙鐢ㄥ搧 4-鐢靛瓙璁惧锛�
      */
-    @ApiModelProperty("鐗╄祫绫诲瀷锛�1-鍏朵粬 2-娓呮磥鐢ㄥ搧 3-鐢靛瓙鐢ㄥ搧 4-鐢靛瓙璁惧锛�")
+    @Schema(description = "鐗╄祫绫诲瀷锛�1-鍏朵粬 2-娓呮磥鐢ㄥ搧 3-鐢靛瓙鐢ㄥ搧 4-鐢靛瓙璁惧锛�")
     @Excel(name = "鐗╄祫绫诲瀷", readConverterExp = "1=鍏朵粬,2=娓呮磥鐢ㄥ搧,3=鐢靛瓙鐢ㄥ搧,4=鐢靛瓙璁惧")
     private Integer materialType;
 
     /**
      * 鐢宠鏁伴噺
      */
-    @ApiModelProperty("鐢宠鏁伴噺")
+    @Schema(description = "鐢宠鏁伴噺")
     @Excel(name = "鐢宠鏁伴噺")
     private Integer applyNum;
 
     /**
      * 瀹℃壒鎰忚
      */
-    @ApiModelProperty("瀹℃壒鎰忚")
+    @Schema(description = "瀹℃壒鎰忚")
 //    @Excel(name = "瀹℃壒鎰忚")
     private String approvalOpinions;
 
     /**
      * 鐢宠鍘熷洜
      */
-    @ApiModelProperty("鐢宠鍘熷洜")
+    @Schema(description = "鐢宠鍘熷洜")
     @Excel(name = "鐢宠鍘熷洜")
     private String reason;
 
@@ -77,21 +76,21 @@
     /**
      * 绱ф�ョ▼搴︼紙1-鏅�� 2-绱ф�� 3-闈炲父绱ф�ワ級
      */
-    @ApiModelProperty("绱ф�ョ▼搴︼紙1-鏅�� 2-绱ф�� 3-闈炲父绱ф�ワ級")
+    @Schema(description = "绱ф�ョ▼搴︼紙1-鏅�� 2-绱ф�� 3-闈炲父绱ф�ワ級")
 //    @Excel(name = "绱ф�ョ▼搴�", readConverterExp = "1=鏅��,2=绱ф��,3=闈炲父绱ф��")
     private Integer urgency;
 
     /**
      * 鐘舵�侊紙1-寰呭鎵� 2-宸叉嫆缁� 3-宸查�氳繃 4-宸插彂鏀撅級
      */
-    @ApiModelProperty("鐘舵�侊紙1-寰呭鎵� 2-宸叉嫆缁� 3-宸查�氳繃 4-宸插彂鏀撅級")
+    @Schema(description = "鐘舵�侊紙1-寰呭鎵� 2-宸叉嫆缁� 3-宸查�氳繃 4-宸插彂鏀撅級")
     @Excel(name = "鐘舵��", readConverterExp = "1=寰呭鎵�,2=宸叉嫆缁�,3=宸查�氳繃,4=宸插彂鏀�")
     private Integer status;
 
     /**
      * 鐢宠鏃堕棿
      */
-    @ApiModelProperty("鐢宠鏃堕棿")
+    @Schema(description = "鐢宠鏃堕棿")
     @Excel(name = "鐢宠鏃堕棿" , width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -101,14 +100,14 @@
     /**
      * 瀹℃壒浜�
      */
-    @ApiModelProperty("瀹℃壒浜�")
+    @Schema(description = "瀹℃壒浜�")
     @Excel(name = "瀹℃壒浜�")
     private String approval;
 
     /**
      * 瀹℃壒鏃堕棿
      */
-    @ApiModelProperty("瀹℃壒鏃堕棿")
+    @Schema(description = "瀹℃壒鏃堕棿")
     @Excel(name = "瀹℃壒鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -117,13 +116,13 @@
     /**
      * 鍙戞斁鏃堕棿
      */
-    @ApiModelProperty("鍙戞斁鏃堕棿")
+    @Schema(description = "鍙戞斁鏃堕棿")
     @Excel(name = "鍙戞斁鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date issueTime;
 
-    @ApiModelProperty("鍙戞斁浜�")
+    @Schema(description = "鍙戞斁浜�")
 //    @Excel(name = "鍙戞斁浜�")
     private String issueUser;
 
@@ -157,4 +156,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/officesupplies/service/impl/OfficeSuppliesServiceImpl.java b/src/main/java/com/ruoyi/officesupplies/service/impl/OfficeSuppliesServiceImpl.java
index 2ba961f..abdc1c7 100644
--- a/src/main/java/com/ruoyi/officesupplies/service/impl/OfficeSuppliesServiceImpl.java
+++ b/src/main/java/com/ruoyi/officesupplies/service/impl/OfficeSuppliesServiceImpl.java
@@ -7,8 +7,8 @@
 import com.ruoyi.officesupplies.mapper.OfficeSuppliesMapper;
 import com.ruoyi.officesupplies.pojo.OfficeSupplies;
 import com.ruoyi.officesupplies.service.OfficeSuppliesService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -17,10 +17,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class OfficeSuppliesServiceImpl extends ServiceImpl<OfficeSuppliesMapper, OfficeSupplies> implements OfficeSuppliesService {
 
-    @Autowired
-    private OfficeSuppliesMapper officeSuppliesMapper;
+    private final OfficeSuppliesMapper officeSuppliesMapper;
 
     @Override
     public AjaxResult listPage(Page page, OfficeSupplies officeSupplies) {
diff --git a/src/main/java/com/ruoyi/other/controller/PdaVersionController.java b/src/main/java/com/ruoyi/other/controller/PdaVersionController.java
new file mode 100644
index 0000000..326db6a
--- /dev/null
+++ b/src/main/java/com/ruoyi/other/controller/PdaVersionController.java
@@ -0,0 +1,31 @@
+package com.ruoyi.other.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.other.dto.PdaVersionDTO;
+import com.ruoyi.other.pojo.PdaVersion;
+import com.ruoyi.other.service.PdaVersionService;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/app")
+@AllArgsConstructor
+public class PdaVersionController {
+
+    private PdaVersionService pdaVersionService;
+
+    @Operation(summary = "鏌ヨ鎵�鏈夌増鏈�")
+    @GetMapping("/getAllVersion")
+    public R getAllVersion(Page<PdaVersion> page, PdaVersion pdaVersion) {
+        return R.ok(pdaVersionService.getAllVersion(page, pdaVersion));
+    }
+
+    @Operation(summary = "娣诲姞鐗堟湰")
+    @PostMapping("/add")
+    public R add(@RequestBody PdaVersionDTO pdaVersion) {
+        return R.ok(pdaVersionService.add(pdaVersion));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/other/controller/TempFileController.java b/src/main/java/com/ruoyi/other/controller/TempFileController.java
deleted file mode 100644
index 1175eb0..0000000
--- a/src/main/java/com/ruoyi/other/controller/TempFileController.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.ruoyi.other.controller;
-
-
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.other.service.TempFileService;
-import com.ruoyi.purchase.dto.ProductRecordDto;
-import com.ruoyi.purchase.dto.TicketRegistrationDto;
-import com.ruoyi.purchase.service.ITicketRegistrationService;
-import com.ruoyi.purchase.service.impl.TicketRegistrationServiceImpl;
-import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-
-
-@RestController
-@RequestMapping("/file")
-@AllArgsConstructor
-public class TempFileController {
-
-    private TempFileService tempFileService;
-
-    private TicketRegistrationServiceImpl ticketRegistrationServiceImpl;
-
-    @PostMapping("/upload")
-    public AjaxResult uploadFile(MultipartFile file, Integer type) {
-        try {
-            return AjaxResult.success(tempFileService.uploadFile(file, type));
-        } catch (Exception e) {
-            return AjaxResult.error(e.getMessage());
-        }
-    }
-
-    @PostMapping("/uploadByCommon")
-    public AjaxResult uploadByCommon(MultipartFile file, Integer type, Long id) {
-        try {
-            return AjaxResult.success(tempFileService.uploadByCommon(file, type,id));
-        } catch (Exception e) {
-            return AjaxResult.error(e.getMessage());
-        }
-    }
-
-    @PostMapping("uploadFile")
-    public AjaxResult uploadFile(@RequestBody ProductRecordDto productRecordDto) {
-        try {
-            if (!productRecordDto.getTempFileIds().isEmpty()&&productRecordDto.getTicketRegistrationId() != null) {
-                ticketRegistrationServiceImpl.migrateTempFilesToFormal(productRecordDto.getTicketRegistrationId(), productRecordDto.getTempFileIds());
-            }
-        } catch (Exception e) {
-            return AjaxResult.error(e.getMessage());
-        }
-        return AjaxResult.success();
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/other/dto/PdaVersionDTO.java b/src/main/java/com/ruoyi/other/dto/PdaVersionDTO.java
new file mode 100644
index 0000000..9cec0e7
--- /dev/null
+++ b/src/main/java/com/ruoyi/other/dto/PdaVersionDTO.java
@@ -0,0 +1,15 @@
+package com.ruoyi.other.dto;
+
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.other.pojo.PdaVersion;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class PdaVersionDTO extends PdaVersion {
+    private List<StorageBlobDTO> storageBlobDTOList;
+    private List<StorageBlobVO> storageBlobVOList;
+    private String downloadURL;
+}
diff --git a/src/main/java/com/ruoyi/other/mapper/PdaVersionMapper.java b/src/main/java/com/ruoyi/other/mapper/PdaVersionMapper.java
new file mode 100644
index 0000000..d688651
--- /dev/null
+++ b/src/main/java/com/ruoyi/other/mapper/PdaVersionMapper.java
@@ -0,0 +1,9 @@
+package com.ruoyi.other.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.other.pojo.PdaVersion;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface PdaVersionMapper extends BaseMapper<PdaVersion> {
+}
diff --git a/src/main/java/com/ruoyi/other/pojo/PdaVersion.java b/src/main/java/com/ruoyi/other/pojo/PdaVersion.java
new file mode 100644
index 0000000..8c0fc60
--- /dev/null
+++ b/src/main/java/com/ruoyi/other/pojo/PdaVersion.java
@@ -0,0 +1,54 @@
+package com.ruoyi.other.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("pda_version")
+@Schema(name = "PdaVersion", description = "PDA鐗堟湰淇℃伅琛�")
+public class PdaVersion implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鍚嶇О")
+    private String name;
+
+    @Schema(description = "鐗堟湰鍙�")
+    private String version;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鍒涘缓浜�")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @Schema(description = "鏇存柊浜�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @Schema(description = "绉熸埛ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/other/pojo/TempFile.java b/src/main/java/com/ruoyi/other/pojo/TempFile.java
index bff7805..11aa897 100644
--- a/src/main/java/com/ruoyi/other/pojo/TempFile.java
+++ b/src/main/java/com/ruoyi/other/pojo/TempFile.java
@@ -1,14 +1,18 @@
 package com.ruoyi.other.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
+import java.io.Serializable;
 import java.time.LocalDateTime;
 
 @Data
 @TableName("temp_file")
-public class TempFile {
+public class TempFile implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @TableId
@@ -17,4 +21,12 @@
     private String tempPath;       // 涓存椂瀛樺偍璺緞
     private LocalDateTime expireTime; // 杩囨湡鏃堕棿
     private Integer type;       // 鍏宠仈琛ㄧ被鍨�
+    private Long fileSize;       // 鏂囦欢澶у皬
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/other/service/PdaVersionService.java b/src/main/java/com/ruoyi/other/service/PdaVersionService.java
new file mode 100644
index 0000000..387eae3
--- /dev/null
+++ b/src/main/java/com/ruoyi/other/service/PdaVersionService.java
@@ -0,0 +1,13 @@
+package com.ruoyi.other.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.other.dto.PdaVersionDTO;
+import com.ruoyi.other.pojo.PdaVersion;
+
+public interface PdaVersionService extends IService<PdaVersion> {
+    IPage<PdaVersionDTO> getAllVersion(Page<PdaVersion> page, PdaVersion pdaVersion);
+
+    boolean add(PdaVersionDTO pdaVersion);
+}
diff --git a/src/main/java/com/ruoyi/other/service/TempFileService.java b/src/main/java/com/ruoyi/other/service/TempFileService.java
deleted file mode 100644
index 355e43c..0000000
--- a/src/main/java/com/ruoyi/other/service/TempFileService.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.ruoyi.other.service;
-
-import com.ruoyi.other.pojo.TempFile;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-
-public interface TempFileService {
-    TempFile uploadFile(MultipartFile file,Integer type) throws IOException;
-
-    String uploadByCommon(MultipartFile file, Integer type, Long id) throws IOException;
-}
diff --git a/src/main/java/com/ruoyi/other/service/impl/PdaVersionServiceImpl.java b/src/main/java/com/ruoyi/other/service/impl/PdaVersionServiceImpl.java
new file mode 100644
index 0000000..3c4dca8
--- /dev/null
+++ b/src/main/java/com/ruoyi/other/service/impl/PdaVersionServiceImpl.java
@@ -0,0 +1,60 @@
+package com.ruoyi.other.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.other.dto.PdaVersionDTO;
+import com.ruoyi.other.mapper.PdaVersionMapper;
+import com.ruoyi.other.pojo.PdaVersion;
+import com.ruoyi.other.service.PdaVersionService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class)
+public class PdaVersionServiceImpl extends ServiceImpl<PdaVersionMapper, PdaVersion> implements PdaVersionService {
+
+    private final PdaVersionMapper pdaVersionMapper;
+
+    private final FileUtil fileUtil;
+
+    @Override
+    public IPage<PdaVersionDTO> getAllVersion(Page<PdaVersion> page, PdaVersion pdaVersion) {
+        LambdaQueryWrapper<PdaVersion> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.orderByDesc(PdaVersion::getCreateTime);
+        Page<PdaVersion> pdaVersionPage = pdaVersionMapper.selectPage(page, queryWrapper);
+        Page<PdaVersionDTO> pdaVersionDTOPage = new Page<>(page.getCurrent(), page.getSize());
+        List<PdaVersionDTO> pdaVersionDTOList = new ArrayList<>();
+        pdaVersionPage.getRecords().forEach(item -> {
+            PdaVersionDTO pdaVersionDTO = new PdaVersionDTO();
+            BeanUtil.copyProperties(item, pdaVersionDTO);
+            pdaVersionDTO.setStorageBlobVOList(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.APK, RecordTypeEnum.PDA_VERSION, item.getId()));
+            String downloadURL = fileUtil.getFileDownloadURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.APK, RecordTypeEnum.PDA_VERSION, item.getId()).get(0) == null ?
+                    "" : fileUtil.getFileDownloadURLByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.APK, RecordTypeEnum.PDA_VERSION, item.getId()).get(0);
+            pdaVersionDTO.setDownloadURL(downloadURL);
+            pdaVersionDTOList.add(pdaVersionDTO);
+        });
+        pdaVersionDTOPage.setRecords(pdaVersionDTOList);
+        return pdaVersionDTOPage;
+    }
+
+    @Override
+    public boolean add(PdaVersionDTO pdaVersion) {
+        // 鍙傛暟鏍¢獙
+        Assert.hasText(pdaVersion.getVersion(), "鐗堟湰鍙蜂笉鑳戒负绌�");
+        pdaVersionMapper.insert(pdaVersion);
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.APK, RecordTypeEnum.PDA_VERSION, pdaVersion.getId(), pdaVersion.getStorageBlobDTOList());
+        return true;
+    }
+}
diff --git a/src/main/java/com/ruoyi/other/service/impl/TempFileServiceImpl.java b/src/main/java/com/ruoyi/other/service/impl/TempFileServiceImpl.java
deleted file mode 100644
index b8e0e2a..0000000
--- a/src/main/java/com/ruoyi/other/service/impl/TempFileServiceImpl.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package com.ruoyi.other.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.other.pojo.TempFile;
-import com.ruoyi.other.service.TempFileService;
-import com.ruoyi.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.pojo.CommonFile;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.catalina.util.URLEncoder;
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.Collections;
-import java.util.List;
-import java.util.UUID;
-
-@Service
-@Slf4j
-public class TempFileServiceImpl extends ServiceImpl<TempFileMapper, TempFile> implements TempFileService {
-
-    @Autowired
-    private TempFileMapper tempFileMapper;
-
-    @Autowired
-    private CommonFileMapper commonFileMapper;
-
-    @Value("${file.upload-dir}")
-    private String uploadDir;
-
-    @Value("${file.temp-dir}")
-    private String tempDir;
-
-    // 涓婁紶鍒颁复鏃剁洰褰�
-    @Override
-    public TempFile uploadFile(MultipartFile file,Integer type) throws IOException {
-        // 1. 鐢熸垚涓存椂鏂囦欢ID鍜岃矾寰�
-        String tempId = UUID.randomUUID().toString();
-        String originalFilename = file.getOriginalFilename();
-        if(originalFilename == null) throw new IOException("鏂囦欢鍚嶄笉鑳戒负绌�");
-//        URLEncoder urlEncoder = new URLEncoder();
-//        String encodedFilename = urlEncoder.encode(originalFilename, StandardCharsets.UTF_8);
-//        encodedFilename = encodedFilename.replaceAll("%2E",".");
-//        Path tempFilePath = Paths.get(tempDir, tempId + "_" + encodedFilename);
-
-        Path tempFilePath = Paths.get(tempDir, tempId + "_" + file.getOriginalFilename());
-
-        // 2. 纭繚鐩綍瀛樺湪
-        Path parentDir = tempFilePath.getParent();
-        if (parentDir != null) {
-            Files.createDirectories(parentDir); // 閫掑綊鍒涘缓鐩綍
-        }
-
-        // 3. 淇濆瓨鏂囦欢鍒颁复鏃剁洰褰�
-        file.transferTo(tempFilePath.toFile());
-
-        // 4. 淇濆瓨涓存椂鏂囦欢璁板綍
-        TempFile tempFileRecord = new TempFile();
-        tempFileRecord.setTempId(tempId);
-        tempFileRecord.setOriginalName(file.getOriginalFilename());
-        tempFileRecord.setTempPath(tempFilePath.toString());
-        tempFileRecord.setExpireTime(LocalDateTime.now().plusHours(2)); // 2灏忔椂鍚庤繃鏈�
-        tempFileRecord.setType(type);
-        tempFileMapper.insert(tempFileRecord);
-        return tempFileRecord;
-    }
-
-    @Override
-    public String uploadByCommon(MultipartFile file, Integer type, Long id) throws  IOException{
-        TempFile tempFile = uploadFile(file, type);
-        if (tempFile != null) {
-            migrateTempFilesToFormal(id, Collections.singletonList(tempFile.getTempId()), type);
-            return tempFile.getTempPath();
-        }
-        return null;
-    }
-
-    /**
-     * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
-     *
-     * @param businessId  涓氬姟ID锛堥攢鍞彴璐D锛�
-     * @param tempFileIds 涓存椂鏂囦欢ID鍒楄〃
-     * @param fileType     鏂囦欢绫诲瀷(鏉ヨ嚜FileNameType)
-     * @throws IOException 鏂囦欢鎿嶄綔寮傚父
-     */
-    public void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds, Integer fileType) throws IOException {
-        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(tempFileIds)) {
-            return;
-        }
-
-        // 鏋勫缓姝e紡鐩綍璺緞锛堟寜涓氬姟绫诲瀷鍜屾棩鏈熷垎缁勶級
-        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
-
-        Path formalDirPath = Paths.get(formalDir);
-
-        // 纭繚姝e紡鐩綍瀛樺湪锛堥�掑綊鍒涘缓锛�
-        if (!Files.exists(formalDirPath)) {
-            Files.createDirectories(formalDirPath);
-        }
-
-        for (String tempFileId : tempFileIds) {
-            // 鏌ヨ涓存椂鏂囦欢璁板綍
-            TempFile tempFile = tempFileMapper.selectById(tempFileId);
-            if (tempFile == null) {
-                log.warn("涓存椂鏂囦欢涓嶅瓨鍦紝璺宠繃澶勭悊: {}", tempFileId);
-                continue;
-            }
-
-            // 鏋勫缓姝e紡鏂囦欢鍚嶏紙鍖呭惈涓氬姟ID鍜屾椂闂存埑锛岄伩鍏嶅啿绐侊級
-            String originalFilename = tempFile.getOriginalName();
-            String fileExtension = FilenameUtils.getExtension(originalFilename);
-            String formalFilename = businessId + "_" +
-                    System.currentTimeMillis() + "_" +
-                    UUID.randomUUID().toString().substring(0, 8) +
-                    (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
-
-            Path formalFilePath = formalDirPath.resolve(formalFilename);
-
-            try {
-                // 鎵ц鏂囦欢杩佺Щ锛堜娇鐢ㄥ師瀛愭搷浣滅‘淇濆畨鍏ㄦ�э級
-//                Files.move(
-//                        Paths.get(tempFile.getTempPath()),
-//                        formalFilePath,
-//                        StandardCopyOption.REPLACE_EXISTING,
-//                        StandardCopyOption.ATOMIC_MOVE
-//                );
-                // 鍘熷瓙绉诲姩澶辫触锛屼娇鐢ㄥ鍒�+鍒犻櫎
-                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
-                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-
-                // 鏇存柊鏂囦欢璁板綍锛堝叧鑱斿埌涓氬姟ID锛�
-                CommonFile fileRecord = new CommonFile();
-                fileRecord.setCommonId(businessId);
-                fileRecord.setName(originalFilename);
-                fileRecord.setUrl(formalFilePath.toString());
-                fileRecord.setCreateTime(LocalDateTime.now());
-                fileRecord.setType(fileType);
-                commonFileMapper.insert(fileRecord);
-
-                // 鍒犻櫎涓存椂鏂囦欢璁板綍
-                tempFileMapper.deleteById(tempFile);
-
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-            } catch (IOException e) {
-                log.error("鏂囦欢杩佺Щ澶辫触: {}", tempFile.getTempPath(), e);
-                // 鍙�夋嫨鍥炴粴浜嬪姟鎴栬褰曞け璐ユ枃浠�
-                throw new IOException("鏂囦欢杩佺Щ寮傚父", e);
-            }
-        }
-    }
-
-//    @Scheduled(cron = "0 0 3 * * ?") // 姣忓ぉ鍑屾櫒3鐐规墽琛�
-    public void cleanupExpiredTempFiles() {
-        LambdaQueryWrapper<TempFile> wrapper = new LambdaQueryWrapper<>();
-        wrapper.lt(TempFile::getExpireTime, LocalDateTime.now()); // expireTime < 褰撳墠鏃堕棿
-
-        List<TempFile> expiredFiles = tempFileMapper.selectList(wrapper);
-        for (TempFile file : expiredFiles) {
-            try {
-                // 鍒犻櫎鐗╃悊鏂囦欢
-                Files.deleteIfExists(Paths.get(file.getTempPath()));
-                // 鍒犻櫎鏁版嵁搴撹褰�
-                tempFileMapper.deleteById(file);
-                log.info("宸叉竻鐞嗚繃鏈熶复鏃舵枃浠�: {}", file.getTempPath());
-            } catch (IOException e) {
-                log.error("鍒犻櫎鏂囦欢澶辫触: {}", file.getTempPath(), e);
-                // 鍙�夋嫨璁板綍澶辫触鏃ュ織鎴栭噸璇�
-            }
-        }
-        log.info("杩囨湡涓存椂鏂囦欢娓呯悊瀹屾垚锛屽叡娓呯悊 {} 涓枃浠�", expiredFiles.size());
-    }
-}
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/GasTankWarningController.java b/src/main/java/com/ruoyi/procurementrecord/controller/GasTankWarningController.java
index 7646478..ea214c2 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/GasTankWarningController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/GasTankWarningController.java
@@ -6,39 +6,43 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.procurementrecord.pojo.GasTankWarning;
 import com.ruoyi.procurementrecord.service.GasTankWarningService;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/gasTankWarning")
+@AllArgsConstructor
 public class GasTankWarningController {
-    @Autowired
     private GasTankWarningService gasTankWarningService;
 
     @GetMapping("/listPage")
     public AjaxResult listPage(Page page, GasTankWarning gasTankWarning) {
         return AjaxResult.success(gasTankWarningService.listPage(page, gasTankWarning));
     }
+
     @PostMapping("/add")
     public AjaxResult add(@RequestBody GasTankWarning gasTankWarning) {
         return AjaxResult.success(gasTankWarningService.save(gasTankWarning));
     }
+
     @PostMapping("update")
     public AjaxResult update(@RequestBody GasTankWarning gasTankWarning) {
         return AjaxResult.success(gasTankWarningService.updateById(gasTankWarning));
     }
+
     @DeleteMapping("delete")
-    public AjaxResult delete(@RequestBody List<Long> ids){
-        if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
+    public AjaxResult delete(@RequestBody List<Long> ids) {
+        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         return AjaxResult.success(gasTankWarningService.removeByIds(ids));
     }
+
     //瀵煎嚭
     @PostMapping("/export")
-    public void export(HttpServletResponse response,@RequestParam(name = "ids", required = false) List<Long> ids){
-        gasTankWarningService.export(response,ids);
+    public void export(HttpServletResponse response, @RequestParam(name = "ids", required = false) List<Long> ids) {
+        gasTankWarningService.export(response, ids);
     }
 
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/InboundManagementController.java b/src/main/java/com/ruoyi/procurementrecord/controller/InboundManagementController.java
index b8ffa23..0a2919d 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/InboundManagementController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/InboundManagementController.java
@@ -7,9 +7,9 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.procurementrecord.pojo.InboundManagement;
 import com.ruoyi.procurementrecord.service.InboundManagementService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -21,22 +21,22 @@
  * @date : 2025/9/16 16:38
  */
 @RestController
-@Api(tags = "鍒拌揣绠$悊")
+@Tag(name = "鍒拌揣绠$悊")
 @RequestMapping("/inboundManagement")
+@AllArgsConstructor
 public class InboundManagementController extends BaseController {
 
-    @Autowired
     private InboundManagementService inboundManagementService;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍒拌揣绠$悊-鏌ヨ")
+    @Operation(summary = "鍒拌揣绠$悊-鏌ヨ")
     public AjaxResult listPage(Page page, InboundManagement inboundManagement) {
         IPage<InboundManagement> result = inboundManagementService.listPage(page, inboundManagement);
         return AjaxResult.success(result);
     }
 
     @PostMapping("/add")
-    @ApiOperation("鍒拌揣绠$悊-娣诲姞")
+    @Operation(summary = "鍒拌揣绠$悊-娣诲姞")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody InboundManagement inboundManagement) {
         inboundManagement.setArrivalTime(new Date());
@@ -45,7 +45,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("鍒拌揣绠$悊-淇敼")
+    @Operation(summary = "鍒拌揣绠$悊-淇敼")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody InboundManagement inboundManagement) {
         boolean result = inboundManagementService.updateById(inboundManagement);
@@ -53,7 +53,7 @@
     }
 
     @DeleteMapping("/del")
-    @ApiOperation("鍒拌揣绠$悊-鍒犻櫎")
+    @Operation(summary = "鍒拌揣绠$悊-鍒犻櫎")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult del(@RequestBody List<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementExceptionRecordController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementExceptionRecordController.java
index d9bc6fc..c594994 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementExceptionRecordController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementExceptionRecordController.java
@@ -10,13 +10,14 @@
 import com.ruoyi.procurementrecord.mapper.ProcurementExceptionRecordMapper;
 import com.ruoyi.procurementrecord.pojo.ProcurementExceptionRecord;
 import com.ruoyi.procurementrecord.service.ProcurementRecordService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -24,12 +25,11 @@
  * @date : 2025/7/7 14:32
  */
 @RestController
-@Api(tags = "閲囪喘寮傚父璁板綍")
+@Tag(name = "閲囪喘寮傚父璁板綍")
 @RequestMapping("/procurementExceptionRecord")
+@AllArgsConstructor
 public class ProcurementExceptionRecordController extends BaseController {
 
-
-    @Autowired
     private ProcurementExceptionRecordMapper procurementExceptionRecordMapper;
 
     @PostMapping("/add")
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java
index 64d9dc8..1d442a9 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java
@@ -6,12 +6,12 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.procurementrecord.pojo.ProcurementPlan;
 import com.ruoyi.procurementrecord.service.ProcurementPlanService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -19,36 +19,36 @@
  * @date : 2025/9/18 16:13
  */
 @RestController
-@Api(tags = "閲囪喘璁″垝")
+@Tag(name = "閲囪喘璁″垝")
 @RequestMapping("/procurementPlan")
+@AllArgsConstructor
 public class ProcurementPlanController extends BaseController {
 
-    @Autowired
     private ProcurementPlanService procurementPlanService;
 
     @RequestMapping("/listPage")
-    @ApiOperation("閲囪喘璁″垝-鏌ヨ")
+    @Operation(summary = "閲囪喘璁″垝-鏌ヨ")
     public AjaxResult listPage(Page page, ProcurementPlan procurementPlan){
         IPage<ProcurementPlan> result = procurementPlanService.listPage(page, procurementPlan);
         return AjaxResult.success(result);
     }
 
     @PostMapping("/add")
-    @ApiOperation("閲囪喘璁″垝-娣诲姞")
+    @Operation(summary = "閲囪喘璁″垝-娣诲姞")
     public AjaxResult add(@RequestBody ProcurementPlan procurementPlan){
         boolean result = procurementPlanService.save(procurementPlan);
         return result ? AjaxResult.success() : AjaxResult.error();
     }
 
     @PostMapping("/update")
-    @ApiOperation("閲囪喘璁″垝-淇敼")
+    @Operation(summary = "閲囪喘璁″垝-淇敼")
     public AjaxResult update(@RequestBody ProcurementPlan procurementPlan){
         boolean result = procurementPlanService.updateById(procurementPlan);
         return result ? AjaxResult.success() : AjaxResult.error();
     }
 
     @DeleteMapping("/del")
-    @ApiOperation("閲囪喘璁″垝-鍒犻櫎")
+    @Operation(summary = "閲囪喘璁″垝-鍒犻櫎")
     public AjaxResult del(@RequestBody List<Long> ids){
         boolean result = procurementPlanService.removeByIds(ids);
         return result ? AjaxResult.success() : AjaxResult.error();
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPriceManagementController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPriceManagementController.java
index 9135b7b..678446c 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPriceManagementController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPriceManagementController.java
@@ -6,13 +6,13 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.procurementrecord.pojo.ProcurementPriceManagement;
 import com.ruoyi.procurementrecord.service.ProcurementPriceManagementService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -20,22 +20,22 @@
  * @date : 2025/9/17 15:08
  */
 @RestController
-@Api(tags = "閲囪喘浠锋牸绠$悊")
+@Tag(name = "閲囪喘浠锋牸绠$悊")
 @RequestMapping("/procurementPriceManagement")
+@AllArgsConstructor
 public class ProcurementPriceManagementController extends BaseController {
 
-    @Autowired
     private ProcurementPriceManagementService procurementPriceManagementService;
 
     @GetMapping("/listPage")
-    @ApiOperation("閲囪喘浠锋牸绠$悊-鏌ヨ")
+    @Operation(summary = "閲囪喘浠锋牸绠$悊-鏌ヨ")
     public AjaxResult listPage(Page page, ProcurementPriceManagement procurementPriceManagement){
         IPage<ProcurementPriceManagement> result = procurementPriceManagementService.listPage(page, procurementPriceManagement);
         return AjaxResult.success(result);
     }
 
     @PostMapping("/add")
-    @ApiOperation("閲囪喘浠锋牸绠$悊-娣诲姞")
+    @Operation(summary = "閲囪喘浠锋牸绠$悊-娣诲姞")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody ProcurementPriceManagement procurementPriceManagement){
         boolean result = procurementPriceManagementService.save(procurementPriceManagement);
@@ -43,7 +43,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("閲囪喘浠锋牸绠$悊-淇敼")
+    @Operation(summary = "閲囪喘浠锋牸绠$悊-淇敼")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody ProcurementPriceManagement procurementPriceManagement){
         boolean result = procurementPriceManagementService.updateById(procurementPriceManagement);
@@ -51,7 +51,7 @@
     }
 
     @DeleteMapping("/del")
-    @ApiOperation("閲囪喘浠锋牸绠$悊-鍒犻櫎")
+    @Operation(summary = "閲囪喘浠锋牸绠$悊-鍒犻櫎")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids){
         if (ids == null || ids.isEmpty()) {
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java
index 879b328..e567eea 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java
@@ -12,14 +12,16 @@
 import com.ruoyi.procurementrecord.mapper.CustomStorageMapper;
 import com.ruoyi.procurementrecord.pojo.CustomStorage;
 import com.ruoyi.procurementrecord.service.ProcurementRecordService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.apache.ibatis.annotations.Delete;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+
 import java.util.List;
 
 /**
@@ -27,22 +29,22 @@
  * @date : 2025/7/7 14:32
  */
 @RestController
-@Api(tags = "閲囪喘鍏ュ簱")
+@Tag(name = "閲囪喘鍏ュ簱")
 @RequestMapping("/stockin")
+@AllArgsConstructor
 public class ProcurementRecordController extends BaseController {
 
-
-    @Autowired
     private ProcurementRecordService procurementRecordService;
-
+    private CustomStorageMapper customStorageMapper;
 
     /**
      * 閫氳繃閿�鍞骇鍝乮d鑾峰彇鍏ュ簱鏁伴噺
+     *
      * @param salesProductId
      * @return
      */
     @GetMapping("/getProcurementAmount")
-    @ApiOperation(value = "閫氳繃閿�鍞骇鍝乮d鑾峰彇鍏ュ簱鏁伴噺")
+    @Operation(summary = "閫氳繃閿�鍞骇鍝乮d鑾峰彇鍏ュ簱鏁伴噺")
     public AjaxResult getProcurementAmount(@RequestParam("salesProductId") Long salesProductId) {
         return AjaxResult.success(procurementRecordService.getProcurementAmount(salesProductId));
     }
@@ -115,19 +117,21 @@
 
     @GetMapping("/listPage")
     @Log(title = "閲囪喘鍏ュ簱-鍏ュ簱绠$悊-鍏ュ簱鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation(value = "鍏ュ簱鏌ヨ")
+    @Operation(summary = "鍏ュ簱鏌ヨ")
     public AjaxResult listPage(Page page, ProcurementPageDto procurementDto) {
         IPage<ProcurementPageDto> result = procurementRecordService.listPage(page, procurementDto);
         return AjaxResult.success(result);
     }
+
     @GetMapping("/listReport")
-    @ApiOperation(value = "鏌ヨ搴撳瓨鍥捐〃鏁版嵁")
+    @Operation(summary = "鏌ヨ搴撳瓨鍥捐〃鏁版嵁")
     public AjaxResult listReport() {
         return AjaxResult.success(procurementRecordService.getReportList());
     }
+
     @GetMapping("/listPageByProduction")
     @Log(title = "鐢熶骇鍏ュ簱-鍏ュ簱绠$悊-鍏ュ簱鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation(value = "鍏ュ簱鏌ヨ")
+    @Operation(summary = "鍏ュ簱鏌ヨ")
     public AjaxResult listPageByProduction(Page page, ProcurementPageDto procurementDto) {
         IPage<ProcurementPageDto> result = procurementRecordService.listPageByProduction(page, procurementDto);
         return AjaxResult.success(result);
@@ -135,7 +139,7 @@
 
     @GetMapping("/listPageByProductProduction")
     @Log(title = "鐢熶骇鍏ュ簱-鍏ュ簱绠$悊-鐢熶骇鍏ュ簱鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation(value = "鍏ュ簱鏌ヨ")
+    @Operation(summary = "鍏ュ簱鏌ヨ")
     public AjaxResult listPageByProductProduction(Page page, ProcurementPageDto procurementDto) {
         IPage<ProcurementPageDto> result = procurementRecordService.listPageByProductProduction(page, procurementDto);
         return AjaxResult.success(result);
@@ -143,7 +147,7 @@
 
     @GetMapping("/listPageByCustom")
     @Log(title = "鑷畾涔夊叆搴�-鍏ュ簱绠$悊-鍏ュ簱鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation(value = "鍏ュ簱鏌ヨ")
+    @Operation(summary = "鍏ュ簱鏌ヨ")
     public AjaxResult listPageByCustom(Page page, CustomStorage customStorage) {
         IPage<CustomStorage> result = procurementRecordService.listPageByCustom(page, customStorage);
         return AjaxResult.success(result);
@@ -178,54 +182,58 @@
 
     /**
      * 搴撳瓨绠$悊閲囪喘瀵煎嚭
+     *
      * @param response
      */
     @PostMapping("/exportCopy")
     public void exportCopy(HttpServletResponse response) {
-        procurementRecordService.exportCopy(response,1);
+        procurementRecordService.exportCopy(response, 1);
     }
 
     /**
      * 搴撳瓨绠$悊鐢熶骇瀵煎嚭
+     *
      * @param response
      */
     @PostMapping("/exportCopyOne")
     public void exportCopyOne(HttpServletResponse response) {
-        procurementRecordService.exportCopy(response,2);
+        procurementRecordService.exportCopy(response, 2);
     }
 
     /**
      * 搴撳瓨绠$悊鑷畾涔夊鍑�
+     *
      * @param response
      */
     @PostMapping("/exportCopyTwo")
     public void exportCopyTwo(HttpServletResponse response) {
-        procurementRecordService.exportCopyTwo(response,3);
+        procurementRecordService.exportCopyTwo(response, 3);
     }
 
     /**
      * 鍏ュ簱锛屽嚭搴撶鐞嗛噰璐鍑�
+     *
      * @param response
      */
     @PostMapping("/export")
     public void export(HttpServletResponse response) {
-        procurementRecordService.export(response,1);
+        procurementRecordService.export(response, 1);
     }
 
     /**
      * 鍏ュ簱锛屽嚭搴撶鐞嗙敓浜у鍑�
+     *
      * @param response
      */
     @PostMapping("/exportOne")
     public void exportOne(HttpServletResponse response) {
-        procurementRecordService.export(response,2);
+        procurementRecordService.export(response, 2);
     }
 
-    @Autowired
-    private CustomStorageMapper customStorageMapper;
 
     /**
      * 鍏ュ簱锛屽嚭搴撶鐞嗚嚜瀹氫箟瀵煎嚭
+     *
      * @param response
      */
     @PostMapping("/exportTwo")
@@ -238,7 +246,7 @@
     @GetMapping("/listPageProductionStock")
     @Log(title = "搴撳瓨绠$悊-鎴愬搧搴撳瓨", businessType = BusinessType.OTHER)
     public AjaxResult listPageProductionStock(Page page, ProcurementPageDto procurementDto) {
-        IPage<ProductModel> result = procurementRecordService.listPageProductionStock(page,procurementDto);
+        IPage<ProductModel> result = procurementRecordService.listPageProductionStock(page, procurementDto);
         return AjaxResult.success(result);
     }
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordOutController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordOutController.java
index 1fb594b..f024bfe 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordOutController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordOutController.java
@@ -7,17 +7,16 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
 import com.ruoyi.procurementrecord.dto.ProcurementRecordOutAdd;
 import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto;
 import com.ruoyi.procurementrecord.dto.ProcurementUpdateDto;
 import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
 import com.ruoyi.procurementrecord.service.ProcurementRecordOutService;
-import io.swagger.annotations.Api;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -25,12 +24,13 @@
  * @date : 2025/7/8 13:30
  */
 @RestController
-@Api(tags = "閲囪喘鍑哄簱")
+@Tag(name = "閲囪喘鍑哄簱")
 @RequestMapping("/stockmanagement")
+@AllArgsConstructor
 public class ProcurementRecordOutController extends BaseController {
 
-    @Autowired
     private ProcurementRecordOutService procurementRecordOutService;
+    private ProcurementRecordOutMapper procurementRecordOutMapper;
 
     @PostMapping("/stockout")
     @Log(title = "閲囪喘鍑哄簱-鍑哄簱绠$悊-鍑哄簱", businessType = BusinessType.INSERT)
@@ -74,6 +74,7 @@
 
     /**
      * 閲囪喘鍑哄簱瀵煎嚭
+     *
      * @param response
      */
     @PostMapping("/export")
@@ -82,10 +83,9 @@
     }
 
 
-    @Autowired
-    public ProcurementRecordOutMapper procurementRecordOutMapper;
     /**
      * 鐢熶骇鍑哄簱瀵煎嚭
+     *
      * @param response
      */
     @PostMapping("/exportOne")
@@ -97,6 +97,7 @@
 
     /**
      * 鑷畾涔夊嚭搴撳鍑�
+     *
      * @param response
      */
     @PostMapping("/exportTwo")
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java
index ebafe40..22882f4 100644
--- a/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java
@@ -15,8 +15,9 @@
 import com.ruoyi.procurementrecord.service.ReturnSaleProductService;
 import com.ruoyi.procurementrecord.service.impl.ReturnSaleProductServiceImpl;
 import com.ruoyi.sales.dto.SalesLedgerDto;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
@@ -28,38 +29,37 @@
  * @date : 2025/9/17 10:34
  */
 @RestController
-@Api(tags = "閿�鍞��璐�")
+@Tag(name = "閿�鍞��璐�")
+@AllArgsConstructor
 @RequestMapping("/returnManagement")
 public class ReturnManagementController extends BaseController {
 
-    @Autowired
     private ReturnManagementService returnManagementService;
-    @Autowired
     private ReturnSaleProductService returnSaleProductService;
 
     @GetMapping("/listPage")
-    @ApiOperation("閿�鍞��璐�-鏌ヨ")
+    @Operation(summary = "閿�鍞��璐�-鏌ヨ")
     public AjaxResult listPage(Page page, ReturnManagementDto returnManagement) {
         IPage<ReturnManagementDto> result = returnManagementService.listPage(page, returnManagement);
         return AjaxResult.success(result);
     }
 
     @PostMapping("/add")
-    @ApiOperation("閿�鍞��璐�-娣诲姞")
+    @Operation(summary = "閿�鍞��璐�-娣诲姞")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody ReturnManagementDto returnManagementDto) {
         return returnManagementService.addReturnManagementDto(returnManagementDto) ? success() : error();
     }
 
     @PostMapping("/update")
-    @ApiOperation("閿�鍞��璐�-淇敼")
+    @Operation(summary = "閿�鍞��璐�-淇敼")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody ReturnManagementDto returnManagementDto) {
         return returnManagementService.updateReturnManagementDto(returnManagementDto) ? success() : error();
     }
 
 
-    @ApiOperation("閿�鍞��璐�-澶勭悊閫�璐у崟")
+    @Operation(summary = "閿�鍞��璐�-澶勭悊閫�璐у崟")
     @GetMapping("/handle")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult handle(Long returnManagementId) {
@@ -68,7 +68,7 @@
 
 
     @DeleteMapping("/del")
-    @ApiOperation("閿�鍞��璐�-鍒犻櫎")
+    @Operation(summary = "閿�鍞��璐�-鍒犻櫎")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult del(@RequestBody List<Long> ids) {
         if (CollectionUtils.isEmpty(ids)) return error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -80,14 +80,14 @@
     }
 
     @GetMapping("/getById")
-    @ApiOperation("閿�鍞��璐�-鏍规嵁id鏌ヨ")
+    @Operation(summary = "閿�鍞��璐�-鏍规嵁id鏌ヨ")
     public AjaxResult getById(Long returnManagementId) {
         ReturnManagementDto returnManagementDto = returnManagementService.getReturnManagementDtoById(returnManagementId);
         return success(returnManagementDto);
     }
 
     @GetMapping("/getByShippingId")
-    @ApiOperation("閿�鍞��璐�-鏍规嵁鍑哄簱鍗曟煡璇㈤攢鍞鍗曚互鍙婁骇鍝佷俊鎭�")
+    @Operation(summary = "閿�鍞��璐�-鏍规嵁鍑哄簱鍗曟煡璇㈤攢鍞鍗曚互鍙婁骇鍝佷俊鎭�")
     public AjaxResult getByShippingId(Long shippingId) {
         SalesLedgerDto salesLedgerDto = returnManagementService.getReturnManagementDtoByShippingIdId(shippingId);
         return success(salesLedgerDto);
diff --git a/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java b/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java
index 1d06eb6..57c2dbb 100644
--- a/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java
+++ b/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java
@@ -3,7 +3,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -65,14 +65,14 @@
     /**
      * 鍏ュ簱鍗曚环
      */
-    @ApiModelProperty(value = "鍏ュ簱鍗曚环")
+    @Schema(description = "鍏ュ簱鍗曚环")
     @Excel(name = "鍏ュ簱鍗曚环")
     private BigDecimal unitPrice;
 
     /**
      * 鍏ュ簱鎬讳环
      */
-    @ApiModelProperty(value = "鍏ュ簱鎬讳环")
+    @Schema(description = "鍏ュ簱鎬讳环")
     @Excel(name = "鍏ュ簱鎬讳环")
     private BigDecimal totalPrice;
 
diff --git a/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java b/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java
index 67f9d03..9173ce3 100644
--- a/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java
+++ b/src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java
@@ -2,7 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -60,14 +60,14 @@
     /**
      * 鍏ュ簱鍗曚环
      */
-    @ApiModelProperty(value = "鍏ュ簱鍗曚环")
+    @Schema(description = "鍏ュ簱鍗曚环")
     @Excel(name = "鍏ュ簱鍗曚环")
     private BigDecimal unitPrice;
 
     /**
      * 鍏ュ簱鎬讳环
      */
-    @ApiModelProperty(value = "鍏ュ簱鎬讳环")
+    @Schema(description = "鍏ュ簱鎬讳环")
     @Excel(name = "鍏ュ簱鎬讳环")
     private BigDecimal totalPrice;
 
diff --git a/src/main/java/com/ruoyi/procurementrecord/dto/ReturnManagementDto.java b/src/main/java/com/ruoyi/procurementrecord/dto/ReturnManagementDto.java
index 74b90c9..b69f241 100644
--- a/src/main/java/com/ruoyi/procurementrecord/dto/ReturnManagementDto.java
+++ b/src/main/java/com/ruoyi/procurementrecord/dto/ReturnManagementDto.java
@@ -7,8 +7,7 @@
 import com.ruoyi.procurementrecord.pojo.ReturnManagement;
 import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -23,26 +22,26 @@
 public class ReturnManagementDto extends ReturnManagement {
 
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
-    @ApiModelProperty(value = "閿�鍞崟鍙�")
+    @Schema(description = "閿�鍞崟鍙�")
     private String salesContractNo;
 
-    @ApiModelProperty(value = "涓氬姟鍛�")
+    @Schema(description = "涓氬姟鍛�")
     private String salesman;
 
 
-    @ApiModelProperty("鍏宠仈鍑哄簱鍗曞彿")
+    @Schema(description = "鍏宠仈鍑哄簱鍗曞彿")
     private String shippingNo;
 
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
+    @Schema(description = "椤圭洰鍚嶇О")
     private String projectName;
 
-    @ApiModelProperty(value = "閿�鍞彴璐d")
+    @Schema(description = "閿�鍞彴璐d")
     private Long salesLedgerId;
 
-    @ApiModelProperty(value = "閿�鍞骇鍝佸璞℃暟缁�")
+    @Schema(description = "閿�鍞骇鍝佸璞℃暟缁�")
     private List<ReturnSaleProductDto> returnSaleProducts;
 
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java b/src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java
index 5107c06..f4e6709 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java
@@ -122,4 +122,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/GasTankWarning.java b/src/main/java/com/ruoyi/procurementrecord/pojo/GasTankWarning.java
index 4f95872..5868d95 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/GasTankWarning.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/GasTankWarning.java
@@ -155,4 +155,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/InboundManagement.java b/src/main/java/com/ruoyi/procurementrecord/pojo/InboundManagement.java
index 56f322e..8936810 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/InboundManagement.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/InboundManagement.java
@@ -2,8 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -17,7 +16,7 @@
  */
 @Data
 @TableName("inbound_management")
-@ApiModel
+@Schema
 public class InboundManagement {
 
     private static final long serialVersionUID = 1L;
@@ -27,47 +26,50 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "璁㈠崟鍙�")
+    @Schema(description = "璁㈠崟鍙�")
     private String orderNo;
 
-    @ApiModelProperty(value = "鍒拌揣鍗曞彿")
+    @Schema(description = "鍒拌揣鍗曞彿")
     private String arrivalNo;
 
-    @ApiModelProperty(value = "渚涘簲鍟嗗悕绉�")
+    @Schema(description = "渚涘簲鍟嗗悕绉�")
     private String supplierName;
 
-    @ApiModelProperty(value = "鍒拌揣鐘舵��")
+    @Schema(description = "鍒拌揣鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "鍒拌揣鏃堕棿")
+    @Schema(description = "鍒拌揣鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date arrivalTime;
 
-    @ApiModelProperty(value = "鍒拌揣鏁伴噺")
+    @Schema(description = "鍒拌揣鏁伴噺")
     private String arrivalQuantity;
 
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementExceptionRecord.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementExceptionRecord.java
index d9e7cc7..9c62016 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementExceptionRecord.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementExceptionRecord.java
@@ -1,5 +1,6 @@
 package com.ruoyi.procurementrecord.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import com.baomidou.mybatisplus.annotation.*;
 import lombok.Builder;
 import lombok.Data;
@@ -51,4 +52,11 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java
index 56892a3..e96412b 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -16,7 +15,7 @@
  */
 @Data
 @TableName("procurement_plan")
-@ApiModel
+@Schema
 public class ProcurementPlan {
 
     private static final long serialVersionUID = 1L;
@@ -26,80 +25,83 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "缂栫爜")
+    @Schema(description = "缂栫爜")
     @Excel(name = "缂栫爜")
     private String code;
 
-    @ApiModelProperty(value = "鍚嶇О")
+    @Schema(description = "鍚嶇О")
     @Excel(name = "鍚嶇О")
     private String planName;
 
-    @ApiModelProperty(value = "鎻忚堪")
+    @Schema(description = "鎻忚堪")
     @Excel(name = "鎻忚堪")
     private String description;
 
-    @ApiModelProperty(value = "鐘舵��")
+    @Schema(description = "鐘舵��")
     @Excel(name = "鐘舵��", readConverterExp = "disabled=绂佺敤,active=鍚敤")
     private String status;
 
-    @ApiModelProperty(value = "鏄惁绯荤粺棰勭疆")
+    @Schema(description = "鏄惁绯荤粺棰勭疆")
     private Boolean isSystemPreset;
 
-    @ApiModelProperty(value = "鑰冭檻鐜版湁搴撳瓨")
+    @Schema(description = "鑰冭檻鐜版湁搴撳瓨")
     private Boolean considerExistingStock;
 
-    @ApiModelProperty(value = "浠撳簱杩愯MRP鐨勬帶鍒�")
+    @Schema(description = "浠撳簱杩愯MRP鐨勬帶鍒�")
     private Boolean warehouseControl;
 
-    @ApiModelProperty(value = "璁$畻鎬婚渶姹�")
+    @Schema(description = "璁$畻鎬婚渶姹�")
     private Boolean calculateTotalDemand;
 
-    @ApiModelProperty(value = "鑰冭檻瀹夊叏搴撳瓨")
+    @Schema(description = "鑰冭檻瀹夊叏搴撳瓨")
     private Boolean considerSafetyStock;
 
-    @ApiModelProperty(value = "鑰冭檻閿佸簱")
+    @Schema(description = "鑰冭檻閿佸簱")
     private Boolean considerLockedStock;
 
-    @ApiModelProperty(value = "涓嶈�冭檻鐗╂枡杈呭姪灞炴��")
+    @Schema(description = "涓嶈�冭檻鐗╂枡杈呭姪灞炴��")
     private Boolean notConsiderMaterialAux;
 
-    @ApiModelProperty(value = "璐熷簱瀛樹綔涓洪渶姹�")
+    @Schema(description = "璐熷簱瀛樹綔涓洪渶姹�")
     private Boolean negativeStockAsDemand;
 
-    @ApiModelProperty(value = "鐗╂枡")
+    @Schema(description = "鐗╂枡")
     private Boolean summaryMaterial;
 
-    @ApiModelProperty(value = "杈呭姪灞炴��")
+    @Schema(description = "杈呭姪灞炴��")
     private Boolean summaryAuxAttributes;
 
-    @ApiModelProperty(value = "闇�姹傛棩鏈�")
+    @Schema(description = "闇�姹傛棩鏈�")
     private Boolean summaryDemandDate;
 
-    @ApiModelProperty(value = "璁$畻鍏紡")
+    @Schema(description = "璁$畻鍏紡")
     @Excel(name = "璁$畻鍏紡")
     private String formula;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "鏈�鍚庤绠楁椂闂�", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java
index 08c9d21..cad1b29 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -17,7 +16,7 @@
  */
 @Data
 @TableName("procurement_price_management")
-@ApiModel
+@Schema
 public class ProcurementPriceManagement {
 
     private static final long serialVersionUID = 1L;
@@ -27,96 +26,99 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鍟嗗搧鍚嶇О")
+    @Schema(description = "鍟嗗搧鍚嶇О")
     @Excel(name = "鍟嗗搧鍚嶇О")
     private String productName;
 
-    @ApiModelProperty(value = "鍟嗗搧缂栫爜")
+    @Schema(description = "鍟嗗搧缂栫爜")
     @Excel(name = "鍟嗗搧缂栫爜")
     private String productCode;
 
-    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     @Excel(name = "瑙勬牸鍨嬪彿")
     private String specification;
 
-    @ApiModelProperty(value = "渚涘簲鍟嗗悕绉�")
+    @Schema(description = "渚涘簲鍟嗗悕绉�")
     @Excel(name = "渚涘簲鍟嗗悕绉�")
     private String supplierName;
 
-    @ApiModelProperty(value = "鍩虹浠锋牸")
+    @Schema(description = "鍩虹浠锋牸")
     @Excel(name = "鍩虹浠锋牸")
     private String basePrice;
 
-    @ApiModelProperty(value = "鐘舵��")
+    @Schema(description = "鐘舵��")
     @TableField(exist = false)
     @Excel(name = "鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "鍗曚綅")
+    @Schema(description = "鍗曚綅")
     private String unit;
 
-    @ApiModelProperty(value = "鎶樻墸绫诲瀷")
+    @Schema(description = "鎶樻墸绫诲瀷")
     @Excel(name = "鎶樻墸绫诲瀷", readConverterExp = "=鏃犳姌鎵�,percentage=鐧惧垎姣旀姌鎵�,fixed=鍥哄畾閲戦")
     private String discountType;
 
-    @ApiModelProperty(value = "鎶樻墸鍊�")
+    @Schema(description = "鎶樻墸鍊�")
     @Excel(name = "鎶樻墸鍊�")
     private String discountValue;
 
-    @ApiModelProperty(value = "鎶樻墸鏈夋晥鏈�")
+    @Schema(description = "鎶樻墸鏈夋晥鏈�")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date discountEndTime;
 
-    @ApiModelProperty(value = "鏈�浣庝环鏍�")
+    @Schema(description = "鏈�浣庝环鏍�")
     @Excel(name = "鏈�浣庝环鏍�")
     private String minPrice;
 
-    @ApiModelProperty(value = "鏈�楂樹环鏍�")
+    @Schema(description = "鏈�楂樹环鏍�")
     @Excel(name = "鏈�楂樹环鏍�")
     private String maxPrice;
 
-    @ApiModelProperty(value = "棰勮闃堝��(%)")
+    @Schema(description = "棰勮闃堝��(%)")
     private String warningThreshold;
 
-    @ApiModelProperty(value = "鐢熸晥鏃堕棿")
+    @Schema(description = "鐢熸晥鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鐢熸晥鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
     private Date effectiveTime;
 
-    @ApiModelProperty(value = "澶辨晥鏃堕棿")
+    @Schema(description = "澶辨晥鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date expireTime;
 
-    @ApiModelProperty(value = "璋冧环鍘熷洜")
+    @Schema(description = "璋冧环鍘熷洜")
     private String reason;
 
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "鏇存柊鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordOut.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordOut.java
index dfa9756..e6f0798 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordOut.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordOut.java
@@ -92,4 +92,7 @@
      */
     private Long productModelId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java
index 29e77c4..631e703 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java
@@ -102,4 +102,7 @@
     private Long productModelId;
 
     private Long qualityInspectId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnManagement.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnManagement.java
index bae0caa..f5d8c79 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnManagement.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnManagement.java
@@ -2,8 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -17,7 +16,7 @@
  */
 @Data
 @TableName("return_management")
-@ApiModel
+@Schema
 public class ReturnManagement {
 
     private static final long serialVersionUID = 1L;
@@ -27,48 +26,55 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "閫�璐у崟鍙�")
+    @Schema(description = "閫�璐у崟鍙�")
     private String returnNo;
 
-    @ApiModelProperty("瀹㈡埛id")
+    @Schema(description = "瀹㈡埛id")
     private Long customerId;
 
-    @ApiModelProperty("鍏宠仈鍑哄簱鍗曞彿Id")
+    @Schema(description = "鍏宠仈鍑哄簱鍗曞彿Id")
     private Long shippingId;
 
-    @ApiModelProperty("椤圭洰id")
+    @Schema(description = "椤圭洰id")
     private Long projectId;
 
-    @ApiModelProperty("椤圭洰闃舵")
+    @Schema(description = "椤圭洰闃舵")
     private String projectStage;
 
-    @ApiModelProperty("鍒跺崟浜�")
+    @Schema(description = "鍒跺崟浜�")
     private String maker;
 
-    @ApiModelProperty("閫�璐у師鍥�")
+    @Schema(description = "閫�璐у師鍥�")
     private String returnReason;
 
-    @ApiModelProperty("閫�娆炬�婚")
+    @Schema(description = "閫�娆炬�婚")
     private BigDecimal refundAmount;
 
-    @ApiModelProperty("鍒跺崟鏃堕棿")
+    @Schema(description = "鍒跺崟鏃堕棿")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime makeTime;
 
-    @ApiModelProperty("缁撶畻浜�")
+    @Schema(description = "缁撶畻浜�")
     private String settler;
 
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     private Integer status;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime updateTime;
 
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnSaleProduct.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnSaleProduct.java
index 9a47197..b7b0efa 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnSaleProduct.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ReturnSaleProduct.java
@@ -1,13 +1,13 @@
 package com.ruoyi.procurementrecord.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.math.BigDecimal;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -22,39 +22,46 @@
 @Getter
 @Setter
 @TableName("return_sale_product")
-@ApiModel(value = "ReturnSaleProduct瀵硅薄", description = "閫�璐т骇鍝佽〃")
+@Schema(name = "ReturnSaleProduct瀵硅薄", description = "閫�璐т骇鍝佽〃")
 public class ReturnSaleProduct implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("浜у搧瑙勬牸id")
+    @Schema(description = "浜у搧瑙勬牸id")
     private Long productModelId;
 
-    @ApiModelProperty("涓婚敭id")
+    @Schema(description = "涓婚敭id")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("閫�璐у崟id")
+    @Schema(description = "閫�璐у崟id")
     private Long returnManagementId;
 
-    @ApiModelProperty("閫�璐т骇鍝乮d")
-    private Long returnSaleLedgerProductId;
+    @Schema(description = "閫�璐т骇鍝乮d")
+    private Long returnsalesLedgerProductId;
 
-    @ApiModelProperty("閫�璐т骇鍝佹暟閲�")
+    @Schema(description = "閫�璐т骇鍝佹暟閲�")
     private BigDecimal num;
 
-    @ApiModelProperty("閫�璐т骇鍝佸崟浠�")
+    @Schema(description = "閫�璐т骇鍝佸崟浠�")
     private BigDecimal price;
 
-    @ApiModelProperty("閫�璐т骇鍝侀噾棰�")
+    @Schema(description = "閫�璐т骇鍝侀噾棰�")
     private BigDecimal amount;
 
-    @ApiModelProperty("閫�璐х姸鎬� 0 鏈��鍥� 1宸查��璐�")
+    @Schema(description = "閫�璐х姸鎬� 0 鏈��鍥� 1宸查��璐�")
     private Integer status;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("鏄惁鏈夎川閲忛棶棰�(1-鏄� 2-鍚�)")
+    @Schema(description = "鏄惁鏈夎川閲忛棶棰�(1-鏄� 2-鍚�)")
     private Integer isQuality;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/GasTankWarningService.java b/src/main/java/com/ruoyi/procurementrecord/service/GasTankWarningService.java
index 912fb3c..bedac85 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/GasTankWarningService.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/GasTankWarningService.java
@@ -5,7 +5,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.procurementrecord.pojo.GasTankWarning;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 public interface GasTankWarningService extends IService<GasTankWarning> {
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java
index e96dbe6..5e778fe 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java
@@ -5,7 +5,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.procurementrecord.pojo.ProcurementPlan;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * @author :yys
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java
index fc26ab6..927d977 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java
@@ -5,7 +5,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.procurementrecord.pojo.ProcurementPriceManagement;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * @author :yys
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordOutService.java b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordOutService.java
index 31fc05e..202ce88 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordOutService.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordOutService.java
@@ -8,7 +8,7 @@
 import com.ruoyi.procurementrecord.dto.ProcurementUpdateDto;
 import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * @author :yys
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java
index 6bd187c..da23205 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java
@@ -9,7 +9,7 @@
 import com.ruoyi.procurementrecord.pojo.CustomStorage;
 import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/GasTankWarningServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/GasTankWarningServiceImpl.java
index 772869b..74e88ec 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/GasTankWarningServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/GasTankWarningServiceImpl.java
@@ -4,34 +4,33 @@
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
 import com.ruoyi.procurementrecord.mapper.GasTankWarningMapper;
 import com.ruoyi.procurementrecord.pojo.GasTankWarning;
 import com.ruoyi.procurementrecord.service.GasTankWarningService;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.List;
 
 @Service
+@RequiredArgsConstructor
 public class GasTankWarningServiceImpl extends ServiceImpl<GasTankWarningMapper, GasTankWarning> implements GasTankWarningService {
-    @Autowired
-    private GasTankWarningMapper gasTankWarningMapper;
+    private final GasTankWarningMapper gasTankWarningMapper;
+
     @Override
     public IPage listPage(Page page, GasTankWarning gasTankWarning) {
-        return gasTankWarningMapper.listPage(page,gasTankWarning);
+        return gasTankWarningMapper.listPage(page, gasTankWarning);
     }
 
     @Override
     public void export(HttpServletResponse response, List<Long> ids) {
         List<GasTankWarning> list = new ArrayList<>();
-        if(CollectionUtils.isEmpty(ids)){
+        if (CollectionUtils.isEmpty(ids)) {
             list = gasTankWarningMapper.selectList(null);
-        }else {
+        } else {
             list = gasTankWarningMapper.selectBatchIds(ids);
         }
         ExcelUtil<GasTankWarning> util = new ExcelUtil<>(GasTankWarning.class);
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/InboundManagementServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/InboundManagementServiceImpl.java
index 5e8fa72..bce3eb5 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/InboundManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/InboundManagementServiceImpl.java
@@ -6,8 +6,8 @@
 import com.ruoyi.procurementrecord.mapper.InboundManagementMapper;
 import com.ruoyi.procurementrecord.pojo.InboundManagement;
 import com.ruoyi.procurementrecord.service.InboundManagementService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -16,10 +16,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class InboundManagementServiceImpl extends ServiceImpl<InboundManagementMapper, InboundManagement> implements InboundManagementService {
 
-    @Autowired
-    private InboundManagementMapper inboundManagementMapper;
+    private final InboundManagementMapper inboundManagementMapper;
 
     @Override
     public IPage<InboundManagement> listPage(Page page, InboundManagement inboundManagement) {
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java
index 81216db..6a7f07d 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java
@@ -6,13 +6,12 @@
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.procurementrecord.mapper.ProcurementPlanMapper;
 import com.ruoyi.procurementrecord.pojo.ProcurementPlan;
-import com.ruoyi.procurementrecord.pojo.ProcurementPriceManagement;
 import com.ruoyi.procurementrecord.service.ProcurementPlanService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -21,10 +20,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class ProcurementPlanServiceImpl extends ServiceImpl<ProcurementPlanMapper, ProcurementPlan> implements ProcurementPlanService {
 
-    @Autowired
-    private ProcurementPlanMapper procurementPlanMapper;
+    private final ProcurementPlanMapper procurementPlanMapper;
 
     @Override
     public IPage<ProcurementPlan> listPage(Page page, ProcurementPlan procurementPlan) {
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java
index e90a7a2..1acc9bf 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java
@@ -3,17 +3,15 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.excel.ExcelUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
 import com.ruoyi.procurementrecord.mapper.ProcurementPriceManagementMapper;
 import com.ruoyi.procurementrecord.pojo.ProcurementPriceManagement;
 import com.ruoyi.procurementrecord.service.ProcurementPriceManagementService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -22,11 +20,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class ProcurementPriceManagementServiceImpl extends ServiceImpl<ProcurementPriceManagementMapper, ProcurementPriceManagement> implements ProcurementPriceManagementService {
 
-
-    @Autowired
-    private ProcurementPriceManagementMapper procurementPriceManagementMapper;
+    private final ProcurementPriceManagementMapper procurementPriceManagementMapper;
 
 
     @Override
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java
index 1255afd..8b6b33d 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java
@@ -19,7 +19,7 @@
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java
index 19509a3..8a3c4ba 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java
@@ -31,7 +31,7 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
@@ -535,7 +535,7 @@
             Long aLong = customStorageMapper.selectCount(null);
             item.setInboundBatches(aLong.equals(0L) ? "绗�1鎵规(鑷畾涔夊叆搴�)" : "绗�"+ (aLong + 1) + "鎵规(鑷畾涔夊叆搴�)" );
             item.setCreateBy(loginUser.getNickName());
-            item.setCode(OrderUtils.countTodayByCreateTime(customStorageMapper, ""));
+            item.setCode(OrderUtils.countTodayByCreateTime(customStorageMapper, "", "code"));
             customStorageMapper.insert(item);
         });
         return AjaxResult.success("鑷畾涔夊叆搴撴垚鍔�");
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java
index d2b6142..e9b2615 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java
@@ -1,13 +1,11 @@
 package com.ruoyi.procurementrecord.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.account.dto.SalesRefundAmountOrderDto;
 import com.ruoyi.account.mapper.AccountExpenseMapper;
 import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.SalesRefundAmountOrder;
 import com.ruoyi.account.service.SalesRefundAmountOrderService;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
@@ -27,9 +25,9 @@
 import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.ShippingInfoService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
@@ -44,25 +42,16 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class ReturnManagementServiceImpl extends ServiceImpl<ReturnManagementMapper, ReturnManagement> implements ReturnManagementService {
 
-    @Autowired
-    private ReturnManagementMapper returnManagementMapper;
-
-    @Autowired
-    private ReturnSaleProductService returnSaleProductService;
-    @Autowired
-    private ShippingInfoService shippingInfoService;
-    @Autowired
-    private SalesLedgerMapper salesLedgerMapper;
-    @Autowired
-    private SalesRefundAmountOrderService salesRefundAmountOrderService;
-
-    @Autowired
-    private StockUtils stockUtils;
-
-    @Autowired
-    private AccountExpenseMapper accountExpenseMapper;
+    private final ReturnManagementMapper returnManagementMapper;
+    private final ReturnSaleProductService returnSaleProductService;
+    private final ShippingInfoService shippingInfoService;
+    private final SalesLedgerMapper salesLedgerMapper;
+    private final SalesRefundAmountOrderService salesRefundAmountOrderService;
+    private final StockUtils stockUtils;
+    private final AccountExpenseMapper accountExpenseMapper;
 
     @Override
     public IPage<ReturnManagementDto> listPage(Page page, ReturnManagementDto returnManagement) {
@@ -72,7 +61,7 @@
 
     @Override
     public boolean addReturnManagementDto(ReturnManagementDto returnManagementDto) {
-        String rt = OrderUtils.countTodayByCreateTime(returnManagementMapper, "RT");
+        String rt = OrderUtils.countTodayByCreateTime(returnManagementMapper, "RT","return_no");
         returnManagementDto.setReturnNo(rt);
         save(returnManagementDto);
         for (ReturnSaleProduct returnSaleProduct : returnManagementDto.getReturnSaleProducts()) {
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnSaleProductServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnSaleProductServiceImpl.java
index a4281d0..4809674 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnSaleProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnSaleProductServiceImpl.java
@@ -1,14 +1,13 @@
 package com.ruoyi.procurementrecord.service.impl;
 
-import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto;
-import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct;
-import com.ruoyi.procurementrecord.mapper.ReturnSaleProductMapper;
-import com.ruoyi.procurementrecord.service.ReturnSaleProductService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto;
+import com.ruoyi.procurementrecord.mapper.ReturnSaleProductMapper;
+import com.ruoyi.procurementrecord.pojo.ReturnSaleProduct;
+import com.ruoyi.procurementrecord.service.ReturnSaleProductService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -20,10 +19,11 @@
  * @since 2026-03-05 03:57:42
  */
 @Service
+@RequiredArgsConstructor
 public class ReturnSaleProductServiceImpl extends ServiceImpl<ReturnSaleProductMapper, ReturnSaleProduct> implements ReturnSaleProductService {
 
-    @Autowired
-    private ReturnSaleProductMapper returnSaleProductMapper;
+    private final ReturnSaleProductMapper returnSaleProductMapper;
+
     @Override
     public List<ReturnSaleProductDto> listReturnSaleProductDto(Long returnManagementId) {
 
diff --git a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
index 819ce65..f561b49 100644
--- a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
+++ b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -4,24 +4,20 @@
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
 import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
-import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.dto.StockUninventoryDto;
+import com.ruoyi.stock.mapper.StockInventoryMapper;
 import com.ruoyi.stock.pojo.StockInRecord;
 import com.ruoyi.stock.pojo.StockOutRecord;
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.stock.service.StockInventoryService;
 import com.ruoyi.stock.service.StockOutRecordService;
 import com.ruoyi.stock.service.StockUninventoryService;
-import com.ruoyi.stock.service.impl.StockInRecordServiceImpl;
-import com.ruoyi.stock.service.impl.StockOutRecordServiceImpl;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Component;
 
 import java.math.BigDecimal;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
 
 @Component
 @RequiredArgsConstructor
@@ -32,31 +28,34 @@
     private final StockInventoryService stockInventoryService;
     private final StockInRecordService stockInRecordService;
     private final StockOutRecordService stockOutRecordService;
+    private final StockInventoryMapper stockInventoryMapper;
 
     /**
      * 涓嶅悎鏍煎叆搴�
+     *
      * @param productModelId
      * @param quantity
      * @param recordType
      * @param recordId
      */
-    public void addUnStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void addUnStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
         StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
         stockUninventoryDto.setRecordId(recordId);
         stockUninventoryDto.setRecordType(String.valueOf(recordType));
         stockUninventoryDto.setQualitity(quantity);
         stockUninventoryDto.setProductModelId(productModelId);
-        stockUninventoryService.addStockUninventory(stockUninventoryDto);
+        stockUninventoryService.addStockInRecordOnly(stockUninventoryDto);
     }
 
     /**
      * 涓嶅悎鏍煎嚭搴�
+     *
      * @param productModelId
      * @param quantity
      * @param recordType
      * @param recordId
      */
-    public void subtractUnStock(Long productModelId, BigDecimal quantity, Integer recordType,Long recordId) {
+    public void subtractUnStock(Long productModelId, BigDecimal quantity, Integer recordType, Long recordId) {
         StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
         stockUninventoryDto.setRecordId(recordId);
         stockUninventoryDto.setRecordType(String.valueOf(recordType));
@@ -72,28 +71,39 @@
      * @param recordType
      * @param recordId
      */
-    public void addStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void addStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
         StockInventoryDto stockInventoryDto = new StockInventoryDto();
         stockInventoryDto.setRecordId(recordId);
         stockInventoryDto.setRecordType(String.valueOf(recordType));
         stockInventoryDto.setQualitity(quantity);
         stockInventoryDto.setProductModelId(productModelId);
-        stockInventoryService.addstockInventory(stockInventoryDto);
+        stockInventoryService.addStockInRecordOnly(stockInventoryDto);
     }
 
     /**
      * 鍚堟牸鍑哄簱
+     *
      * @param productModelId
      * @param quantity
      * @param recordType
      * @param recordId
      */
-    public void substractStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
+    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
         StockInventoryDto stockInventoryDto = new StockInventoryDto();
         stockInventoryDto.setRecordId(recordId);
         stockInventoryDto.setRecordType(String.valueOf(recordType));
         stockInventoryDto.setQualitity(quantity);
         stockInventoryDto.setProductModelId(productModelId);
+        stockInventoryService.subtractStockInventory(stockInventoryDto);
+    }
+
+    public void substractStock(Long productModelId, BigDecimal quantity, String recordType, Long recordId, String batchNo) {
+        StockInventoryDto stockInventoryDto = new StockInventoryDto();
+        stockInventoryDto.setRecordId(recordId);
+        stockInventoryDto.setRecordType(String.valueOf(recordType));
+        stockInventoryDto.setQualitity(quantity);
+        stockInventoryDto.setProductModelId(productModelId);
+        stockInventoryDto.setBatchNo(batchNo);
         stockInventoryService.subtractStockInventory(stockInventoryDto);
     }
 
@@ -104,14 +114,29 @@
                 .eq(StockInRecord::getRecordType, recordType));
         if (ObjectUtils.isNotEmpty(one)) {
             stockInRecordService.batchDelete(Collections.singletonList(one.getId()));
+            //灏嗗簱瀛樺噺鍥炴潵
+            StockInventoryDto stockInventoryDto = new StockInventoryDto();
+            stockInventoryDto.setRecordId(recordId);
+            stockInventoryDto.setRecordType(recordType);
+            stockInventoryDto.setQualitity(one.getStockInNum());
+            stockInventoryMapper.updateSubtractStockInventory((stockInventoryDto));
         }
+
     }
+
     public void deleteStockOutRecord(Long recordId, String recordType) {
         StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>()
                 .lambda().eq(StockOutRecord::getRecordId, recordId)
                 .eq(StockOutRecord::getRecordType, recordType));
         if (ObjectUtils.isNotEmpty(one)) {
             stockOutRecordService.batchDelete(Collections.singletonList(one.getId()));
+            //灏嗗簱瀛樺姞鍥炴潵
+            StockInventoryDto stockInventoryDto = new StockInventoryDto();
+            stockInventoryDto.setRecordId(recordId);
+            stockInventoryDto.setRecordType(recordType);
+            stockInventoryDto.setQualitity(one.getStockOutNum());
+            stockInventoryMapper.updateAddStockInventory((stockInventoryDto));
         }
+
     }
 }
diff --git a/src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java b/src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java
new file mode 100644
index 0000000..11393f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/BomImportDto.java
@@ -0,0 +1,38 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class BomImportDto {
+    @Schema(description = "鐖朵骇鍝佸悕绉�")
+    @Excel(name = "鐖朵骇鍝佸悕绉�")
+    private String parentName;
+
+    @Schema(description = "鐖朵骇鍝佽鏍�")
+    @Excel(name = "鐖朵骇鍝佽鏍�")
+    private String parentSpec;
+
+    @Schema(description = "瀛愪骇鍝佸悕绉�")
+    @Excel(name = "瀛愪骇鍝佸悕绉�")
+    private String childName;
+
+    @Schema(description = "瀛愪骇鍝佽鏍�")
+    @Excel(name = "瀛愪骇鍝佽鏍�")
+    private String childSpec;
+
+    @Schema(description = "鍗曚綅鐢ㄩ噺")
+    @Excel(name = "鍗曚綅鐢ㄩ噺")
+    private BigDecimal unitQty;
+
+    @Schema(description = "宸ュ簭")
+    @Excel(name = "宸ュ簭")
+    private String process;
+
+    @Schema(description = "澶囨敞")
+    @Excel(name = "澶囨敞")
+    private String remark;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java
new file mode 100644
index 0000000..85f28d1
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductStructureDto.java
@@ -0,0 +1,33 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class ProductStructureDto {
+    @Schema(description = "涓婚敭ID")
+    private Long id;
+    @Schema(description = "BOM涓婚敭ID")
+    private Long bomId;
+    @Schema(description = "鐖剁骇ID")
+    private Long parentId;
+    @Schema(description = "浜у搧鍨嬪彿ID")
+    private Long productModelId;
+    @Schema(description = "鍗曚綅鐢ㄩ噺")
+    private BigDecimal unitQuantity;
+    @Schema(description = "鍗曚綅")
+    private String unit;
+    @Schema(description = "宸ュ簭ID")
+    private Long processId;
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String processName;
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+    @Schema(description = "瀛愯妭鐐�")
+    private List<ProductStructureDto> children;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java
new file mode 100644
index 0000000..91b97ef
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionAccountDto.java
@@ -0,0 +1,63 @@
+package com.ruoyi.production.bean.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.production.pojo.ProductionAccount;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "ProductionAccountDto", description = "production account query dto")
+public class ProductionAccountDto extends ProductionAccount {
+
+    @Schema(description = "sales contract no")
+    private String salesContractNo;
+
+    @Schema(description = "customer contract no")
+    private String customerContractNo;
+
+    @Schema(description = "project name")
+    private String projectName;
+
+    @Schema(description = "customer name")
+    private String customerName;
+
+    @Schema(description = "product category")
+    private String productCategory;
+
+    @Schema(description = "specification model")
+    private String specificationModel;
+
+    @Schema(description = "scheduling user id")
+    private Long schedulingUserId;
+
+    @Schema(description = "scheduling user name")
+    private String schedulingUserName;
+
+    @Schema(description = "process")
+    private String process;
+
+    @Schema(description = "date type(day/month)")
+    private String dateType;
+
+    @Schema(description = "day query date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate entryDate;
+
+    @Schema(description = "date range")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate[] dateRange;
+
+    @Schema(description = "start date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate entryDateStart;
+
+    @Schema(description = "end date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate entryDateEnd;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java
new file mode 100644
index 0000000..c898c56
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionBomStructureDto.java
@@ -0,0 +1,31 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.production.pojo.ProductionBomStructure;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ProductionBomStructureDto extends ProductionBomStructure {
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "浜у搧ID")
+    private Long productId;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    private String tempId;
+
+    private String parentTempId;
+
+    private List<ProductionBomStructureDto> children;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
new file mode 100644
index 0000000..965cbf3
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
@@ -0,0 +1,47 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ProductionOperationTaskDto extends ProductionOperationTask {
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String processName;
+
+    @Schema(description = "鐢熶骇璁㈠崟鍙�")
+    private String productOrderNpsNo;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鎶ュ簾鏁伴噺")
+    private BigDecimal scrapQty;
+
+    @Schema(description = "瀹屾垚杩涘害")
+    private BigDecimal completionStatus;
+
+    @Schema(description = "璁㈠崟鍙�")
+    private String npsNo;
+
+    @Schema(description = "寮�濮嬫棩鏈�")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate startDate;
+
+    @Schema(description = "缁撴潫鏃ユ湡")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate endDate;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderDto.java
new file mode 100644
index 0000000..4b0a711
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderDto.java
@@ -0,0 +1,17 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.production.pojo.ProductionOrder;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "ProductionOrderDto", description = "鐢熶骇璁㈠崟鏌ヨ瀵硅薄")
+public class ProductionOrderDto extends ProductionOrder {
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java
new file mode 100644
index 0000000..1b226ad
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickDto.java
@@ -0,0 +1,48 @@
+package com.ruoyi.production.bean.dto;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import com.ruoyi.production.pojo.ProductionOrderPick;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@Schema(name = "ProductionOrderPickDto", description = "鐢熶骇璁㈠崟棰嗘枡淇濆瓨鍙傛暟")
+public class ProductionOrderPickDto extends ProductionOrderPick {
+
+    @Schema(description = "鐢熶骇璁㈠崟ID")
+    private Long productionOrderId;
+
+    @Schema(description = "鐢熶骇宸ュ崟ID")
+    private Long productionOperationTaskId;
+
+    @Schema(description = "鎵瑰彿")
+    private String batchNo;
+
+    @Schema(description = "鎵瑰彿鍒楄〃")
+    private List<String> batchNoList;
+
+    @Schema(description = "棰嗘枡鏁伴噺")
+    private BigDecimal pickQuantity;
+
+    @Schema(description = "棰嗘枡绫诲瀷锛�1姝e父棰嗘枡锛�2琛ユ枡")
+    private Byte pickType;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "琛ユ枡鍘熷洜")
+    private String feedingReason;
+
+    @Schema(description = "鏈琛ユ枡鏁伴噺")
+    private BigDecimal feedingQuantity;
+
+    @Schema(description = "棰嗘枡鏄庣粏鍒楄〃")
+    @JsonAlias({"dto", "productionOrderPickDto"})
+    private List<ProductionOrderPickDto> pickList;
+
+    @Schema(description = "闇�瑕佸垹闄ょ殑棰嗘枡ID鍒楄〃")
+    private List<Long> deletePickIds;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java
new file mode 100644
index 0000000..6954c4a
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderPickRecordDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.production.pojo.ProductionOrderPickRecord;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Schema(name = "ProductionOrderPickRecordDto", description = "棰嗘枡璁板綍鏌ヨ鍙傛暟")
+public class ProductionOrderPickRecordDto extends ProductionOrderPickRecord {
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamDto.java
new file mode 100644
index 0000000..a4e29a0
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamDto.java
@@ -0,0 +1,10 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ProductionOrderRoutingOperationParamDto extends ProductionOrderRoutingOperationParam {
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamSyncDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamSyncDto.java
new file mode 100644
index 0000000..0afb65e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionOrderRoutingOperationParamSyncDto.java
@@ -0,0 +1,14 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class ProductionOrderRoutingOperationParamSyncDto {
+
+    @Schema(description = "鐢熶骇璁㈠崟宸ュ簭鍙傛暟ID")
+    private Long productionOrderRoutingOperationId;
+
+    @Schema(description = "鏄惁鏇挎崲宸叉湁鍙傛暟")
+    private Boolean replaceExisting;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanDto.java
new file mode 100644
index 0000000..60ab542
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanDto.java
@@ -0,0 +1,55 @@
+package com.ruoyi.production.bean.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.production.pojo.ProductionPlan;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ProductionPlanDto extends ProductionPlan {
+
+    @Schema(description = "浜у搧鍚嶇О")
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "浜у搧瑙勬牸")
+    @Excel(name = "浜у搧瑙勬牸")
+    private String model;
+
+    @Schema(description = "浜у搧鍗曚綅")
+    @Excel(name = "浜у搧鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鐢熶骇璁″垝id闆嗗悎")
+    private List<Long> ids;
+
+    @Schema(description = "涓嬪彂鏁伴噺")
+    private BigDecimal totalAssignedQuantity;
+
+    @Schema(description = "璁″垝瀹屾垚鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate planCompleteTime;
+
+    @Schema(description = "浜у搧ID")
+    private Long productId;
+
+    @Schema(description = "绛涢�夊紑濮嬫棩鏈�")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate requiredDateStart;
+
+    @Schema(description = "绛涢�夌粨鏉熸棩鏈�")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate requiredDateEnd;
+
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanImportDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanImportDto.java
new file mode 100644
index 0000000..5dd5160
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanImportDto.java
@@ -0,0 +1,81 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+/**
+ * <br>
+ * 閿�鍞敓浜ч渶姹� Excel瀵煎叆瀵煎嚭DTO
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/11 11:28
+ */
+@Data
+@Schema(name = "閿�鍞敓浜ч渶姹� Excel瀵煎叆瀵煎嚭DTO")
+public class ProductionPlanImportDto {
+
+    @Schema(description = "涓荤敓浜ц鍒掑彿")
+    @Excel(name = "涓荤敓浜ц鍒掑彿")
+    private String mpsNo;
+
+    @Schema(description = "闇�姹傛棩鏈�")
+    @Excel(name = "闇�姹傛棩鏈�")
+    private LocalDate requiredDate;
+
+    @Schema(description = "澶囨敞")
+    @Excel(name = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "闇�姹傛暟閲�")
+    @Excel(name = "闇�姹傛暟閲�")
+    private BigDecimal qtyRequired;
+
+    @Schema(description = "鏉ユ簮 閿�鍞�/鍐呴儴")
+    @Excel(name = "鏉ユ簮 閿�鍞�/鍐呴儴")
+    private String source;
+
+    @Schema(description = "鎵胯鏃ユ湡")
+    @Excel(name = "鎵胯鏃ユ湡")
+    private LocalDate promisedDeliveryDate;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    @Excel(name = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    @Excel(name = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    @Excel(name = "鍗曚綅")
+    private String unit;
+
+
+    /**
+     * 鍒涘缓浜�
+     */
+    @Schema(description = "鍒涘缓浜�")
+    @Excel(name = "鍒涘缓浜�", type = Excel.Type.EXPORT)
+    private String creatorName;
+
+    /**
+     * 淇敼浜�
+     */
+    @Schema(description = "淇敼浜�")
+    @Excel(name = "淇敼浜�", type = Excel.Type.EXPORT)
+    private String modifierName;
+
+
+    /**
+     * 宸蹭笅鍙戞暟閲�
+     */
+    @Schema(description = "宸蹭笅鍙戞暟閲�")
+    @Excel(name = "宸蹭笅鍙戞暟閲�", type = Excel.Type.EXPORT)
+    private BigDecimal assignedQuantity;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanSummaryDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanSummaryDto.java
new file mode 100644
index 0000000..8f7ea6e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionPlanSummaryDto.java
@@ -0,0 +1,71 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * <br>
+ * 閿�鍞敓浜ч渶姹� - 浜у搧绫诲瀷姹囨�籇TO
+ * </br>
+ */
+@Data
+@Schema(name = "鐢熶骇闇�姹備骇鍝佹眹鎬�")
+public class ProductionPlanSummaryDto {
+
+    /**
+     * 鐗╂枡缂栫爜
+     */
+    @Schema(description = "鐗╂枡缂栫爜")
+    private String materialCode;
+
+    /**
+     * 浜у搧鍚嶇О
+     */
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    /**
+     * 浜у搧瑙勬牸
+     */
+    @Schema(description = "浜у搧瑙勬牸")
+    private String model;
+
+    /**
+     * 浜у搧闀垮害
+     */
+    @Schema(description = "浜у搧闀垮害")
+    private Integer length;
+
+    /**
+     * 浜у搧瀹藉害
+     */
+    @Schema(description = "浜у搧瀹藉害")
+    private Integer width;
+
+    /**
+     * 浜у搧楂樺害
+     */
+    @Schema(description = "浜у搧楂樺害")
+    private Integer height;
+
+    /**
+     * 姹囨�诲潡鏁�
+     */
+    @Schema(description = "姹囨�诲潡鏁�")
+    private Integer quantity;
+
+    /**
+     * 姹囨�绘柟鏁�
+     */
+    @Schema(description = "姹囨�绘柟鏁�")
+    private BigDecimal volume;
+
+    /**
+     * 鍩烘湰鍗曚綅
+     */
+    @Schema(description = "鍩烘湰鍗曚綅")
+    private String unit;
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductInputDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductInputDto.java
new file mode 100644
index 0000000..0a2a139
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductInputDto.java
@@ -0,0 +1,44 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+public class ProductionProductInputDto {
+    @Schema(description = "涓婚敭ID")
+    private Long id;
+    @Schema(description = "浜у搧涓昏〃ID")
+    private Long productMainId;
+    @Schema(description = "鐢熶骇浜у搧涓昏〃ID")
+    private Long productionProductMainId;
+    @Schema(description = "浜у搧鍨嬪彿ID")
+    private Long productModelId;
+    @Schema(description = "鏁伴噺")
+    private BigDecimal quantity;
+    @Schema(description = "鎶曞叆鏁伴噺")
+    private BigDecimal inputQuantity;
+    @Schema(description = "鍒涘缓鏃堕棿")
+    private LocalDateTime createTime;
+    @Schema(description = "鏇存柊鏃堕棿")
+    private LocalDateTime updateTime;
+    @Schema(description = "绉熸埛ID")
+    private Long tenantId;
+    @Schema(description = "鍒涘缓浜�")
+    private Integer createUser;
+    @Schema(description = "鏇存柊浜�")
+    private Integer updateUser;
+    @Schema(description = "閮ㄩ棬ID")
+    private Long deptId;
+
+    @Schema(description = "浜у搧缂栧彿")
+    private String productNo;
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+    @Schema(description = "鍗曚綅")
+    private String unit;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
new file mode 100644
index 0000000..9fc8d86
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductMainDto.java
@@ -0,0 +1,74 @@
+package com.ruoyi.production.bean.dto;
+
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import com.ruoyi.production.pojo.ProductionProductMain;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "ProductionProductMainDto", description = "production report query dto")
+public class ProductionProductMainDto extends ProductionProductMain {
+
+    @Schema(description = "product process route item id")
+    private Long productProcessRouteItemId;
+
+    @Schema(description = "production report id")
+    private Long productMainId;
+
+    @Schema(description = "tenant id")
+    private Long tenantId;
+
+    @Schema(description = "work order no")
+    private String workOrderNo;
+
+    @Schema(description = "work order status")
+    private String workOrderStatus;
+
+    @Schema(description = "nick name")
+    private String nickName;
+
+    @Schema(description = "quantity")
+    private BigDecimal quantity;
+
+    @Schema(description = "scrap quantity")
+    private BigDecimal scrapQty;
+
+    @Schema(description = "product name")
+    private String productName;
+
+    @Schema(description = "product model name")
+    private String productModelName;
+
+    @Schema(description = "unit")
+    private String unit;
+
+    @Schema(description = "sales contract no")
+    private String salesContractNo;
+
+    @Schema(description = "scheduling date")
+    private LocalDate schedulingDate;
+
+    @Schema(description = "scheduling user name")
+    private String schedulingUserName;
+
+    @Schema(description = "customer name")
+    private String customerName;
+
+    @Schema(description = "process")
+    private String process;
+
+    @Schema(description = "salary quota")
+    private BigDecimal workHours;
+
+    @Schema(description = "wages")
+    private BigDecimal wages;
+
+    @Schema(description = "operation param list")
+    private List<ProductionOrderRoutingOperationParam> productionOperationParamList;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/ProductionProductOutputDto.java b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductOutputDto.java
new file mode 100644
index 0000000..73acbe4
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/ProductionProductOutputDto.java
@@ -0,0 +1,40 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+public class ProductionProductOutputDto {
+    @Schema(description = "涓婚敭ID")
+    private Long id;
+    @Schema(description = "浜у搧涓昏〃ID")
+    private Long productMainId;
+    @Schema(description = "鐢熶骇浜у搧涓昏〃ID")
+    private Long productionProductMainId;
+    @Schema(description = "浜у搧鍨嬪彿ID")
+    private Long productModelId;
+    @Schema(description = "鏁伴噺")
+    private BigDecimal quantity;
+    @Schema(description = "鎶ュ簾鏁伴噺")
+    private BigDecimal scrapQty;
+    @Schema(description = "鍒涘缓鏃堕棿")
+    private LocalDateTime createTime;
+    @Schema(description = "鏇存柊鏃堕棿")
+    private LocalDateTime updateTime;
+    @Schema(description = "绉熸埛ID")
+    private Long tenantId;
+    @Schema(description = "鍒涘缓浜�")
+    private Integer createUser;
+    @Schema(description = "鏇存柊浜�")
+    private Integer updateUser;
+    @Schema(description = "閮ㄩ棬ID")
+    private Long deptId;
+
+    @Schema(description = "浜у搧缂栧彿")
+    private String productNo;
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/SalesLedgerProductionAccountingDto.java b/src/main/java/com/ruoyi/production/bean/dto/SalesLedgerProductionAccountingDto.java
new file mode 100644
index 0000000..9b2054e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/SalesLedgerProductionAccountingDto.java
@@ -0,0 +1,20 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+@Data
+public class SalesLedgerProductionAccountingDto {
+    @Schema(description = "鐢ㄦ埛ID")
+    private Long userId;
+    @Schema(description = "鐢ㄦ埛鍚嶇О")
+    private String userName;
+    @Schema(description = "宸ュ簭")
+    private String process;
+    @Schema(description = "寮�濮嬫棩鏈�")
+    private LocalDate startDate;
+    @Schema(description = "缁撴潫鏃ユ湡")
+    private LocalDate endDate;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/UserAccountDto.java b/src/main/java/com/ruoyi/production/bean/dto/UserAccountDto.java
new file mode 100644
index 0000000..6e371fe
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/UserAccountDto.java
@@ -0,0 +1,14 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class UserAccountDto {
+    @Schema(description = "閲戦")
+    private BigDecimal account = BigDecimal.ZERO;
+    @Schema(description = "璐︽埛浣欓")
+    private BigDecimal accountBalance = BigDecimal.ZERO;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/dto/UserProductionAccountingDto.java b/src/main/java/com/ruoyi/production/bean/dto/UserProductionAccountingDto.java
new file mode 100644
index 0000000..aafe767
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/dto/UserProductionAccountingDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.production.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class UserProductionAccountingDto {
+    @Schema(description = "鐢ㄦ埛ID")
+    private Long userId;
+    @Schema(description = "鏃ユ湡")
+    private String date;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java
new file mode 100644
index 0000000..5d86e7c
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionAccountVo.java
@@ -0,0 +1,59 @@
+package com.ruoyi.production.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+@Schema(name = "ProductionAccountVo", description = "production account page result")
+public class ProductionAccountVo {
+
+    @Schema(description = "customer contract no")
+    private String customerContractNo;
+
+    @Schema(description = "project name")
+    private String projectName;
+
+    @Schema(description = "customer name")
+    private String customerName;
+
+    @Schema(description = "product category")
+    private String productCategory;
+
+    @Schema(description = "specification model")
+    private String specificationModel;
+
+    @Schema(description = "unit")
+    private String unit;
+
+    @Schema(description = "scheduling user id")
+    private Long schedulingUserId;
+
+    @Schema(description = "scheduling user name")
+    private String schedulingUserName;
+
+    @Schema(description = "wages")
+    private BigDecimal wages;
+
+    @Schema(description = "finished quantity")
+    private BigDecimal finishedNum;
+
+    @Schema(description = "salary quota")
+    private BigDecimal workHours;
+
+    @Schema(description = "output rate")
+    private String outputRate;
+
+    @Schema(description = "process")
+    private String process;
+
+    @Schema(description = "scheduling date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate schedulingDate;
+
+    @Schema(description = "scheduling month(yyyy-MM)")
+    private String schedulingMonth;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java
new file mode 100644
index 0000000..36f9221
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionBomStructureVo.java
@@ -0,0 +1,27 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.production.pojo.ProductionBomStructure;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ProductionBomStructureVo extends ProductionBomStructure {
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "浜у搧ID")
+    private Long productId;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    private List<ProductionBomStructureVo> children;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
new file mode 100644
index 0000000..6c7c5a7
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOperationTaskVo.java
@@ -0,0 +1,49 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ProductionOperationTaskVo extends ProductionOperationTask {
+
+    @Schema(description = "璁㈠崟鍙�")
+    private String npsNo;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "宸ュ崟绫诲瀷 姝e父/杩斿伐杩斾慨")
+    private String workOrderType;
+
+    @Schema(description = "鐢熶骇浠诲姟鏁�")
+    private Long productionTaskCount;
+
+    @Schema(description = "鑹搧鏁�")
+    private BigDecimal goodQuantity;
+
+    @Schema(description = "鎶ュ簾鏁伴噺")
+    private BigDecimal scrapQty;
+
+    @Schema(description = "瀹屾垚杩涘害")
+    private BigDecimal completionStatus;
+
+    @Schema(description = "鎶ュ伐浜哄憳鍚嶇О锛屽涓娇鐢ㄩ�楀彿鍒嗛殧")
+    private String userNames;
+
+    @Schema(description = "鏄惁缁撴潫锛�")
+    private Boolean endOrder;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java
new file mode 100644
index 0000000..aea1c85
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickRecordVo.java
@@ -0,0 +1,34 @@
+package com.ruoyi.production.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.production.pojo.ProductionOrderPickRecord;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Schema(name = "ProductionOrderPickRecordVo", description = "宸查鏂欒鎯�")
+public class ProductionOrderPickRecordVo extends ProductionOrderPickRecord {
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "琛ユ枡浜�")
+    private String supplementUserName;
+
+    @Schema(description = "琛ユ枡鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime supplementTime;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java
new file mode 100644
index 0000000..d072634
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderPickVo.java
@@ -0,0 +1,32 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.production.pojo.ProductionOrderPick;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ProductionOrderPickVo extends ProductionOrderPick {
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "搴撳瓨鏁伴噺")
+    private BigDecimal stockQuantity;
+
+    @Schema(description = "棰嗙敤鏁伴噺")
+    private BigDecimal pickQuantity;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鎵瑰彿")
+    private List<String> batchNoList;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationParamVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationParamVo.java
new file mode 100644
index 0000000..e0819da
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationParamVo.java
@@ -0,0 +1,8 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import lombok.Data;
+
+@Data
+public class ProductionOrderRoutingOperationParamVo extends ProductionOrderRoutingOperationParam {
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationVo.java
new file mode 100644
index 0000000..4333814
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderRoutingOperationVo.java
@@ -0,0 +1,26 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ProductionOrderRoutingOperationVo extends ProductionOrderRoutingOperation {
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鍩虹宸ュ簭ID")
+    private Long technologyOperationId;
+
+    @Schema(description = "鍩虹宸ュ簭ID")
+    private Long productionOrderRoutingOperationId;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
new file mode 100644
index 0000000..1bb26a4
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderVo.java
@@ -0,0 +1,42 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.production.pojo.ProductionOrder;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "ProductionOrderVo", description = "鐢熶骇璁㈠崟杩斿洖瀵硅薄")
+public class ProductionOrderVo extends ProductionOrder {
+    @Schema(description = "閿�鍞悎鍚屽彿")
+    private String salesContractNo;
+
+    @Schema(description = "瀹㈡埛鍚嶇О")
+    private String customerName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "宸ヨ壓璺嚎缂栫爜")
+    private String processRouteCode;
+
+    @Schema(description = "浜у搧鍥剧墖")
+    private List<StorageBlobVO> productImages;
+
+    @Schema(description = "bom缂栧彿")
+    private String bomNo;
+
+    @Schema(description = "瀹屾垚杩涘害")
+    private BigDecimal completionStatus;
+
+    @Schema(description = "鏄惁宸查��鏂�")
+    private Boolean returned;
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java
new file mode 100644
index 0000000..2a0571d
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionOrderWorkOrderDetailVo.java
@@ -0,0 +1,74 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import com.ruoyi.production.pojo.ProductionProductMain;
+import com.ruoyi.production.pojo.ProductionProductOutput;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectFile;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@Schema(name = "ProductionOrderWorkOrderDetailVo", description = "鐢熶骇杩芥函杩斿洖瀵硅薄")
+public class ProductionOrderWorkOrderDetailVo {
+
+    @Schema(description = "璁㈠崟")
+    private ProductionOrderVo productionOrder;
+
+    @Schema(description = "宸ュ崟鏄庣粏鍒楄〃")
+    private List<WorkOrderDetail> workOrderList;
+
+    @Data
+    @Schema(name = "WorkOrderDetail", description = "宸ュ崟鏄庣粏")
+    public static class WorkOrderDetail {
+
+        @Schema(description = "宸ュ崟淇℃伅")
+        private ProductionOperationTaskVo workOrder;
+
+        @Schema(description = "鎶ュ伐璇︽儏鍒楄〃")
+        private List<ReportDetail> reportList;
+
+        @Schema(description = "璐ㄦ璇︽儏鍒楄〃")
+        private List<InspectDetail> inspectList;
+    }
+
+    @Data
+    @Schema(name = "ReportDetail", description = "鎶ュ伐璇︽儏")
+    public static class ReportDetail {
+
+        @Schema(description = "鎶ュ伐涓讳俊鎭�")
+        private ProductionProductMain reportMain;
+
+        @Schema(description = "鎶ュ伐浜у嚭鏄庣粏")
+        private List<ProductionProductOutput> reportOutputList;
+
+        @Schema(description = "鎶ュ伐宸ュ簭鍙傛暟")
+        private List<ProductionOrderRoutingOperationParam> reportParamList;
+    }
+
+    @Data
+    @Schema(name = "InspectDetail", description = "璐ㄦ璇︽儏")
+    public static class InspectDetail {
+
+        @Schema(description = "鎶ュ伐ID")
+        private Long reportId;
+
+        @Schema(description = "鎶ュ伐鍗曞彿")
+        private String reportNo;
+
+        @Schema(description = "鎶ュ伐涓讳俊鎭�")
+        private ProductionProductMain reportMain;
+
+        @Schema(description = "璐ㄦ涓讳俊鎭�")
+        private QualityInspect inspect;
+
+        @Schema(description = "璐ㄦ鎸囨爣鏄庣粏")
+        private List<QualityInspectParam> inspectParamList;
+
+        @Schema(description = "璐ㄦ闄勪欢鍒楄〃")
+        private List<QualityInspectFile> inspectFileList;
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/bean/vo/ProductionPlanVo.java b/src/main/java/com/ruoyi/production/bean/vo/ProductionPlanVo.java
new file mode 100644
index 0000000..a39c83a
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/bean/vo/ProductionPlanVo.java
@@ -0,0 +1,33 @@
+package com.ruoyi.production.bean.vo;
+
+import com.ruoyi.production.pojo.ProductionPlan;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "ProductionPlanVo", description = "鐢熶骇璁″垝杩斿洖瀵硅薄")
+public class ProductionPlanVo extends ProductionPlan {
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "浜у搧ID")
+    private Long productId;
+
+    @Schema(description = "閿�鍞悎鍚屽彿")
+    private String salesContractNo;
+
+    @Schema(description = "瀹㈡埛鍚嶇О")
+    private String customerName;
+
+    @Schema(description = "椤圭洰鍚嶇О")
+    private String projectName;
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProcessRouteController.java b/src/main/java/com/ruoyi/production/controller/ProcessRouteController.java
deleted file mode 100644
index 50ac4a8..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProcessRouteController.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import com.ruoyi.production.service.ProcessRouteItemService;
-import com.ruoyi.production.service.ProcessRouteService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Arrays;
-
-@RestController
-@RequestMapping("processRoute")
-@Api(tags = "宸ヨ壓璺嚎")
-public class ProcessRouteController {
-
-    @Autowired
-    private ProcessRouteService processRouteService;
-
-    @GetMapping("page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
-    public R page(Page<ProcessRouteDto>  page, ProcessRouteDto processRouteDto) {
-        return R.ok(processRouteService.pageProcessRouteDto(page, processRouteDto));
-    }
-
-    @ApiOperation("鏂板宸ヨ壓璺嚎")
-    @PostMapping ()
-    public R add(@RequestBody  ProcessRoute processRoute) {
-        return R.ok(processRouteService.saveProcessRoute(processRoute));
-    }
-    @ApiOperation("淇敼宸ヨ壓璺嚎")
-    @PutMapping ()
-    public R update(@RequestBody  ProcessRoute processRoute) {
-        return R.ok(processRouteService.updateById(processRoute));
-    }
-    @ApiOperation("鍒犻櫎宸ヨ壓璺嚎")
-    @DeleteMapping("/{ids}")
-    public R delete(@PathVariable("ids") Long[] ids) {
-        return R.ok(processRouteService.batchDelete(Arrays.asList(ids)));
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProcessRouteItemController.java b/src/main/java/com/ruoyi/production/controller/ProcessRouteItemController.java
deleted file mode 100644
index 451548d..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProcessRouteItemController.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProcessRouteItemDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import com.ruoyi.production.service.ProcessRouteItemService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Arrays;
-import java.util.List;
-
-@RestController
-@RequestMapping("processRouteItem")
-@Api(tags = "宸ヨ壓璺嚎鏄庣粏")
-public class ProcessRouteItemController {
-    @Autowired
-    private ProcessRouteItemService processRouteItemService;
-
-    @GetMapping("list")
-    public R listProcessRouteItemDto(ProcessRouteItemDto processRouteItemDto) {
-        return R.ok(processRouteItemService.listProcessRouteItemDto(processRouteItemDto));
-    }
-
-    @PostMapping ()
-    @ApiOperation("鏂板淇敼")
-    public R addOrUpdate(@RequestBody ProcessRouteItem processRouteItem) {
-        return R.ok(processRouteItemService.saveOrUpdate(processRouteItem));
-    }
-
-    @PostMapping ("/sort")
-    @ApiOperation("鎺掑簭")
-    public R sort(@RequestBody ProcessRouteItem processRouteItem) {
-        return R.ok(processRouteItemService.sort(processRouteItem));
-    }
-
-    @ApiOperation("鍒犻櫎宸ヨ壓璺嚎鏄庣粏")
-    @DeleteMapping("/batchDelete/{id}")
-    @Log(title = "鍒犻櫎", businessType = BusinessType.DELETE)
-    public AjaxResult batchDelete(@PathVariable("id") Long id) {
-        return AjaxResult.success(processRouteItemService.batchDelete(id));
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductBomController.java b/src/main/java/com/ruoyi/production/controller/ProductBomController.java
deleted file mode 100644
index 0ad7d59..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductBomController.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.dto.BomImportDto;
-import com.ruoyi.production.dto.ProductBomDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import com.ruoyi.production.pojo.ProductBom;
-import com.ruoyi.production.pojo.ProductProcessRoute;
-import com.ruoyi.production.pojo.ProductStructure;
-import com.ruoyi.production.service.ProcessRouteService;
-import com.ruoyi.production.service.ProductBomService;
-import com.ruoyi.production.service.ProductProcessRouteService;
-import com.ruoyi.production.service.ProductStructureService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiModelProperty;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * <p>
- * BOM涓昏〃 鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 09:59:27
- */
-@RestController
-@RequestMapping("/productBom")
-@Api(tags = "BOM")
-public class ProductBomController {
-
-    @Autowired
-    private ProductBomService productBomService;
-
-    @Autowired
-    private ProcessRouteService processRouteService;
-
-    @Autowired
-    private ProductProcessRouteService productProcessRouteService;
-
-    @Autowired
-    private ProductStructureService productStructureService;
-
-    @GetMapping("/listPage")
-    @Log(title = "BOM-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("BOM-鍒嗛〉鏌ヨ")
-    public AjaxResult listPage(Page page, ProductBomDto productBomDto) {
-        IPage<ProductBomDto> listPage = productBomService.listPage(page, productBomDto);
-        return AjaxResult.success(listPage);
-    }
-
-    @ApiModelProperty("鏂板BOM")
-    @PostMapping("/add")
-    @Log(title = "鏂板", businessType = BusinessType.INSERT)
-    public AjaxResult add(@RequestBody ProductBom productBom) {
-        return productBomService.add(productBom);
-    }
-
-    @ApiOperation("鏇存柊BOM")
-    @Log(title = "淇敼", businessType = BusinessType.UPDATE)
-    @PutMapping("/update")
-    public AjaxResult update(@RequestBody ProductBom productBom) {
-        return AjaxResult.success(productBomService.updateById(productBom));
-    }
-
-    @ApiOperation("鍒犻櫎BOM")
-    @DeleteMapping("/batchDelete")
-    @Log(title = "鍒犻櫎", businessType = BusinessType.DELETE)
-    public AjaxResult batchDelete(@RequestBody List<Integer> ids) {
-        List<ProcessRoute> list = processRouteService.list(Wrappers.<ProcessRoute>lambdaQuery().in(ProcessRoute::getBomId, ids));
-        List<ProductProcessRoute> list2 = productProcessRouteService.list(Wrappers.<ProductProcessRoute>lambdaQuery().in(ProductProcessRoute::getBomId, ids));
-        if (list.size() > 0 || list2.size() > 0) {
-            return AjaxResult.error("璇OM宸茬粡瀛樺湪瀵瑰簲鐨勫伐鑹鸿矾绾�,鏃犳硶杩涜鍒犻櫎");
-        }
-        if (CollectionUtils.isEmpty(ids)) {
-            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
-        }
-        //鍒犻櫎bom瀛愯〃
-        productStructureService.remove(Wrappers.<ProductStructure>lambdaQuery().in(ProductStructure::getBomId, ids));
-        return AjaxResult.success(productBomService.removeBatchByIds(ids));
-    }
-
-    @GetMapping("/getByModel")
-    @Log(title = "BOM-鏍规嵁閫夋嫨鐨勮鏍煎瀷鍙穒d鏌ヨ瀛樺湪鐨刡om", businessType = BusinessType.OTHER)
-    @ApiOperation("BOM-鏍规嵁閫夋嫨鐨勮鏍煎瀷鍙穒d鏌ヨ瀛樺湪鐨刡om")
-    public AjaxResult getByModel(Long productModelId) {
-        List<ProductBom> productBoms = productBomService.list(Wrappers.<ProductBom>lambdaQuery().eq(ProductBom::getProductModelId, productModelId));
-        return AjaxResult.success(productBoms);
-    }
-
-
-    @PostMapping("uploadBom")
-    @PreAuthorize("@ss.hasPermi('product:bom:import')")
-    @Log(title = "鏍规嵁Excel瀵煎叆BOM", businessType = BusinessType.IMPORT)
-    @ApiOperation("鏍规嵁Excel瀵煎叆BOM")
-    public AjaxResult uploadBom(@RequestParam("file") MultipartFile file) {
-        return productBomService.uploadBom(file);
-    }
-
-    @PostMapping("exportBom")
-    @PreAuthorize("@ss.hasPermi('product:bom:export')")
-    @ApiOperation("瀵煎嚭BOM鏂囦欢")
-    @Log(title = "瀵煎嚭BOM鏂囦欢", businessType = BusinessType.EXPORT)
-    public void exportBom(HttpServletResponse response, @RequestParam Integer bomId) {
-        productBomService.exportBom(response, bomId);
-    }
-
-    @GetMapping("/downloadTemplate")
-    @Log(title = "涓嬭浇BOM瀵煎叆妯℃澘", businessType = BusinessType.EXPORT)
-    @ApiOperation("涓嬭浇BOM瀵煎叆妯℃澘")
-    public void importTemplate(HttpServletResponse response) {
-        ExcelUtil<BomImportDto> excelUtil = new ExcelUtil<>(BomImportDto.class);
-        excelUtil.importTemplateExcel(response, "BOM瀵煎叆妯℃澘");
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductOrderController.java b/src/main/java/com/ruoyi/production/controller/ProductOrderController.java
deleted file mode 100644
index e1c22d1..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductOrderController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.basic.pojo.Customer;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductOrderDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import com.ruoyi.production.pojo.ProductOrder;
-import com.ruoyi.production.service.ProductOrderService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.util.List;
-
-@RequestMapping("productOrder")
-@RestController
-@Api(tags = "鐢熶骇璁㈠崟")
-public class ProductOrderController {
-
-    @Autowired
-    private ProductOrderService productOrderService;
-
-
-    @ApiOperation("鍒嗛〉鏌ヨ")
-    @GetMapping("page")
-    public R page(ProductOrderDto productOrder, Page page) {
-        return R.ok(productOrderService.pageProductOrder(page, productOrder));
-    }
-
-    @ApiOperation("缁戝畾宸ヨ壓璺嚎")
-    @PostMapping("/bindingRoute")
-    public R bindingRoute(@RequestBody ProductOrder productOrder) {
-        return R.ok(productOrderService.bindingRoute(productOrder));
-    }
-
-    @ApiOperation("鏌ヨ瑙勬牸鍨嬪彿瀵瑰簲鐨勫伐鑹鸿矾绾�")
-    @GetMapping("/listProcessRoute")
-    public R listProcessRoute(Long productModelId) {
-        return R.ok(productOrderService.listProcessRoute(productModelId));
-    }
-
-    /**
-     * 瀵煎嚭鐢熶骇璁㈠崟
-     */
-    @Log(title = "鐢熶骇璁㈠崟", businessType = BusinessType.EXPORT)
-    @PostMapping("/export")
-    public void export(HttpServletResponse response, ProductOrderDto productOrderDto) {
-        List<ProductOrderDto> list = productOrderService.pageProductOrder(new Page<>(1, -1), productOrderDto).getRecords();
-        ExcelUtil<ProductOrderDto> util = new ExcelUtil<>(ProductOrderDto.class);
-        util.exportExcel(response, list, "鐢熶骇璁㈠崟鏁版嵁");
-    }
-
-    @ApiOperation("鏌ヨ鐢熶骇璁㈠崟瀵瑰簲鐨凚OM")
-    @GetMapping("/listProcessBom")
-    public R listProcessBom(Long orderId) {
-        return R.ok(productOrderService.listProcessBom(orderId));
-    }
-
-
-    @ApiOperation("鏂板鐢熶骇璁㈠崟")
-    @PostMapping("addProductOrder")
-    public R addProductOrder(@RequestBody ProductOrder productOrder) {
-        return R.ok(productOrderService.addProductOrder(productOrder));
-    }
-
-    @ApiOperation("鍒犻櫎鐢熶骇璁㈠崟")
-    @DeleteMapping("/{ids}")
-    public R delete(@PathVariable("ids") Long[] ids) {
-        return R.ok(productOrderService.delete(ids));
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductProcessController.java b/src/main/java/com/ruoyi/production/controller/ProductProcessController.java
deleted file mode 100644
index c25f2cc..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductProcessController.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.basic.pojo.Customer;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.device.pojo.DeviceRepair;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.oA.pojo.OaProject;
-import com.ruoyi.production.dto.ProductProcessDto;
-import com.ruoyi.production.pojo.ProductProcess;
-import com.ruoyi.production.service.impl.ProductProcessServiceImpl;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiModelProperty;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
-@RestController
-@Api(tags = "宸ュ簭")
-@RequestMapping("/productProcess")
-public class ProductProcessController extends BaseController {
-
-
-    @Autowired
-    private ProductProcessServiceImpl productProcessService;
-
-    @GetMapping("/listPage")
-    @Log(title = "宸ュ簭-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("宸ュ簭-鍒嗛〉鏌ヨ")
-    public AjaxResult listPage(Page page, ProductProcessDto productProcessDto) {
-        IPage<ProductProcessDto> listPage = productProcessService.listPage(page, productProcessDto);
-        return AjaxResult.success(listPage);
-    }
-
-    @ApiModelProperty("鏂板宸ュ簭")
-    @PostMapping()
-    @Log(title = "鏂板", businessType = BusinessType.INSERT)
-    public AjaxResult add( @RequestBody ProductProcessDto productProcessDto) {
-        return productProcessService.add(productProcessDto);
-    }
-
-    @ApiOperation("鏇存柊宸ュ簭")
-    @Log(title = "淇敼", businessType = BusinessType.UPDATE)
-    @PutMapping("/update")
-    public AjaxResult update(@RequestBody ProductProcess productProcess) {
-        return AjaxResult.success(productProcessService.updateById(productProcess));
-    }
-
-    @ApiOperation("鍒犻櫎宸ュ簭")
-    @DeleteMapping("/batchDelete")
-    @Log(title = "鍒犻櫎", businessType = BusinessType.DELETE)
-    public AjaxResult batchDelete(@RequestBody List<Integer> ids) {
-        return AjaxResult.success(productProcessService.batchDelete(ids));
-    }
-
-    @ApiOperation("鏌ヨ鎵�鏈夊伐搴�")
-    @GetMapping("/list")
-    public AjaxResult list() {
-        return AjaxResult.success(productProcessService.list());
-        }
-
-    /**
-     * 瀵煎叆宸ュ簭
-     */
-    @Log(title = "宸ュ簭", businessType = BusinessType.IMPORT)
-    @PostMapping("/importData")
-    public AjaxResult importData(MultipartFile file) throws Exception {
-        return productProcessService.importData(file);
-    }
-
-    @PostMapping("/downloadTemplate")
-    @Log(title = "宸ュ簭-涓嬭浇妯℃澘", businessType = BusinessType.EXPORT)
-    public void downloadTemplate(HttpServletResponse response) {
-        ExcelUtil<ProductProcess> util = new ExcelUtil<ProductProcess>(ProductProcess.class);
-        util.importTemplateExcel(response, "宸ュ簭妯℃澘");
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductProcessRouteController.java b/src/main/java/com/ruoyi/production/controller/ProductProcessRouteController.java
deleted file mode 100644
index bb1b010..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductProcessRouteController.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.controller;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- *  鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:51:09
- */
-@RestController
-@RequestMapping("/productProcessRoute")
-public class ProductProcessRouteController {
-
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductProcessRouteItemController.java b/src/main/java/com/ruoyi/production/controller/ProductProcessRouteItemController.java
deleted file mode 100644
index 2d5231d..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductProcessRouteItemController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductProcessRouteItemDto;
-import com.ruoyi.production.mapper.*;
-import com.ruoyi.production.pojo.*;
-import com.ruoyi.production.service.ProductProcessRouteItemService;
-import com.ruoyi.production.service.ProductProcessRouteService;
-import com.ruoyi.production.service.ProductWorkOrderService;
-import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.pojo.QualityInspect;
-import com.ruoyi.sales.mapper.SalesLedgerMapper;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.SalesLedger;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import lombok.AllArgsConstructor;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-@RequestMapping("/productProcessRoute")
-@RestController
-@AllArgsConstructor
-@Api(tags = "鐢熶骇宸ヨ壓璺嚎")
-public class ProductProcessRouteItemController {
-
-
-    private ProductProcessRouteItemService productProcessRouteItemService;
-    private ProductProcessRouteService productProcessRouteService;
-
-    @GetMapping("list")
-    @ApiOperation("鏍规嵁Id鏌ヨ宸ヨ壓璺嚎瀛愯〃")
-    public R list(Long orderId) {
-        return R.ok(productProcessRouteItemService.listItem(orderId));
-    }
-
-    @GetMapping("listMain")
-    @ApiOperation("鏍规嵁Id鏌ヨ宸ヨ壓璺嚎涓昏〃")
-    public R listMain(Long orderId) {
-        return R.ok(productProcessRouteService.listMain(orderId));
-    }
-
-    @PostMapping("/addRouteItem")
-    @ApiOperation("鏂板鐢熶骇璁㈠崟鐨勫伐鑹鸿矾绾胯鎯�")
-    public R addRouteItem(@RequestBody ProductProcessRouteItem productProcessRouteItem) {
-        return productProcessRouteItemService.addRouteItem(productProcessRouteItem);
-    }
-
-    @PostMapping("/updateRouteItem")
-    @ApiOperation("淇敼鐢熶骇璁㈠崟鐨勫伐鑹鸿矾绾胯鎯�")
-    public R updateRouteItem(@RequestBody ProductProcessRouteItem productProcessRouteItem) {
-        return R.ok(productProcessRouteItemService.updateById(productProcessRouteItem));
-    }
-
-    @DeleteMapping("/deleteRouteItem/{id}")
-    @ApiOperation("鍒犻櫎鐢熶骇宸ヨ壓璺嚎")
-    public R deleteRouteItem(@PathVariable("id") Long id) {
-        return productProcessRouteItemService.deleteRouteItem(id);
-    }
-
-    @PostMapping ("/sortRouteItem")
-    @ApiOperation("鎺掑簭")
-    public R sortRouteItem(@RequestBody ProductProcessRouteItem productProcessRouteItem) {
-        return R.ok(productProcessRouteItemService.sortRouteItem(productProcessRouteItem));
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductStructureController.java b/src/main/java/com/ruoyi/production/controller/ProductStructureController.java
deleted file mode 100644
index 89ead6d..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductStructureController.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductProcessDto;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.pojo.ProductStructure;
-import com.ruoyi.production.service.ProductStructureService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Arrays;
-
-@RequestMapping("productStructure")
-@RestController
-@Api(tags = "BOM")
-public class ProductStructureController {
-    @Autowired
-    private ProductStructureService productStructureService;
-
-
-    @ApiOperation("鏂板BOM瀛愰泦")
-    @PostMapping()
-    public R addOrUpdate(@RequestBody ProductStructureDto productStructureDto){
-        return R.ok(productStructureService.addProductStructureDto(productStructureDto));
-    }
-
-    @ApiOperation("BOM鏌ョ湅瀛愰泦璇︽儏")
-    @GetMapping("/listBybomId/{bomId}")
-    public R listBybomId( @PathVariable("bomId") Integer bomId){
-        return R.ok(productStructureService.listBybomId(bomId));
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductWorkOrderController.java b/src/main/java/com/ruoyi/production/controller/ProductWorkOrderController.java
deleted file mode 100644
index 029e457..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductWorkOrderController.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductWorkOrderDto;
-import com.ruoyi.production.pojo.ProductWorkOrder;
-import com.ruoyi.production.service.ProductWorkOrderService;
-import com.ruoyi.quality.pojo.QualityInspect;
-import io.swagger.annotations.ApiOperation;
-import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletResponse;
-
-@RestController
-@AllArgsConstructor
-@RequestMapping("/productWorkOrder")
-public class ProductWorkOrderController {
-
-    private ProductWorkOrderService productWorkOrderservice;
-
-
-    /**
-     * 浜у搧宸ュ崟瀹炰綋绫诲垎椤垫煡璇�
-     */
-    @ApiOperation("浜у搧宸ュ崟瀹炰綋绫诲垎椤垫煡璇�")
-    @GetMapping("/page")
-    public R page(Page<ProductWorkOrderDto> page, ProductWorkOrderDto productWorkOrder) {
-        return R.ok(productWorkOrderservice.listPage(page, productWorkOrder));
-    }
-
-    /**
-     * 浜у搧宸ュ崟鏇存柊
-     */
-    @ApiOperation("浜у搧宸ュ崟鏇存柊")
-    @PostMapping ("/updateProductWorkOrder")
-    public R updateProductWorkOrder(@RequestBody ProductWorkOrderDto productWorkOrderDto) {
-        return R.ok(productWorkOrderservice.updateProductWorkOrder(productWorkOrderDto));
-    }
-
-    /**
-     * pda鏍规嵁浜岀淮鐮佺殑宸ュ崟id鏌ヨ鏁版嵁
-     */
-    @ApiOperation("pda鏍规嵁浜岀淮鐮佺殑宸ュ崟id鏌ヨ鏁版嵁")
-    @GetMapping("/getProductWorkOrderById")
-    public R getProductWorkOrderById(Long id) {
-        return R.ok(productWorkOrderservice.getById(id));
-    }
-
-    /**
-     * 宸ュ崟娴佽浆鍗′笅杞�
-     * @param response
-     * @param productWorkOrder
-     */
-    @PostMapping("/down")
-    public void down(HttpServletResponse response, @RequestBody ProductWorkOrder productWorkOrder) {
-        productWorkOrderservice.down(response, productWorkOrder);
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductWorkOrderFileController.java b/src/main/java/com/ruoyi/production/controller/ProductWorkOrderFileController.java
deleted file mode 100644
index 1f1b37e..0000000
--- a/src/main/java/com/ruoyi/production/controller/ProductWorkOrderFileController.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.pojo.ProductWorkOrderFile;
-import com.ruoyi.production.service.ProductWorkOrderFileService;
-import com.ruoyi.quality.pojo.QualityInspectFile;
-import com.ruoyi.quality.service.IQualityInspectFileService;
-import io.swagger.annotations.Api;
-import org.checkerframework.checker.units.qual.A;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-/**
- * <p>
- * 鐢熶骇宸ュ崟闄勪欢琛� 鍓嶇鎺у埗鍣�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-23 03:28:32
- */
-@Api(tags = "鐢熶骇宸ュ崟闄勪欢琛�")
-@RestController
-@RequestMapping("/productWorkOrderFile")
-public class ProductWorkOrderFileController {
-
-    @Resource
-    private ProductWorkOrderFileService productWorkOrderFileService;
-
-
-    /**
-     * 鏂板
-     * @param productWorkOrderFile
-     * @return
-     */
-    @PostMapping("/add")
-    public AjaxResult add(@RequestBody ProductWorkOrderFile productWorkOrderFile) {
-        return AjaxResult.success(productWorkOrderFileService.save(productWorkOrderFile));
-    }
-
-    /**
-     * 鍒犻櫎
-     * @param ids
-     * @return
-     */
-    @DeleteMapping("/del")
-    public AjaxResult delQualityUnqualified(@RequestBody List<Integer> ids) {
-        if(CollectionUtils.isEmpty(ids)){
-            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
-        }
-        //鍒犻櫎妫�楠岄檮浠�
-        return AjaxResult.success(productWorkOrderFileService.removeBatchByIds(ids));
-    }
-
-    /**
-     *鍒嗛〉鏌ヨ
-     * @param page
-     * @param productWorkOrderFile
-     * @return
-     */
-    @GetMapping("/listPage")
-    public AjaxResult listPage(Page page, ProductWorkOrderFile productWorkOrderFile) {
-        return AjaxResult.success(productWorkOrderFileService.page(page, Wrappers.<ProductWorkOrderFile>lambdaQuery().eq(ProductWorkOrderFile::getWorkOrderId,productWorkOrderFile.getWorkOrderId())));
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionAccountController.java b/src/main/java/com/ruoyi/production/controller/ProductionAccountController.java
new file mode 100644
index 0000000..d87996f
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionAccountController.java
@@ -0,0 +1,41 @@
+package com.ruoyi.production.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
+import com.ruoyi.production.service.ProductionAccountService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鐢熶骇鏍哥畻琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ */
+@RestController
+@RequestMapping("/productionAccount")
+@RequiredArgsConstructor
+@Tag(name = "鐢熶骇鏍哥畻")
+public class ProductionAccountController {
+
+    private final ProductionAccountService productionAccountService;
+
+    @GetMapping("/listPage")
+    @Operation(summary = "鐢熶骇鏍哥畻鍒嗛〉鏌ヨ")
+    public R<IPage<ProductionAccountVo>> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto) {
+        return R.ok(productionAccountService.listPage(page, dto));
+    }
+
+    @GetMapping("/listProductionDetails")
+    @Operation(summary ="鏌ヨ宸ヤ汉鐢熶骇宸ヨ祫淇℃伅")
+    public R<IPage<ProductionProductMainDto>> listProductionDetails(ProductionAccountDto productionAccountDto, Page page) {
+        return R.ok(productionAccountService.listProductionDetails(productionAccountDto,page));
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java b/src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java
new file mode 100644
index 0000000..dd1d50e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionBomStructureController.java
@@ -0,0 +1,40 @@
+package com.ruoyi.production.controller;
+
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionBomStructureDto;
+import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
+import com.ruoyi.production.service.ProductionBomStructureService;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@RestController
+@RequestMapping("/productionBomStructure")
+@AllArgsConstructor
+public class ProductionBomStructureController {
+
+    private ProductionBomStructureService productionBomStructureService;
+
+    @GetMapping("/listByBomId/{bomId}")
+    @Operation(summary = "鏍规嵁BOM鏌ヨ鐢熶骇璁㈠崟BOM缁撴瀯鏍�")
+    public R<List<ProductionBomStructureVo>> listByBomId(@PathVariable Long bomId) {
+        return R.ok(productionBomStructureService.listByBomId(bomId));
+    }
+
+    @PostMapping("/addOrUpdateBomStructs")
+    @Operation(summary = "鏂板鎴栦慨鏀笲OM缁撴瀯")
+    public R addProductionBomStructure(@RequestBody ProductionBomStructureDto productionBomStructureDto) {
+        return R.ok(productionBomStructureService.addProductionBomStructure(productionBomStructureDto));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOperationMainParamController.java b/src/main/java/com/ruoyi/production/controller/ProductionOperationMainParamController.java
new file mode 100644
index 0000000..e3dac6a
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOperationMainParamController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.production.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鐢熶骇宸ュ崟鎶ュ伐鍙傛暟琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@RestController
+@RequestMapping("/productionOperationMainParam")
+public class ProductionOperationMainParamController {
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
new file mode 100644
index 0000000..56ed8c2
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
@@ -0,0 +1,85 @@
+package com.ruoyi.production.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
+import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import com.ruoyi.production.service.ProductionOperationTaskService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/productionOperationTask")
+@Tag(name = "鐢熶骇宸ュ崟")
+@RequiredArgsConstructor
+public class ProductionOperationTaskController {
+
+    private final ProductionOperationTaskService productionOperationTaskService;
+
+    @GetMapping("/page")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
+    public R page(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) {
+        return R.ok(productionOperationTaskService.pageProductionOperationTask(page, dto));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "宸ュ崟鍒楄〃")
+    public R<List<ProductionOperationTaskVo>> list(ProductionOperationTaskDto dto) {
+        return R.ok(productionOperationTaskService.listProductionOperationTask(dto));
+    }
+
+    @GetMapping("/{id}")
+    @Operation(summary = "宸ュ崟璇︽儏")
+    public R<ProductionOperationTaskVo> getInfo(@PathVariable("id") Long id) {
+        return R.ok(productionOperationTaskService.getProductionOperationTaskInfo(id));
+    }
+
+    @PostMapping
+    @Operation(summary = "鏂板宸ュ崟")
+    public R<Boolean> add(@RequestBody ProductionOperationTask productionOperationTask) {
+        return R.ok(productionOperationTaskService.saveProductionOperationTask(productionOperationTask));
+    }
+
+    @PutMapping
+    @Operation(summary = "淇敼宸ュ崟")
+    public R<Boolean> edit(@RequestBody ProductionOperationTask productionOperationTask) {
+        return R.ok(productionOperationTaskService.saveProductionOperationTask(productionOperationTask));
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "鍒犻櫎宸ュ崟")
+    public R<Boolean> remove(@RequestBody List<Long> ids) {
+        return R.ok(productionOperationTaskService.removeProductionOperationTask(ids));
+    }
+
+    @Operation(summary = "浜у搧宸ュ崟鏇存柊")
+    @PostMapping("/updateProductWorkOrder")
+    public R updateProductWorkOrder(@RequestBody ProductionOperationTaskDto dto) {
+        return R.ok(productionOperationTaskService.updateProductWorkOrder(dto));
+    }
+
+    @Operation(summary = "鎸囨淳鎶ュ伐浜�")
+    @PostMapping("/assign")
+    public R<Boolean> assign(@RequestBody ProductionOperationTaskDto dto) {
+        return R.ok(productionOperationTaskService.assign(dto));
+    }
+
+    @PostMapping("/down")
+    @Operation(summary = "宸ュ崟娴佽浆鍗′笅杞�")
+    public void down(HttpServletResponse response, @RequestBody ProductionOperationTaskDto dto) {
+        productionOperationTaskService.down(response, dto);
+    }
+
+    @GetMapping("/getOperation")
+    @Operation(summary = "宸ュ簭璇︽儏鏌ヨ")
+    public R<List<ProductionOperationTaskVo>> getOperation(ProductionOperationTaskDto dto) {
+        return R.ok(productionOperationTaskService.getOperation(dto));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java
new file mode 100644
index 0000000..ee0ecdc
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderBomController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.production.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@RestController
+@RequestMapping("/productionOrderBom")
+public class ProductionOrderBomController {
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
new file mode 100644
index 0000000..b5f7b97
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
@@ -0,0 +1,98 @@
+package com.ruoyi.production.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionOrderDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.bean.vo.ProductionOrderVo;
+import com.ruoyi.production.bean.vo.ProductionPlanVo;
+import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.service.ProductionOrderService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/productionOrder")
+@Tag(name = "鐢熶骇璁㈠崟")
+@RequiredArgsConstructor
+public class ProductionOrderController {
+
+    private final ProductionOrderService productionOrderService;
+
+    @GetMapping("/page")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
+    public R<IPage<ProductionOrderVo>> page(ProductionOrderDto dto, Page<ProductionOrderDto> page) {
+        return R.ok(productionOrderService.pageProductionOrder(page, dto));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "鐢熶骇璁㈠崟鍒楄〃")
+    public R<List<ProductionOrderVo>> list(ProductionOrderDto dto) {
+        return R.ok(productionOrderService.listProductionOrder(dto));
+    }
+
+    @GetMapping("/{id}")
+    @Operation(summary = "鐢熶骇璁㈠崟璇︽儏")
+    public R<ProductionOrderVo> getInfo(@PathVariable Long id) {
+        return R.ok(productionOrderService.getProductionOrderInfo(id));
+    }
+
+    @PostMapping("/addOrder")
+    @Operation(summary = "鏂板鐢熶骇璁㈠崟", description = "鏂板涓嬪崟鍙敮鎸�1绉嶆柟寮忥細鐢熶骇璁″垝鐢熸垚锛屼紶 productionPlanIds锛岀郴缁熻嚜鍔ㄦ眹鎬昏鍒掑緱鍒颁骇鍝佽鏍煎拰鏁伴噺锛�"
+                    + "technologyRoutingId 涓虹┖鏃朵細鑷姩鍖归厤璇ヤ骇鍝佽鏍兼渶鏂板伐鑹鸿矾绾匡紝quantity 鏈�缁堝繀椤诲ぇ浜� 0銆�")
+    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, description = "鍓嶇鍙嬪ソ鎻愮ず锛氬鏋滄槸鐢熶骇璁″垝鐢熸垚锛岃浼� productionPlanIds锛�"
+                    , content = @Content(schema = @Schema(implementation = ProductionOrder.class)))
+    public R<Boolean> add(@RequestBody ProductionOrder productionOrder) {
+        return R.ok(productionOrderService.saveProductionOrder(productionOrder));
+    }
+
+    @Operation(summary = "缁戝畾宸ヨ壓璺嚎")
+    @PostMapping("/bindingRoute")
+    public R bindingRoute(@RequestBody ProductionOrderDto productionOrderDto) {
+        return R.ok(productionOrderService.bindingRoute(productionOrderDto));
+    }
+
+    @PostMapping("/syncSnapshot/{id}")
+    @Operation(summary = "鍚屾鐢熶骇璁㈠崟宸ヨ壓/BOM蹇収")
+    public R<Integer> syncSnapshot(@PathVariable Long id) {
+        return R.ok(productionOrderService.syncProductionOrderSnapshot(id));
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "鍒犻櫎鐢熶骇璁㈠崟")
+    public R<Boolean> remove(@RequestBody List<Long> ids) {
+        return R.ok(productionOrderService.removeProductionOrder(ids));
+    }
+
+    @GetMapping("/source/{id}")
+    @Operation(summary = "鐢熶骇璁㈠崟鏌ヨ鏉ユ簮")
+    public R<List<ProductionPlanVo>> getSource(@PathVariable Long id) {
+        return R.ok(productionOrderService.getSource(id));
+    }
+
+    @GetMapping("/pick/{productionOrderId}")
+    @Operation(summary = "鏍规嵁璁㈠崟id鏌ヨbom棰嗘枡鍗�")
+    public R<List<ProductionOrderPickVo>> pick(@PathVariable Long productionOrderId) {
+        return R.ok(productionOrderService.pick(productionOrderId));
+    }
+
+    @GetMapping("/ordeDetail")
+    @Operation(summary = "鐢熶骇杩芥函")
+    public R<ProductionOrderWorkOrderDetailVo> getWorkOrderReportInspectDetail(ProductionOrderDto productionOrderDto) {
+        return R.ok(productionOrderService.getWorkOrderReportInspectDetail(productionOrderDto));
+    }
+
+    @Operation(summary = "鏇存柊璁㈠崟鐘舵��")
+    @PostMapping("/updateOrder")
+    public R updateOrder(@RequestBody ProductionOrderDto productionOrderDto) {
+        return R.ok(productionOrderService.updateOrder(productionOrderDto));
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java
new file mode 100644
index 0000000..a8e2d2e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderPickController.java
@@ -0,0 +1,48 @@
+package com.ruoyi.production.controller;
+
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.service.ProductionOrderPickService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璁㈠崟棰嗘枡绾胯竟浠� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@RestController
+@RequestMapping("/productionOrderPick")
+@Tag(name = "鐢熶骇璁㈠崟棰嗘枡")
+@RequiredArgsConstructor
+public class ProductionOrderPickController {
+
+    private final ProductionOrderPickService productionOrderPickService;
+
+    @PostMapping("/savePick")
+    @Operation(summary = "棰嗘枡淇濆瓨鍒扮嚎杈逛粨")
+    public R<Boolean> savePick(@RequestBody ProductionOrderPickDto dto) {
+        return R.ok(productionOrderPickService.savePick(dto));
+    }
+
+    @PostMapping("/updatePick")
+    @Operation(summary = "鍙樻洿棰嗘枡")
+    public R<Boolean> updatePick(@RequestBody ProductionOrderPickDto dto) {
+        return R.ok(productionOrderPickService.updatePick(dto));
+    }
+
+    @GetMapping("/detail/{productionOrderId}")
+    @Operation(summary = "鏌ヨ宸查鏂欒鎯�")
+    public R<List<ProductionOrderPickVo>> listPickedDetail(@PathVariable Long productionOrderId) {
+        return R.ok(productionOrderPickService.listPickedDetail(productionOrderId));
+    }
+}
+
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java
new file mode 100644
index 0000000..05e1a50
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderPickRecordController.java
@@ -0,0 +1,37 @@
+package com.ruoyi.production.controller;
+
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
+import com.ruoyi.production.service.ProductionOrderPickRecordService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 绾胯竟浠撳嚭鍏ュ簱璁板綍 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@RestController
+@RequestMapping("/productionOrderPickRecord")
+@Tag(name = "鐢熶骇璁㈠崟棰嗘枡璁板綍")
+@RequiredArgsConstructor
+public class ProductionOrderPickRecordController {
+
+    private final ProductionOrderPickRecordService productionOrderPickRecordService;
+
+    @GetMapping("/feeding")
+    @Operation(summary = "鏌ヨ琛ユ枡璁板綍")
+    public R<List<ProductionOrderPickRecordVo>> listFeedingRecord(ProductionOrderPickRecordDto dto) {
+        return R.ok(productionOrderPickRecordService.listFeedingRecord(dto));
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java
new file mode 100644
index 0000000..dda1aa0
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingController.java
@@ -0,0 +1,56 @@
+package com.ruoyi.production.controller;
+
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+import com.ruoyi.production.service.ProductionOrderRoutingOperationService;
+import com.ruoyi.production.service.ProductionOrderRoutingService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/productionOrderRouting")
+@Tag(name = "鐢熶骇璁㈠崟宸ヨ壓璺嚎")
+@RequiredArgsConstructor
+public class ProductionOrderRoutingController {
+
+    private final ProductionOrderRoutingService productionOrderRoutingService;
+    private final ProductionOrderRoutingOperationService productionOrderRoutingOperationService;
+
+    @GetMapping("list")
+    @Operation(summary = "鏍规嵁Id鏌ヨ宸ヨ壓璺嚎瀛愯〃")
+    public R list(Long orderId) {
+        return R.ok(productionOrderRoutingService.listItem(orderId));
+    }
+
+    @GetMapping("listMain")
+    @Operation(summary = "鏍规嵁Id鏌ヨ宸ヨ壓璺嚎涓昏〃")
+    public R listMain(Long orderId) {
+        return R.ok(productionOrderRoutingService.listMain(orderId));
+    }
+
+    @PostMapping("/addRouteItem")
+    @Operation(summary = "鏂板鐢熶骇璁㈠崟鐨勫伐鑹鸿矾绾胯鎯�")
+    public R addRouteItem(@RequestBody ProductionOrderRoutingOperation productionOrderRoutingOperation) {
+        return productionOrderRoutingOperationService.addRouteItem(productionOrderRoutingOperation);
+    }
+
+    @PostMapping("/updateRouteItem")
+    @Operation(summary = "淇敼鐢熶骇璁㈠崟鐨勫伐鑹鸿矾绾胯鎯�")
+    public R updateRouteItem(@RequestBody ProductionOrderRoutingOperation productionOrderRoutingOperation) {
+        return R.ok(productionOrderRoutingOperationService.updateById(productionOrderRoutingOperation));
+    }
+
+    @DeleteMapping("/deleteRouteItem/{id}")
+    @Operation(summary = "鍒犻櫎鐢熶骇宸ヨ壓璺嚎")
+    public R deleteRouteItem(@PathVariable("id") Long id) {
+        return productionOrderRoutingOperationService.deleteRouteItem(id);
+    }
+
+    @PostMapping("/sortRouteItem")
+    @Operation(summary = "鎺掑簭")
+    public R sortRouteItem(@RequestBody ProductionOrderRoutingOperation productionOrderRoutingOperation) {
+        return R.ok(productionOrderRoutingOperationService.sortRouteItem(productionOrderRoutingOperation));
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationController.java
new file mode 100644
index 0000000..d25de7b
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.production.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@RestController
+@RequestMapping("/productionOrderRoutingOperation")
+public class ProductionOrderRoutingOperationController {
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationParamController.java b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationParamController.java
new file mode 100644
index 0000000..fd229ef
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionOrderRoutingOperationParamController.java
@@ -0,0 +1,62 @@
+package com.ruoyi.production.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionOrderRoutingOperationParamDto;
+import com.ruoyi.production.bean.vo.ProductionOrderRoutingOperationParamVo;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import com.ruoyi.production.service.ProductionOrderRoutingOperationParamService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/productionOrderRoutingOperationParam")
+@Tag(name = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+@RequiredArgsConstructor
+public class ProductionOrderRoutingOperationParamController {
+
+    private final ProductionOrderRoutingOperationParamService productionOrderRoutingOperationParamService;
+
+    @GetMapping("/page")
+    @Operation(summary = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟鍒嗛〉鏌ヨ")
+    public R<IPage<ProductionOrderRoutingOperationParamVo>> page(Page<ProductionOrderRoutingOperationParamDto> page,
+                                                                 ProductionOrderRoutingOperationParamDto dto) {
+        return R.ok(productionOrderRoutingOperationParamService.pageProductionOrderRoutingOperationParam(page, dto));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟鍒楄〃")
+    public R<List<ProductionOrderRoutingOperationParamVo>> list(ProductionOrderRoutingOperationParamDto dto) {
+        return R.ok(productionOrderRoutingOperationParamService.listProductionOrderRoutingOperationParam(dto));
+    }
+
+    @GetMapping("/{id}")
+    @Operation(summary = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟璇︽儏")
+    public R<ProductionOrderRoutingOperationParamVo> getInfo(@PathVariable("id") Long id) {
+        return R.ok(productionOrderRoutingOperationParamService.getProductionOrderRoutingOperationParamInfo(id));
+    }
+
+    @PostMapping
+    @Operation(summary = "鏂板鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+    public R<Boolean> add(@RequestBody ProductionOrderRoutingOperationParam item) {
+        return R.ok(productionOrderRoutingOperationParamService.saveProductionOrderRoutingOperationParam(item));
+    }
+
+    @PutMapping
+    @Operation(summary = "淇敼鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+    public R<Boolean> edit(@RequestBody ProductionOrderRoutingOperationParam item) {
+        return R.ok(productionOrderRoutingOperationParamService.updateById(item));
+    }
+
+    @DeleteMapping("/{id}")
+    @Operation(summary = "鍒犻櫎鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+    public R<Boolean> remove(@PathVariable("id") Long id) {
+        return R.ok(productionOrderRoutingOperationParamService.removeProductionOrderRoutingOperationParam(id));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionPlanController.java b/src/main/java/com/ruoyi/production/controller/ProductionPlanController.java
new file mode 100644
index 0000000..6190a47
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionPlanController.java
@@ -0,0 +1,103 @@
+package com.ruoyi.production.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.ProductionPlanDto;
+import com.ruoyi.production.bean.dto.ProductionPlanImportDto;
+import com.ruoyi.production.bean.vo.ProductionPlanVo;
+import com.ruoyi.production.service.ProductionPlanService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁″垝琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 02:11:10
+ */
+@RestController
+@RequestMapping("/productionPlan")
+@RequiredArgsConstructor
+@Tag(name = "涓荤敓浜ц鍒�")
+public class ProductionPlanController {
+
+    private final ProductionPlanService productionPlanService;
+
+    @GetMapping("/listPage")
+    @Operation(summary = "鑾峰彇鐢熶骇璁″垝鍒楄〃")
+    public R<IPage<ProductionPlanVo>> productionPlanListPage(Page<ProductionPlanDto> page, ProductionPlanDto productionPlanDto) {
+        return R.ok(productionPlanService.listPage(page, productionPlanDto));
+    }
+
+    @PostMapping("/combine")
+    @Log(title = "鍚堝苟鐢熶骇璁″垝", businessType = BusinessType.INSERT)
+    @Operation(summary = "鍚堝苟鐢熶骇璁″垝")
+    public R combine(@RequestBody ProductionPlanDto productionPlanDto) {
+        if (productionPlanDto.getIds() == null || productionPlanDto.getIds().isEmpty()) {
+            return R.fail("璇烽�夋嫨瑕佷笅鍙戠殑鐢熶骇璁″垝");
+        }
+
+        if (productionPlanDto.getTotalAssignedQuantity() == null || productionPlanDto.getTotalAssignedQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+            return R.fail("璇疯緭鍏ヤ笅鍙戞暟閲�");
+        }
+        return R.ok(productionPlanService.combine(productionPlanDto));
+    }
+
+    @PostMapping("addProductionPlan")
+    @Log(title = "鍒涘缓鐢熶骇璁″垝", businessType = BusinessType.INSERT)
+    @Operation(summary = "鍒涘缓鐢熶骇璁″垝")
+    public R add(@RequestBody ProductionPlanDto productionPlanDto) {
+        return R.ok(productionPlanService.add(productionPlanDto));
+    }
+
+    @PutMapping("updateProductionPlan")
+    @Log(title = "鏇存柊鐢熶骇璁″垝", businessType = BusinessType.UPDATE)
+    @Operation(summary = "鏇存柊鐢熶骇璁″垝")
+    public R update(@RequestBody ProductionPlanDto productionPlanDto) {
+        return R.ok(productionPlanService.update(productionPlanDto));
+    }
+
+    @DeleteMapping("deleteProductionPlan")
+    @Log(title = "鍒犻櫎鐢熶骇璁″垝", businessType = BusinessType.DELETE)
+    @Operation(summary = "鍒犻櫎鐢熶骇璁″垝")
+    public R delete(@RequestBody List<Long> ids) {
+        return R.ok(productionPlanService.delete(ids));
+    }
+
+    @PostMapping("/downloadTemplate")
+    @Log(title = "涓嬭浇涓荤敓浜ц鍒掑鍏ユā鏉�", businessType = BusinessType.EXPORT)
+    @Operation(summary = "涓嬭浇涓荤敓浜ц鍒掑鍏ユā鏉�")
+    public void importTemplate(HttpServletResponse response) {
+        ExcelUtil<ProductionPlanImportDto> excelUtil = new ExcelUtil<>(ProductionPlanImportDto.class);
+        excelUtil.importTemplateExcel(response, "涓荤敓浜ц鍒掑鍏ユā鏉�");
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "涓荤敓浜ц鍒掓暟鎹鍏�")
+    @Log(title = "涓荤敓浜ц鍒掓暟鎹鍏�", businessType = BusinessType.IMPORT)
+    public R importProdData(@RequestParam("file") MultipartFile file) {
+        productionPlanService.importProdData(file);
+        return R.ok("瀵煎叆鎴愬姛");
+    }
+
+    @PostMapping("/export")
+    @Operation(summary = "涓荤敓浜ц鍒掓暟鎹鍑�")
+    @Log(title = "涓荤敓浜ц鍒掓暟鎹鍑�", businessType = BusinessType.EXPORT)
+    public void exportProdData(HttpServletResponse response, @RequestBody(required = false) List<Long> ids) {
+        productionPlanService.exportProdData(response, ids);
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java b/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java
index b4bf7dc..7f61dbf 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionProductInputController.java
@@ -2,23 +2,23 @@
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductionProductInputDto;
+import com.ruoyi.production.bean.dto.ProductionProductInputDto;
 import com.ruoyi.production.service.ProductionProductInputService;
-import io.swagger.annotations.Api;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-@RequestMapping("productionProductInput")
+@RequestMapping("/productionProductInput")
 @RestController
-@Api(value = "鐢熶骇鎶曞叆")
+@Tag(name = "鐢熶骇鎶曞叆")
+@AllArgsConstructor
 public class ProductionProductInputController {
 
-    @Autowired
     private ProductionProductInputService productionProductInputService;
 
-    @GetMapping("listPage")
+    @GetMapping("/listPage")
     public R page(Page<ProductionProductInputDto> page, ProductionProductInputDto productionProductInputDto) {
         return R.ok(productionProductInputService.listPageProductionProductInputDto(page, productionProductInputDto));
     }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java b/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
index e4a0813..926a59f 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionProductMainController.java
@@ -3,26 +3,23 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductProcessRouteItemDto;
-import com.ruoyi.production.dto.ProductionProductMainDto;
-import com.ruoyi.production.dto.SalesLedgerProductionAccountingDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
 import com.ruoyi.production.service.ProductionProductMainService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
-import java.util.Arrays;
 import java.util.List;
 
-@RequestMapping("productionProductMain")
+@RequestMapping("/productionProductMain")
 @RestController
-@Api(value = "鐢熶骇鎶ュ伐")
+@Tag(name = "鐢熶骇鎶ュ伐")
+@AllArgsConstructor
 public class ProductionProductMainController {
 
-    @Autowired
     private ProductionProductMainService productionProductMainService;
 
     /**
@@ -31,9 +28,21 @@
      * @param productionProductMainDto
      * @return
      */
-    @GetMapping("listPage")
+    @GetMapping("/listPage")
     public R page(Page<ProductionProductMainDto> page, ProductionProductMainDto productionProductMainDto) {
         return R.ok(productionProductMainService.listPageProductionProductMainDto(page, productionProductMainDto));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "鐢熶骇鎶ュ伐鍒嗛〉鏌ヨ")
+    public R pageProductionProductMain(Page<ProductionProductMainDto> page, ProductionProductMainDto productionProductMainDto) {
+        return R.ok(productionProductMainService.pageProductionProductMain(page, productionProductMainDto));
+    }
+
+    @GetMapping("/{id}")
+    @Operation(summary = "鐢熶骇鎶ュ伐璇︽儏")
+    public R getInfo(@PathVariable("id") Long id) {
+        return R.ok(productionProductMainService.getProductionProductMainInfo(id));
     }
 
     /**
@@ -41,17 +50,36 @@
      * @param productionProductMainDto
      * @return
      */
-    @PostMapping("addProductMain")
+    @PostMapping("/addProductMain")
+    @PreAuthorize("@ss.hasPermi('productionProductMain:add')")
     public R addProductMain(@RequestBody ProductionProductMainDto productionProductMainDto) {
         return R.ok(productionProductMainService.addProductMain(productionProductMainDto));
     }
 
-    @ApiOperation("鍒犻櫎鎶ュ伐")
+    @PostMapping
+    @Operation(summary = "鏂板鐢熶骇鎶ュ伐")
+    public R add(@RequestBody ProductionProductMainDto productionProductMainDto) {
+        return R.ok(productionProductMainService.saveProductionProductMain(productionProductMainDto));
+    }
+
+    @PutMapping
+    @Operation(summary = "淇敼鐢熶骇鎶ュ伐")
+    public R edit(@RequestBody ProductionProductMainDto productionProductMainDto) {
+        return R.ok(productionProductMainService.saveProductionProductMain(productionProductMainDto));
+    }
+
+    @Operation(summary = "鍒犻櫎鎶ュ伐")
     @DeleteMapping("/delete")
     public R delete(@RequestBody ProductionProductMainDto productionProductMainDto) {
         return R.ok(productionProductMainService.removeProductMain(productionProductMainDto.getId()));
     }
 
+    @DeleteMapping("/{id}")
+    @Operation(summary = "鍒犻櫎鐢熶骇鎶ュ伐")
+    public R remove(@PathVariable("id") Long id) {
+        return R.ok(productionProductMainService.removeProductMain(id));
+    }
+
 
     /**
      * 瀵煎嚭
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionProductOutputController.java b/src/main/java/com/ruoyi/production/controller/ProductionProductOutputController.java
index ca9c1e8..2d3fe80 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductionProductOutputController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductionProductOutputController.java
@@ -2,22 +2,20 @@
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductionProductInputDto;
-import com.ruoyi.production.dto.ProductionProductOutputDto;
-import com.ruoyi.production.service.ProductionProductInputService;
+import com.ruoyi.production.bean.dto.ProductionProductOutputDto;
 import com.ruoyi.production.service.ProductionProductOutputService;
-import io.swagger.annotations.Api;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 @RequestMapping("productionProductOutput")
 @RestController
-@Api(value = "鐢熶骇浜у嚭")
+@Tag(name = "鐢熶骇浜у嚭")
+@AllArgsConstructor
 public class ProductionProductOutputController {
 
-    @Autowired
     private ProductionProductOutputService productionProductOutputService;
 
     @GetMapping("listPage")
diff --git a/src/main/java/com/ruoyi/production/controller/SalesLedgerProductionAccountingController.java b/src/main/java/com/ruoyi/production/controller/SalesLedgerProductionAccountingController.java
deleted file mode 100644
index 02d36c8..0000000
--- a/src/main/java/com/ruoyi/production/controller/SalesLedgerProductionAccountingController.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductOrderDto;
-import com.ruoyi.production.dto.SalesLedgerProductionAccountingDto;
-import com.ruoyi.production.dto.UserProductionAccountingDto;
-import com.ruoyi.production.pojo.SalesLedgerProductionAccounting;
-import com.ruoyi.production.service.SalesLedgerProductionAccountingService;
-import com.ruoyi.production.service.impl.SalesLedgerProductionAccountingServiceImpl;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiModelProperty;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:43
- */
-@RestController
-@Api(tags = "鐢熶骇鏍哥畻")
-@RequestMapping("/salesLedger/productionAccounting")
-public class SalesLedgerProductionAccountingController extends BaseController {
-
-    @Autowired
-    private SalesLedgerProductionAccountingService salesLedgerProductionAccountingService;
-
-    @GetMapping("/listPage")
-    @ApiOperation("鐢熶骇鏍哥畻-鍒嗛〉鏌ヨ")
-    @Log(title = "鐢熶骇鏍哥畻-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    public AjaxResult listPage(Page page, SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto) {
-        IPage<SalesLedgerProductionAccountingDto> list = salesLedgerProductionAccountingService.listPage(page, salesLedgerProductionAccountingDto);
-        return AjaxResult.success(list);
-    }
-
-    /**
-     * 瀵煎嚭
-     */
-    @PostMapping("/export")
-    public void export(HttpServletResponse response, SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto) {
-        List<SalesLedgerProductionAccountingDto> list;
-        list = salesLedgerProductionAccountingService.listPage(new Page<>(1, -1), salesLedgerProductionAccountingDto).getRecords();
-        ExcelUtil<SalesLedgerProductionAccountingDto> util = new ExcelUtil<SalesLedgerProductionAccountingDto>(SalesLedgerProductionAccountingDto.class);
-        util.exportExcel(response, list, "鐢熶骇鏍哥畻鏁版嵁");
-    }
-//----------------------------------------------------------------------------------------------------------------------------------------------------
-    @GetMapping("/page")
-    @ApiModelProperty("鏌ヨ宸ヤ汉鐢熶骇宸ヨ祫淇℃伅")
-    public R pageProductionAccounting(SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page){
-        return R.ok(salesLedgerProductionAccountingService.pageProductionAccounting(salesLedgerProductionAccountingDto, page));
-    }
-
-    @GetMapping("/listProductionDetails")
-    @ApiModelProperty("鏌ヨ宸ヤ汉鐢熶骇宸ヨ祫淇℃伅")
-    public R listProductionDetails(SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page){
-        return R.ok(salesLedgerProductionAccountingService.listProductionDetails(salesLedgerProductionAccountingDto,page));
-    }
-
-    @GetMapping("getByUserId")
-    @ApiModelProperty("鏌ヨ宸ヤ汉鐢熶骇宸ヨ祫淇℃伅")
-    public R getByUserId(UserProductionAccountingDto userProductionAccountingDto){
-        return R.ok(salesLedgerProductionAccountingService.getByUserId(userProductionAccountingDto));
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/controller/SalesLedgerSchedulingController.java b/src/main/java/com/ruoyi/production/controller/SalesLedgerSchedulingController.java
deleted file mode 100644
index 907cd44..0000000
--- a/src/main/java/com/ruoyi/production/controller/SalesLedgerSchedulingController.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package com.ruoyi.production.controller;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.aspectj.lang.annotation.Log;
-import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.procurementrecord.dto.ProcurementDto;
-import com.ruoyi.production.dto.ProcessSchedulingDto;
-import com.ruoyi.production.dto.ProductionDispatchAddDto;
-import com.ruoyi.production.dto.SalesLedgerSchedulingDto;
-import com.ruoyi.production.dto.SalesLedgerSchedulingProcessDto;
-import com.ruoyi.production.mapper.SpeculativeTradingInfoMapper;
-import com.ruoyi.production.pojo.SpeculativeTradingInfo;
-import com.ruoyi.production.service.impl.SalesLedgerSchedulingServiceImpl;
-import com.ruoyi.sales.mapper.LossMapper;
-import com.ruoyi.sales.pojo.Loss;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:43
- */
-@RestController
-@Api(tags = "鐢熶骇璁㈠崟")
-@RequestMapping("/salesLedger/scheduling")
-@Deprecated // 鏍囪璇ョ被宸插純鐢�
-public class SalesLedgerSchedulingController extends BaseController {
-
-    @Autowired
-    private SalesLedgerSchedulingServiceImpl salesLedgerSchedulingService;
-
-
-    @Autowired
-    private SpeculativeTradingInfoMapper speculativeTradingInfoMapper;
-
-    @Autowired
-    private LossMapper lossMapper;
-
-    @GetMapping("/loss")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇娲惧伐-鎹熻�楃巼", businessType = BusinessType.OTHER)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇娲惧伐-鎹熻�楃巼")
-    public AjaxResult loss() {
-        return AjaxResult.success(lossMapper.selectOne(new LambdaQueryWrapper<Loss>().last("limit 1")));
-    }
-
-    @PostMapping("/addLoss")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇娲惧伐-娣诲姞鎹熻�楃巼", businessType = BusinessType.INSERT)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇娲惧伐-娣诲姞鎹熻�楃巼")
-    public AjaxResult addLoss(@RequestBody Loss loss) {
-        lossMapper.insert(loss);
-        return AjaxResult.success("娣诲姞鎹熻�楃巼鎴愬姛");
-    }
-
-    @PostMapping("/updateLoss")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇娲惧伐-淇敼鎹熻�楃巼", businessType = BusinessType.UPDATE)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇娲惧伐-淇敼鎹熻�楃巼")
-    public AjaxResult updateLoss(@RequestBody Loss loss) {
-        lossMapper.updateById(loss);
-        return AjaxResult.success("淇敼鎹熻�楃巼鎴愬姛");
-    }
-
-    @GetMapping("/list")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇娲惧伐-鐐掓満淇℃伅", businessType = BusinessType.OTHER)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇娲惧伐-鐐掓満淇℃伅")
-    public AjaxResult list() {
-        List<SpeculativeTradingInfo> result = speculativeTradingInfoMapper.selectList(null);
-        result.forEach(item -> {
-            item.setCurrentWorkLoad(salesLedgerSchedulingService.getSchedulingNumBySpeculativeTradingName(item.getName()).divide(new BigDecimal(1000),2, RoundingMode.CEILING));
-            item.setVacant(item.getWorkLoad().subtract(item.getCurrentWorkLoad()).setScale(2, RoundingMode.HALF_UP)); //淇濈暀涓や綅灏忔暟
-        });
-        return AjaxResult.success(result);
-    }
-
-    @PostMapping("/addSpeculatTrading")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇娲惧伐-娣诲姞鐐掓満淇℃伅", businessType = BusinessType.INSERT)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇娲惧伐-娣诲姞鐐掓満淇℃伅")
-    public AjaxResult addSpeculatTrading(@RequestBody List<SpeculativeTradingInfo> speculativeTradingInfo) {
-        if(CollectionUtils.isEmpty(speculativeTradingInfo)) return AjaxResult.error("鏁版嵁缁勪笉鑳戒负绌�");
-        speculativeTradingInfo.forEach(item -> {
-            speculativeTradingInfoMapper.insert(item);
-        });
-        return AjaxResult.success("娣诲姞鐐掓満淇℃伅鎴愬姛");
-    }
-
-    @PostMapping("/updateSpeculatTrading")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇娲惧伐-淇敼鐐掓満淇℃伅", businessType = BusinessType.UPDATE)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇娲惧伐-淇敼鐐掓満淇℃伅")
-    public AjaxResult updateSpeculatTrading(@RequestBody List<SpeculativeTradingInfo> speculativeTradingInfo) {
-        if(CollectionUtils.isEmpty(speculativeTradingInfo)) return AjaxResult.error("鏁版嵁缁勪笉鑳戒负绌�");
-        speculativeTradingInfo.forEach(item -> {
-            speculativeTradingInfoMapper.updateById(item);
-        });
-        return AjaxResult.success("淇敼鐐掓満淇℃伅鎴愬姛");
-    }
-
-
-    @GetMapping("/listPage")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇璁㈠崟-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇璁㈠崟-鍒嗛〉鏌ヨ")
-    public AjaxResult listPage(Page page, SalesLedgerSchedulingDto salesLedgerSchedulingDto) {
-        IPage<SalesLedgerSchedulingDto> result = salesLedgerSchedulingService.listPage(page,salesLedgerSchedulingDto);
-        return AjaxResult.success(result);
-    }
-
-    /**
-     * 瀵煎嚭
-     * @param response
-     */
-    @PostMapping("/export")
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇璁㈠崟-瀵煎嚭")
-    public void export(HttpServletResponse response) {
-        salesLedgerSchedulingService.export(response);
-    }
-
-
-    /**
-     * 瀵煎嚭
-     * @param response
-     */
-    @PostMapping("/exportOne")
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇娲惧伐-瀵煎嚭")
-    public void exportOne(HttpServletResponse response) {
-        salesLedgerSchedulingService.exportOne(response);
-    }
-
-    @PostMapping("/productionDispatch")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇璁㈠崟-鐢熶骇娲惧伐", businessType = BusinessType.INSERT)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇璁㈠崟-鐢熶骇娲惧伐")
-    @Transactional(rollbackFor = Exception.class)
-    public AjaxResult productionDispatch(@RequestBody ProductionDispatchAddDto productionDispatchAddDto) {
-        List<ProductionDispatchAddDto> productionDispatchAddDtoList = new ArrayList<>();
-        productionDispatchAddDtoList.add(productionDispatchAddDto);
-        String result = salesLedgerSchedulingService.productionDispatch(productionDispatchAddDtoList);
-        return AjaxResult.success(result);
-    }
-
-    @PostMapping("/productionDispatchList")
-    @Log(title = "鐢熶骇绠$悊-鐢熶骇璁㈠崟-鑷姩娲惧伐", businessType = BusinessType.INSERT)
-    @ApiOperation("鐢熶骇绠$悊-鐢熶骇璁㈠崟-鑷姩娲惧伐")
-    @Transactional(rollbackFor = Exception.class)
-    public AjaxResult productionDispatchList(@RequestBody List<ProductionDispatchAddDto> productionDispatchAddDto) {
-        String result = salesLedgerSchedulingService.productionDispatch(productionDispatchAddDto);
-        return AjaxResult.success(result);
-    }
-
-    @GetMapping("/listPageProcess")
-    @Log(title = "鐢熶骇绠$悊-宸ュ簭鎺掍骇-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-    @ApiOperation("鐢熶骇绠$悊-宸ュ簭鎺掍骇-鍒嗛〉鏌ヨ")
-    public AjaxResult listPageProcess(Page page, SalesLedgerSchedulingProcessDto salesLedgerSchedulingDto) {
-        IPage<SalesLedgerSchedulingProcessDto> result = salesLedgerSchedulingService.listPageProcess(page,salesLedgerSchedulingDto);
-        return AjaxResult.success(result);
-    }
-
-    /**
-     * 瀵煎嚭
-     * @param response
-     */
-    @PostMapping("/exportTwo")
-    @ApiOperation("鐢熶骇绠$悊-宸ュ簭鎺掍骇-瀵煎嚭")
-    public void exportTwo(HttpServletResponse response) {
-        Page page = new Page(-1,-1);
-        SalesLedgerSchedulingProcessDto salesLedgerSchedulingDto = new SalesLedgerSchedulingProcessDto();
-        IPage<SalesLedgerSchedulingProcessDto> result = salesLedgerSchedulingService.listPageProcess(page,salesLedgerSchedulingDto);
-        result.getRecords().forEach(item -> {
-            item.setStatusName(item.getStatus().toString());
-        });
-        ExcelUtil<SalesLedgerSchedulingProcessDto> util = new ExcelUtil<>(SalesLedgerSchedulingProcessDto.class);
-        util.exportExcel(response, result.getRecords(), "宸ュ簭鎺掍骇");
-    }
-
-
-    @DeleteMapping("/productionDispatchDelete")
-    @Log(title = "鐢熶骇绠$悊-宸ュ簭鎺掍骇-鍙栨秷鎺掍骇", businessType = BusinessType.DELETE)
-    @ApiOperation("鐢熶骇绠$悊-宸ュ簭鎺掍骇-鍙栨秷鎺掍骇")
-    @Transactional(rollbackFor = Exception.class)
-    public AjaxResult productionDispatchDelete(@RequestBody List<Long> ids) {
-        int result = salesLedgerSchedulingService.productionDispatchDelete(ids);
-        return AjaxResult.success(result);
-    }
-
-
-    @PostMapping("/processScheduling")
-    @Log(title = "鐢熶骇绠$悊-宸ュ簭鎺掍骇", businessType = BusinessType.INSERT)
-    @ApiOperation("鐢熶骇绠$悊-宸ュ簭鎺掍骇")
-    @Transactional(rollbackFor = Exception.class)
-    public AjaxResult processScheduling(@RequestBody List<ProcessSchedulingDto> processSchedulingDto) {
-        int result = salesLedgerSchedulingService.processScheduling(processSchedulingDto);
-        return AjaxResult.success(result);
-    }
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/controller/SalesLedgerWorkController.java b/src/main/java/com/ruoyi/production/controller/SalesLedgerWorkController.java
deleted file mode 100644
index bd3610c..0000000
--- a/src/main/java/com/ruoyi/production/controller/SalesLedgerWorkController.java
+++ /dev/null
@@ -1,92 +0,0 @@
-//package com.ruoyi.production.controller;
-//
-//import com.baomidou.mybatisplus.core.metadata.IPage;
-//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-//import com.ruoyi.common.utils.poi.ExcelUtil;
-//import com.ruoyi.framework.aspectj.lang.annotation.Log;
-//import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
-//import com.ruoyi.framework.web.controller.BaseController;
-//import com.ruoyi.framework.web.domain.AjaxResult;
-//import com.ruoyi.production.dto.ProcessSchedulingDto;
-//import com.ruoyi.production.dto.ProductionReportDto;
-//import com.ruoyi.production.dto.SalesLedgerSchedulingProcessDto;
-//import com.ruoyi.production.dto.SalesLedgerWorkDto;
-//import com.ruoyi.production.pojo.SalesLedgerWork;
-//import com.ruoyi.production.service.SalesLedgerWorkService;
-//import io.swagger.annotations.Api;
-//import io.swagger.annotations.ApiOperation;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.transaction.annotation.Transactional;
-//import org.springframework.web.bind.annotation.*;
-//
-//import javax.servlet.http.HttpServletResponse;
-//import java.util.List;
-//
-///**
-// * @author :yys
-// * @date : 2025/7/21 14:43
-// */
-//@RestController
-//@Api(tags = "鐢熶骇鎶ュ伐(鎺掍骇璁板綍)")
-//@RequestMapping("/salesLedger/work")
-//@Deprecated // 鏍囪璇ョ被宸插純鐢�
-//public class SalesLedgerWorkController extends BaseController {
-//
-//
-//    @Autowired
-//    private SalesLedgerWorkServiceImpl salesLedgerWorkService;
-//
-//    @GetMapping("/listPage")
-//    @Log(title = "鐢熶骇鎶ュ伐-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
-//    @ApiOperation("鐢熶骇鎶ュ伐-鍒嗛〉鏌ヨ")
-//    public AjaxResult listPage(Page page, SalesLedgerWorkDto salesLedgerWorkDto) {
-//        IPage<SalesLedgerWorkDto> listPage = salesLedgerWorkService.listPage(page, salesLedgerWorkDto);
-//        return AjaxResult.success(listPage);
-//    }
-//
-//    /**
-//     * 瀵煎嚭
-//     * @param response
-//     */
-//    @PostMapping("/export")
-//    @ApiOperation("鐢熶骇绠$悊-鐢熶骇鎶ュ伐-瀵煎嚭")
-//    public void export(HttpServletResponse response) {
-//        Page page = new Page(-1,-1);
-//        SalesLedgerWorkDto salesLedgerSchedulingDto = new SalesLedgerWorkDto();
-//        IPage<SalesLedgerWorkDto> result = salesLedgerWorkService.listPage(page,salesLedgerSchedulingDto);
-//        result.getRecords().forEach(item -> {
-//            item.setDaiNum(item.getFinishedNum().subtract(item.getSchedulingNum()));
-//            item.setStatusName(item.getStatus().toString());
-//        });
-//        ExcelUtil<SalesLedgerWorkDto> util = new ExcelUtil<>(SalesLedgerWorkDto.class);
-//        util.exportExcel(response, result.getRecords(), "宸ュ簭鎺掍骇");
-//    }
-//
-//    @GetMapping("/list")
-//    @Log(title = "鐢熶骇鎶ュ伐-鏌ヨ", businessType = BusinessType.OTHER)
-//    @ApiOperation("鐢熶骇鎶ュ伐-鏌ヨ")
-//    public AjaxResult list(@RequestParam("id") Long id) {
-//        List<ProductionReportDto> list = salesLedgerWorkService.getList(id);
-//        return AjaxResult.success(list);
-//    }
-//
-//    @PostMapping("/productionReport")
-//    @Log(title = "鐢熶骇绠$悊-鐢熶骇鎶ュ伐", businessType = BusinessType.INSERT)
-//    @ApiOperation("鐢熶骇绠$悊-鐢熶骇鎶ュ伐")
-//    @Transactional(rollbackFor = Exception.class)
-//    public AjaxResult productionReport(@RequestBody ProductionReportDto productionReportDto) {
-//        int result = salesLedgerWorkService.productionReport(productionReportDto);
-//        return AjaxResult.success(result);
-//    }
-//
-//
-//    @PostMapping("/productionReportUpdate")
-//    @Log(title = "鐢熶骇绠$悊-鐢熶骇鎶ュ伐-淇敼", businessType = BusinessType.UPDATE)
-//    @ApiOperation("鐢熶骇绠$悊-鐢熶骇鎶ュ伐-淇敼")
-//    @Transactional(rollbackFor = Exception.class)
-//    public AjaxResult productionReportUpdate(@RequestBody ProductionReportDto productionReportDto) {
-//        int result = salesLedgerWorkService.productionReportUpdate(productionReportDto);
-//        return AjaxResult.success(result);
-//    }
-//
-//}
diff --git a/src/main/java/com/ruoyi/production/dto/BomImportDto.java b/src/main/java/com/ruoyi/production/dto/BomImportDto.java
deleted file mode 100644
index 0cea81a..0000000
--- a/src/main/java/com/ruoyi/production/dto/BomImportDto.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-@Data
-public class BomImportDto {
-
-    @Excel(name = "鐖堕」浜у搧缂栧彿")
-    private String parentCode;
-
-    @Excel(name = "鐖堕」浜у搧鍚嶇О")
-    private String parentName;
-
-    @Excel(name = "鐖堕」浜у搧瑙勬牸")
-    private String parentSpec;
-
-    @Excel(name = "瀛愰」浜у搧缂栧彿")
-    private String childCode;
-
-    @Excel(name = "瀛愰」浜у搧鍚嶇О")
-    private String childName;
-
-    @Excel(name = "瀛愰」浜у搧瑙勬牸")
-    private String childSpec;
-
-    @Excel(name = "鍗曚綅鐢ㄩ噺")
-    private BigDecimal unitQty;
-
-    @Excel(name = "鎶曟枡宸ュ簭")
-    private String process;
-
-    @Excel(name = "澶囨敞")
-    private String remark;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/DaiDto.java b/src/main/java/com/ruoyi/production/dto/DaiDto.java
deleted file mode 100644
index 86853cb..0000000
--- a/src/main/java/com/ruoyi/production/dto/DaiDto.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * @author :yys
- * @date : 2025/11/3 9:35
- */
-@Data
-public class DaiDto{
-
-    @Excel(name = "寰呮帓鏁伴噺")
-    private BigDecimal daiNum;
-
-    @ApiModelProperty(value = "閿�鍞骇鍝両D")
-    private Long salesLedgerProductId;
-
-    @ApiModelProperty(value = "閿�鍞彴璐D")
-    private Long salesLedgerId;
-
-    /**
-     * 閿�鍞悎鍚屽彿
-     */
-    @Excel(name = "閿�鍞悎鍚屽彿")
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
-    private String salesContractNo;
-
-    /**
-     * 瀹㈡埛鍚堝悓鍙�
-     */
-    @Excel(name = "瀹㈡埛鍚堝悓鍙�")
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
-    private String customerContractNo;
-
-    /**
-     * 椤圭洰鍚嶇О
-     */
-    @Excel(name = "椤圭洰鍚嶇О")
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
-    private String projectName;
-
-    /**
-     * 褰曞叆鏃ユ湡
-     */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "褰曞叆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "褰曞叆鏃ユ湡")
-    private Date entryDate;
-
-    @ApiModelProperty(value = "褰曞叆鏃ユ湡寮�濮�")
-    private String entryDateStart;
-
-    @ApiModelProperty(value = "褰曞叆鏃ユ湡缁撴潫")
-    private String entryDateEnd;
-
-    /**
-     * 瀹㈡埛鍚嶇О
-     */
-    @Excel(name = "瀹㈡埛鍚嶇О")
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
-    private String customerName;
-
-
-    /**
-     * 浜у搧澶х被
-     */
-    @Excel(name = "浜у搧澶х被")
-    @ApiModelProperty(value = "浜у搧澶х被")
-    private String productCategory;
-
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
-    @Excel(name = "瑙勬牸鍨嬪彿")
-    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
-    private String specificationModel;
-
-    /**
-     * 鍗曚綅
-     */
-    @Excel(name = "鍗曚綅")
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-
-    /**
-     * 鏁伴噺
-     */
-    @Excel(name = "鏁伴噺")
-    @ApiModelProperty(value = "鏁伴噺")
-    private BigDecimal quantity;
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    @Excel(name = "鎺掍骇鏁伴噺")
-    @ApiModelProperty(value = "鎺掍骇鏁伴噺")
-    private BigDecimal schedulingNum;
-
-    @ApiModelProperty(value = "绉熸埛ID")
-    private Long tenantId;
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProcessRouteDto.java b/src/main/java/com/ruoyi/production/dto/ProcessRouteDto.java
deleted file mode 100644
index 232a00c..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProcessRouteDto.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.production.pojo.ProcessRoute;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-@Data
-public class ProcessRouteDto extends ProcessRoute {
-
-    private Long productId;
-
-    private String productName;
-
-    @ApiModelProperty("瑙勬牸")
-    private String model;
-
-    private String bomNo;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProcessRouteItemDto.java b/src/main/java/com/ruoyi/production/dto/ProcessRouteItemDto.java
deleted file mode 100644
index 705354c..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProcessRouteItemDto.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class ProcessRouteItemDto extends ProcessRouteItem {
-
-    @ApiModelProperty(value = "宸ュ簭鍚嶇О")
-    private String processName;
-
-    @ApiModelProperty(value = "宸ヨ壓璺嚎鍚嶇О")
-    private String routeName;
-
-    @ApiModelProperty(value = "鐢熶骇鐐掓満")
-    private String speculativeTradingName;
-
-    @ApiModelProperty(value = "浜у搧鍚嶇О")
-    private String productName;
-
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-
-    private Long productId;
-
-
-    private String model;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProcessSchedulingDto.java b/src/main/java/com/ruoyi/production/dto/ProcessSchedulingDto.java
deleted file mode 100644
index 1143abd..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProcessSchedulingDto.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.ruoyi.production.dto;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * @author :yys
- * @date : 2025/7/22 9:19
- */
-@Data
-@ApiModel
-public class ProcessSchedulingDto {
-
-    private Long id;
-
-    /**
-     * 鎺掍骇浜篿d
-     */
-    @ApiModelProperty(value = "鎺掍骇浜篿d")
-    private Long schedulingUserId;
-
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    @ApiModelProperty(value = "鎺掍骇鏁伴噺")
-    private BigDecimal schedulingNum;
-
-    /**
-     * 宸ユ椂瀹氶
-     */
-    @ApiModelProperty(value = "宸ユ椂瀹氶")
-    private BigDecimal workHours;
-
-    /**
-     * 浜х嚎
-     */
-    @ApiModelProperty(value = "浜х嚎")
-    private String productionLine;
-
-    /**
-     * 宸ュ簭
-     */
-    @ApiModelProperty(value = "宸ュ簭")
-    private String process;
-
-
-    /**
-     * 鎺掍骇鏃ユ湡
-     */
-    @ApiModelProperty(value = "鎺掍骇鏃ユ湡")
-    private String schedulingDate;
-
-    /**
-     * 澶囨敞
-     */
-    @ApiModelProperty(value = "澶囨敞")
-    private String remark;
-
-    /**
-     * 鎹熻��
-     */
-    @ApiModelProperty(value = "鎹熻��")
-    private String loss;
-
-    /**
-     * 鍙e懗鍒嗙被
-     */
-    @ApiModelProperty(value = "鍙e懗鍒嗙被")
-    private String type;
-
-    /**
-     * 棰嗙敤
-     */
-    @ApiModelProperty(value = "棰嗙敤")
-    private String receive;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductBomDto.java b/src/main/java/com/ruoyi/production/dto/ProductBomDto.java
deleted file mode 100644
index ab695ca..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductBomDto.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.production.pojo.ProductBom;
-import lombok.Data;
-
-import java.util.List;
-
-//鍒嗛〉鏌ヨ鍥炴樉鏁版嵁
-@Data
-public class ProductBomDto extends ProductBom {
-
-    //浜у搧鍚嶇О
-    private String productName;
-
-    //浜у搧瑙勬牸鍨嬪彿
-    private String productModelName;
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java b/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
deleted file mode 100644
index dc2185a..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.production.pojo.ProductOrder;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-@Data
-@ExcelIgnoreUnannotated
-public class ProductOrderDto extends ProductOrder {
-
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
-    @Excel(name = "閿�鍞悎鍚屽彿")
-    private String salesContractNo;
-
-    @ApiModelProperty(value = "椤圭洰鍚�")
-    @Excel(name = "椤圭洰鍚�")
-    private String projectName;
-
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
-    @Excel(name = "瀹㈡埛鍚嶇О")
-    private String customerName;
-
-    @ApiModelProperty(value = "浜у搧鍚嶇О")
-    @Excel(name = "浜у搧鍚嶇О")
-    private String productCategory;
-
-    @ApiModelProperty(value = "瑙勬牸")
-    @Excel(name = "瑙勬牸")
-    private String specificationModel;
-
-    @ApiModelProperty(value = "宸ヨ壓璺嚎缂栧彿")
-    @Excel(name = "宸ヨ壓璺嚎缂栧彿")
-    private String processRouteCode;
-
-    @ApiModelProperty(value = "瀹屾垚杩涘害")
-    @Excel(name = "瀹屾垚杩涘害", suffix = "%")
-    private BigDecimal completionStatus;
-
-    @ApiModelProperty(value = "BOM缂栧彿")
-    @Excel(name = "BOM缂栧彿")
-    private String bomNo;
-
-    @ApiModelProperty(value = "浜ゆ湡鍋忓樊")
-    private Integer deliveryDaysDiff;
-
-    @ApiModelProperty(value = "浜ゆ湡")
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate deliveryDate;
-
-    //鏄惁鍙戣揣(鍙拌处椤甸潰棰滆壊鎺у埗)
-    private Boolean isFh;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductProcessDto.java b/src/main/java/com/ruoyi/production/dto/ProductProcessDto.java
deleted file mode 100644
index 7383a82..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductProcessDto.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.production.pojo.ProductProcess;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-@Data
-@ApiModel
-public class ProductProcessDto extends ProductProcess {
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductProcessRouteItemDto.java b/src/main/java/com/ruoyi/production/dto/ProductProcessRouteItemDto.java
deleted file mode 100644
index d6ec3f1..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductProcessRouteItemDto.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import com.ruoyi.production.pojo.ProductProcessRouteItem;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class ProductProcessRouteItemDto extends ProductProcessRouteItem {
-
-    @ApiModelProperty(value = "宸ュ簭鍚嶇О")
-    private String processName;
-
-    @ApiModelProperty(value = "浜у搧鍚嶇О")
-    private String productCategory;
-
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-
-    private Long productId;
-
-    private String productName;
-
-    private String model;
-
-    private Boolean isComplete;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductStructureDto.java b/src/main/java/com/ruoyi/production/dto/ProductStructureDto.java
deleted file mode 100644
index ec43eef..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductStructureDto.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.ruoyi.production.pojo.ProductStructure;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.util.List;
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class ProductStructureDto extends ProductStructure {
-
-    @ApiModelProperty(value = "宸ヨ壓鍚嶇О")
-    private String processName;
-
-    @ApiModelProperty(value = "浜у搧鍚嶇О")
-    private String productName;
-
-    @ApiModelProperty(value = "浜у搧id")
-    private Long productId;
-
-    private String model;
-
-    @TableField(exist = false)
-    private String tempId;
-
-    @TableField(exist = false)
-    private String parentTempId;
-
-    @TableField(exist = false)
-    private List<ProductStructureDto> children;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java b/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
deleted file mode 100644
index 6e2ca95..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.production.pojo.ProductWorkOrder;
-import com.ruoyi.production.pojo.ProductWorkOrderFile;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class ProductWorkOrderDto extends ProductWorkOrder {
-
-    //浜у搧鍚嶇О
-    @ApiModelProperty(value = "浜у搧鍚嶇О")
-    private String productName;
-
-    //瑙勬牸
-    @ApiModelProperty(value = "瑙勬牸")
-    private String model;
-
-    //宸ュ簭
-    @ApiModelProperty(value = "宸ュ簭")
-    private String processName;
-
-    //鍗曚綅
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-
-
-    //鐢熶骇璁㈠崟鍙�
-    @ApiModelProperty(value = "鐢熶骇璁㈠崟鍙�")
-    private String productOrderNpsNo;
-
-    @ApiModelProperty(value = "瀹屾垚杩涘害")
-    private BigDecimal completionStatus;
-
-    @ApiModelProperty(value = "鎶ュ簾鏁伴噺")
-    private BigDecimal scrapQty;
-
-    @ApiModelProperty(value = "宸ュ崟绫诲瀷 姝e父 /杩斿伐杩斾慨")
-    private String workOrderType;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionDispatchAddDto.java b/src/main/java/com/ruoyi/production/dto/ProductionDispatchAddDto.java
deleted file mode 100644
index 67a6332..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductionDispatchAddDto.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-/**
- * @author :yys
- * @date : 2025/7/21 16:28
- */
-@Data
-@ApiModel
-public class ProductionDispatchAddDto {
-
-    @ApiModelProperty(value = "閿�鍞彴璐D")
-    private Long salesLedgerId;
-
-    @ApiModelProperty(value = "閿�鍞骇鍝両D")
-    private Long salesLedgerProductId;
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    @ApiModelProperty(value = "鎺掍骇鏁伴噺")
-    private BigDecimal schedulingNum;
-
-    /**
-     * 鎺掍骇浜�
-     */
-    @ApiModelProperty(value = "鎺掍骇浜�")
-    private Long schedulingUserId;
-
-    /**
-     * 鎺掍骇鏃ユ湡
-     */
-    @ApiModelProperty(value = "鎺掍骇鏃ユ湡")
-    private String schedulingDate;
-
-    /**
-     * 鐢熶骇鐐掓満
-     */
-    private String speculativeTradingName;
-    /**
-     * 浜х嚎
-     */
-    @ApiModelProperty(value = "浜х嚎")
-    private String productionLine;
-
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
-    private String specificationModel;
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionProductInputDto.java b/src/main/java/com/ruoyi/production/dto/ProductionProductInputDto.java
deleted file mode 100644
index 13bb4a3..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductionProductInputDto.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.production.pojo.ProductionProductInput;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-@Data
-public class ProductionProductInputDto extends ProductionProductInput {
-    @ApiModelProperty(value = "鎶ュ伐鍗曞彿")
-    private String productNo;
-
-    @ApiModelProperty(value = "浜у搧鍨嬪彿")
-    private String model;
-
-    @ApiModelProperty(value = "浜у搧鍚嶇О")
-    private String productName;
-
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java b/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
deleted file mode 100644
index 9e5e121..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import com.ruoyi.production.pojo.ProductionProductMain;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-@Data
-@ExcelIgnoreUnannotated
-public class ProductionProductMainDto extends ProductionProductMain {
-    @ApiModelProperty(value = "宸ュ崟缂栧彿")
-    @Excel(name = "宸ュ崟缂栧彿")
-    private String workOrderNo;
-
-    @ApiModelProperty(value = "宸ュ崟鐘舵��")
-    private String workOrderStatus;
-
-    @ApiModelProperty(value = "鎶ュ伐浜哄憳鏄电О")
-    @Excel(name = "鎶ュ伐浜�")
-    private String nickName;
-
-    @ApiModelProperty(value = "鎶ュ伐鏁伴噺")
-    @Excel(name = "鎶ュ伐鏁伴噺")
-    private BigDecimal quantity;
-
-    @ApiModelProperty(value = "鎶ュ簾鏁伴噺")
-    @Excel(name = "鎶ュ簾鏁伴噺")
-    private BigDecimal scrapQty = BigDecimal.ZERO;
-
-    //浜у搧鍚嶇О
-    @Excel(name = "浜у搧鍚嶇О")
-    private String productName;
-
-    //浜у搧瑙勬牸鍨嬪彿
-    @Excel(name = "浜у搧瑙勬牸鍨嬪彿")
-    private String productModelName;
-
-    //鍗曚綅
-    @Excel(name = "鍗曚綅")
-    private String unit;
-
-    //閿�鍞悎鍚屽彿
-    @Excel(name = "閿�鍞悎鍚屽彿")
-    private String salesContractNo;
-
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate schedulingDate;
-    private String schedulingUserName;
-    private String customerName;
-    //宸ュ簭
-    @Excel(name = "宸ュ簭")
-    private String process;
-    private BigDecimal workHours;
-    private BigDecimal wages;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionProductOutputDto.java b/src/main/java/com/ruoyi/production/dto/ProductionProductOutputDto.java
deleted file mode 100644
index f98cc80..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductionProductOutputDto.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.production.pojo.ProductionProductInput;
-import com.ruoyi.production.pojo.ProductionProductOutput;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-@Data
-public class ProductionProductOutputDto extends ProductionProductOutput {
-    @ApiModelProperty(value = "鎶ュ伐鍗曞彿")
-    private String productNo;
-
-    @ApiModelProperty(value = "浜у搧鍨嬪彿")
-    private String model;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionReportDto.java b/src/main/java/com/ruoyi/production/dto/ProductionReportDto.java
deleted file mode 100644
index 727decb..0000000
--- a/src/main/java/com/ruoyi/production/dto/ProductionReportDto.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.ruoyi.production.dto;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-/**
- * @author :yys
- * @date : 2025/7/22 10:24
- */
-@Data
-@ApiModel
-public class ProductionReportDto {
-
-    private Long id;
-    /**
-     * 鎺掍骇浜篿d
-     */
-    @ApiModelProperty(value = "鐢熶骇浜篿d")
-    private Long schedulingUserId;
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    private BigDecimal schedulingNum;
-
-    /**
-     * 鐢熶骇鏁伴噺
-     */
-    @ApiModelProperty(value = "鐢熶骇鏁伴噺")
-    private BigDecimal finishedNum;
-
-    /**
-     * 鐢熶骇鏃ユ湡
-     */
-    @ApiModelProperty(value = "鐢熶骇鏃ユ湡")
-    private String schedulingDate;
-
-
-    /**
-     * 鍏ュ簱鍗曚环
-     */
-    @ApiModelProperty(value = "鍏ュ簱鍗曚环")
-    private BigDecimal unitPrice;
-
-    /**
-     * 鍏ュ簱鎬讳环
-     */
-    @ApiModelProperty(value = "鍏ュ簱鎬讳环")
-    private BigDecimal totalPrice;
-}
diff --git a/src/main/java/com/ruoyi/production/dto/SalesLedgerProductDto.java b/src/main/java/com/ruoyi/production/dto/SalesLedgerProductDto.java
deleted file mode 100644
index 33e758d..0000000
--- a/src/main/java/com/ruoyi/production/dto/SalesLedgerProductDto.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.util.Date;
-
-/**
- * @author :yys
- * @date : 2025/7/22 9:35
- */
-@Data
-@ApiModel
-public class SalesLedgerProductDto {
-
-    /**
-     * 閿�鍞悎鍚屽彿
-     */
-    @Excel(name = "閿�鍞悎鍚屽彿")
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
-    private String salesContractNo;
-
-    /**
-     * 瀹㈡埛鍚堝悓鍙�
-     */
-    @Excel(name = "瀹㈡埛鍚堝悓鍙�")
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
-    private String customerContractNo;
-
-    /**
-     * 椤圭洰鍚嶇О
-     */
-    @Excel(name = "椤圭洰鍚嶇О")
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
-    private String projectName;
-
-
-    /**
-     * 瀹㈡埛鍚嶇О
-     */
-    @Excel(name = "瀹㈡埛鍚嶇О")
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
-    private String customerName;
-
-
-    /**
-     * 浜у搧澶х被
-     */
-    @Excel(name = "浜у搧澶х被")
-    @ApiModelProperty(value = "浜у搧澶х被")
-    private String productCategory;
-
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
-    @Excel(name = "瑙勬牸鍨嬪彿")
-    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
-    private String specificationModel;
-
-    /**
-     * 鍗曚綅
-     */
-    @Excel(name = "鍗曚綅")
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/SalesLedgerProductionAccountingDto.java b/src/main/java/com/ruoyi/production/dto/SalesLedgerProductionAccountingDto.java
deleted file mode 100644
index 8cb4d91..0000000
--- a/src/main/java/com/ruoyi/production/dto/SalesLedgerProductionAccountingDto.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-/**
- * @author :yys
- * @date : 2025/7/22 13:55
- */
-@Data
-@ApiModel
-@ExcelIgnoreUnannotated
-public class SalesLedgerProductionAccountingDto extends SalesLedgerProductDto{
-
-    /**
-     * 鐢熶骇浜篿d
-     */
-    @ApiModelProperty(value = "鐢熶骇浜篿d")
-    private Long schedulingUserId;
-
-    /**
-     * 鎺掍骇浜哄悕绉�
-     */
-    @ApiModelProperty(value = "鐢熶骇浜哄悕绉�")
-    @Excel(name = "鐢熶骇浜�")
-    private String schedulingUserName;
-
-
-    /**
-     * 宸ヨ祫
-     */
-    @ApiModelProperty(value = "宸ヨ祫")
-    @Excel(name = "宸ヨ祫")
-    private BigDecimal wages;
-
-    /**
-     * 鐢熶骇鏁伴噺
-     */
-    @ApiModelProperty(value = "鐢熶骇鏁伴噺")
-    @Excel(name = "鐢熶骇鏁伴噺")
-    private BigDecimal finishedNum;
-
-    /**
-     * 宸ユ椂瀹氶
-     */
-    @ApiModelProperty(value = "宸ユ椂瀹氶")
-    @Excel(name = "宸ユ椂瀹氶")
-    private BigDecimal workHours;
-
-    /**
-     * 宸ュ簭
-     */
-    @ApiModelProperty(value = "宸ュ簭")
-    @Excel(name = "宸ュ簭")
-    private String process;
-    /**
-     * 鎺掍骇鏃ユ湡
-     */
-    @ApiModelProperty(value = "鎺掍骇鏃ユ湡")
-    @Excel(name = "鐢熶骇鏃ユ湡")
-    private LocalDate schedulingDate;
-
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate entryDateStart;
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate entryDateEnd;
-
-
-    private BigDecimal outputNum;
-
-    private String outputRate;
-
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate entryDate;
-
-    private String dateType;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingDto.java b/src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingDto.java
deleted file mode 100644
index 57d14ab..0000000
--- a/src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingDto.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.Date;
-
-/**
- * @author :yys
- * @date : 2025/7/21 15:42
- */
-@Data
-@ApiModel
-public class SalesLedgerSchedulingDto {
-
-    @ApiModelProperty(value = "閿�鍞骇鍝両D")
-    private Long salesLedgerProductId;
-
-    @ApiModelProperty(value = "閿�鍞彴璐D")
-    private Long salesLedgerId;
-
-    @ApiModelProperty(value = "鐢熶骇鎬婚噺(鍗曚綅kg)")
-    private BigDecimal totalProduction;
-
-    /**
-     * 鐢熶骇鐐掓満
-     */
-    @Excel(name = "鐢熶骇鐐掓満")
-    private String speculativeTradingName;
-
-    /**
-     * 閿�鍞悎鍚屽彿
-     */
-    @Excel(name = "閿�鍞悎鍚屽彿")
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
-    private String salesContractNo;
-
-    /**
-     * 瀹㈡埛鍚堝悓鍙�
-     */
-    @Excel(name = "瀹㈡埛鍚堝悓鍙�")
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
-    private String customerContractNo;
-
-    /**
-     * 椤圭洰鍚嶇О
-     */
-    @Excel(name = "椤圭洰鍚嶇О")
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
-    private String projectName;
-
-    /**
-     * 褰曞叆鏃ユ湡
-     */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "褰曞叆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "褰曞叆鏃ユ湡")
-    private Date entryDate;
-
-    @ApiModelProperty(value = "褰曞叆鏃ユ湡寮�濮�")
-    private String entryDateStart;
-
-    @ApiModelProperty(value = "褰曞叆鏃ユ湡缁撴潫")
-    private String entryDateEnd;
-
-    /**
-     * 瀹㈡埛鍚嶇О
-     */
-    @Excel(name = "瀹㈡埛鍚嶇О")
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
-    private String customerName;
-
-
-    /**
-     * 浜у搧澶х被
-     */
-    @Excel(name = "浜у搧澶х被")
-    @ApiModelProperty(value = "浜у搧澶х被")
-    private String productCategory;
-
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
-    @Excel(name = "瑙勬牸鍨嬪彿")
-    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
-    private String specificationModel;
-
-    /**
-     * 鍗曚綅
-     */
-    @Excel(name = "鍗曚綅")
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-
-    /**
-     * 鏁伴噺
-     */
-    @Excel(name = "鏁伴噺")
-    @ApiModelProperty(value = "鏁伴噺")
-    private BigDecimal quantity;
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    @Excel(name = "鎺掍骇鏁伴噺")
-    @ApiModelProperty(value = "鎺掍骇鏁伴噺")
-    private BigDecimal schedulingNum;
-
-    /**
-     * 瀹屽伐鏁伴噺
-     */
-    @Excel(name = "瀹屽伐鏁伴噺")
-    @ApiModelProperty(value = "瀹屽伐鏁伴噺")
-    private BigDecimal successNum;
-
-    @Excel(name = "鐘舵��")
-    private String status;
-
-    @Excel(name = "杩涘害")
-    private BigDecimal progress;
-
-    @ApiModelProperty(value = "绉熸埛ID")
-    private Long tenantId;
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingProcessDto.java b/src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingProcessDto.java
deleted file mode 100644
index b04e43e..0000000
--- a/src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingProcessDto.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * @author :yys
- * @date : 2025/7/21 16:47
- */
-@Data
-@ApiModel
-public class SalesLedgerSchedulingProcessDto {
-
-    @ApiModelProperty(value = "閿�鍞骇鍝両D")
-    private Long salesLedgerProductId;
-
-    @ApiModelProperty(value = "鐢熶骇鎬婚噺(鍗曚綅kg)")
-    private BigDecimal totalProduction;
-
-    @ApiModelProperty(value = "閿�鍞彴璐D")
-    private Long salesLedgerId;
-
-    /**
-     * 鐢熶骇鐐掓満
-     */
-    @Excel(name = "鐢熶骇鐐掓満")
-    private String speculativeTradingName;
-
-    @ApiModelProperty(value = "浜х嚎")
-    @Excel(name = "浜х嚎")
-    private String productionLine;
-
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
-    private String entryDateStart;
-
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
-    private String entryDateEnd;
-
-    /**
-     * id
-     */
-    private Long id;
-
-    /**
-     * 閿�鍞悎鍚屽彿
-     */
-    @Excel(name = "閿�鍞悎鍚屽彿")
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
-    private String salesContractNo;
-
-    /**
-     * 瀹㈡埛鍚堝悓鍙�
-     */
-    @Excel(name = "瀹㈡埛鍚堝悓鍙�")
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
-    private String customerContractNo;
-
-    /**
-     * 椤圭洰鍚嶇О
-     */
-    @Excel(name = "椤圭洰鍚嶇О")
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
-    private String projectName;
-
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "娲惧伐鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "娲惧伐鏃ユ湡")
-    private Date schedulingDate;
-
-    /**
-     * 瀹㈡埛鍚嶇О
-     */
-    @Excel(name = "瀹㈡埛鍚嶇О")
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
-    private String customerName;
-
-
-    /**
-     * 浜у搧澶х被
-     */
-    @Excel(name = "浜у搧澶х被")
-    @ApiModelProperty(value = "浜у搧澶х被")
-    private String productCategory;
-
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
-    @Excel(name = "瑙勬牸鍨嬪彿")
-    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
-    private String specificationModel;
-
-    /**
-     * 鍗曚綅
-     */
-    @Excel(name = "鍗曚綅")
-    @ApiModelProperty(value = "鍗曚綅")
-    private String unit;
-
-    /**
-     * 鐘舵��
-     */
-    @ApiModelProperty(value = "鐘舵��")
-    private Integer status;
-
-    @Excel(name = "鐘舵��", readConverterExp = "1=寰呮帓浜�,2=鎺掍骇涓�,3=宸叉帓浜�")
-    private String statusName;
-
-    /**
-     * 娲惧伐浜�
-     */
-    @Excel(name = "娲惧伐浜�")
-    @ApiModelProperty(value = "娲惧伐浜�")
-    private String schedulingUserName;
-
-    /**
-     * 娲惧伐浜�
-     */
-    @ApiModelProperty(value = "娲惧伐浜篿d")
-    private Long schedulingUserId;
-
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    @Excel(name = "鎺掍骇鏁伴噺")
-    @ApiModelProperty(value = "鎺掍骇鏁伴噺")
-    private BigDecimal schedulingNum;
-
-    /**
-     * 宸叉帓浜ф暟閲�
-     */
-    @ApiModelProperty(value = "宸叉帓浜ф暟閲�")
-    @Excel(name = "宸叉帓浜ф暟閲�")
-    private BigDecimal successNum;
-
-    private Long tenantId;
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/SalesLedgerWorkDto.java b/src/main/java/com/ruoyi/production/dto/SalesLedgerWorkDto.java
deleted file mode 100644
index 3e982e7..0000000
--- a/src/main/java/com/ruoyi/production/dto/SalesLedgerWorkDto.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.ruoyi.production.dto;
-
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-/**
- * @author :yys
- * @date : 2025/7/22 9:33
- */
-@Data
-@ApiModel
-public class SalesLedgerWorkDto extends SalesLedgerProductDto{
-
-    private Long id;
-
-    /**
-     * 鎺掍骇浜篿d
-     */
-    @ApiModelProperty(value = "鎺掍骇浜篿d")
-    private Long schedulingUserId;
-
-    /**
-     * 鎺掍骇浜哄悕绉�
-     */
-    @ApiModelProperty(value = "鎺掍骇浜哄悕绉�")
-    @Excel(name = "鎺掍骇浜�")
-    private String schedulingUserName;
-
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    @ApiModelProperty(value = "鎺掍骇鏁伴噺")
-    @Excel(name = "鎺掍骇鏁伴噺")
-    private BigDecimal schedulingNum;
-
-    /**
-     * 鐢熶骇鏁伴噺
-     */
-    @ApiModelProperty(value = "鐢熶骇鏁伴噺")
-    @Excel(name = "鐢熶骇鏁伴噺")
-    private BigDecimal finishedNum;
-
-    /**
-     * 寰呯敓浜ф暟閲�
-     */
-    @ApiModelProperty(value = "寰呯敓浜ф暟閲�")
-    @Excel(name = "寰呯敓浜ф暟閲�")
-    private BigDecimal daiNum;
-
-    /**
-     * 宸ユ椂瀹氶
-     */
-    @ApiModelProperty(value = "宸ユ椂瀹氶")
-    private BigDecimal workHours;
-
-    /**
-     * 宸ュ簭
-     */
-    @ApiModelProperty(value = "宸ュ簭")
-    @Excel(name = "宸ュ簭")
-    private String process;
-
-
-    /**
-     * 浜х嚎
-     */
-    @ApiModelProperty(value = "浜х嚎")
-    @Excel(name = "浜х嚎")
-    private String productionLine;
-    /**
-     * 鎺掍骇鏃ユ湡
-     */
-    @ApiModelProperty(value = "鎺掍骇鏃ユ湡")
-    @Excel(name = "鎺掍骇鏃ユ湡")
-    private String schedulingDate;
-
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
-    private String entryDateStart;
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
-    private String entryDateEnd;
-
-    /**
-     * 鎶ュ伐鐘舵�侊紙1-寰呯敓浜� 2-宸叉姤宸ワ級
-     */
-    @ApiModelProperty(value = "鎶ュ伐鐘舵��")
-    private Integer status;
-
-    @Excel(name = "鐘舵��", readConverterExp = "1=寰呯敓浜�,2=鐢熶骇涓�,3=宸叉姤宸�")
-    private String statusName;
-
-    /**
-     * 澶囨敞
-     */
-    @ApiModelProperty(value = "澶囨敞")
-    @Excel(name = "澶囨敞")
-    private String remark;
-
-    /**
-     * 鎹熻��
-     */
-    @ApiModelProperty(value = "鎹熻��")
-    @Excel(name = "鎹熻��")
-    private String loss;
-
-    /**
-     * 缁戝畾鏈哄櫒
-     */
-    @ApiModelProperty(value = "缁戝畾鏈哄櫒")
-    @Excel(name = "缁戝畾鏈哄櫒")
-    private String speculativeTradingName;
-
-    /**
-     * 鍙e懗鍒嗙被
-     */
-    @ApiModelProperty(value = "鍙e懗鍒嗙被")
-    @Excel(name = "鍙e懗鍒嗙被")
-    private String type;
-
-    /**
-     * 棰嗙敤
-     */
-    @ApiModelProperty(value = "棰嗙敤")
-    @Excel(name = "棰嗙敤")
-    private String receive;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/UserAccountDto.java b/src/main/java/com/ruoyi/production/dto/UserAccountDto.java
deleted file mode 100644
index 75f99bc..0000000
--- a/src/main/java/com/ruoyi/production/dto/UserAccountDto.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ruoyi.production.dto;
-
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-@Data
-public class UserAccountDto {
-
-    private String userName;
-
-    private Long userId;
-
-    @ApiModelProperty("璁℃椂")
-    private BigDecimal account;
-
-    @ApiModelProperty("璁′欢")
-    private BigDecimal accountBalance;
-
-}
diff --git a/src/main/java/com/ruoyi/production/dto/UserProductionAccountingDto.java b/src/main/java/com/ruoyi/production/dto/UserProductionAccountingDto.java
deleted file mode 100644
index ba191d1..0000000
--- a/src/main/java/com/ruoyi/production/dto/UserProductionAccountingDto.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.ruoyi.production.dto;
-
-import lombok.Data;
-
-@Data
-public class UserProductionAccountingDto {
-    private Long userId;
-
-    private String date;
-}
diff --git a/src/main/java/com/ruoyi/production/enums/ProductOrderStatusEnum.java b/src/main/java/com/ruoyi/production/enums/ProductOrderStatusEnum.java
new file mode 100644
index 0000000..5ad55c3
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/enums/ProductOrderStatusEnum.java
@@ -0,0 +1,65 @@
+package com.ruoyi.production.enums;
+
+import lombok.Getter;
+
+/**
+ * <br>
+ * 鐢熶骇璁㈠崟鐘舵�佹灇涓剧被
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/18 14:18
+ */
+@Getter
+public enum ProductOrderStatusEnum {
+
+    WAIT(1, "寰呭紑濮�"),
+    RUNNING(2, "杩涜涓�"),
+    FINISHED(3, "宸插畬鎴�"),
+    CANCEL(4, "宸插彇娑�");
+
+    private final Integer code;
+    private final String desc;
+
+    ProductOrderStatusEnum(Integer code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    /**
+     * 鏍规嵁code鑾峰彇鏋氫妇
+     */
+    public static ProductOrderStatusEnum getByCode(Integer code) {
+        if (code == null) {
+            return null;
+        }
+        for (ProductOrderStatusEnum item : values()) {
+            if (item.getCode().equals(code)) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鍏佽鍒犻櫎锛�4锛�
+     */
+    public static boolean canDelete(Integer code) {
+        return WAIT.getCode().equals(code) || CANCEL.getCode().equals(code);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鍏佽鎾ゅ洖锛�1锛�
+     */
+    public static boolean canRevoke(Integer code) {
+        return WAIT.getCode().equals(code);
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁宸插紑濮嬬敓浜э紙2銆�3锛�
+     */
+    public static boolean isStarted(Integer code) {
+        return RUNNING.getCode().equals(code) || FINISHED.getCode().equals(code);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/mapper/ProcessRouteItemMapper.java b/src/main/java/com/ruoyi/production/mapper/ProcessRouteItemMapper.java
deleted file mode 100644
index 394c3a7..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProcessRouteItemMapper.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProcessRouteItemDto;
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-@Mapper
-public interface ProcessRouteItemMapper  extends BaseMapper<ProcessRouteItem> {
-
-
-    List<ProcessRouteItemDto> listProcessRouteItemDto(@Param("c") ProcessRouteItemDto processRouteItemDto);
-
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProcessRouteMapper.java b/src/main/java/com/ruoyi/production/mapper/ProcessRouteMapper.java
deleted file mode 100644
index 493b764..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProcessRouteMapper.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-@Mapper
-public interface ProcessRouteMapper extends BaseMapper<ProcessRoute> {
-
-    IPage<ProcessRouteDto> pageProcessRouteDto(Page<ProcessRouteDto> page,@Param("c") ProcessRouteDto processRouteDto);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductBomMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductBomMapper.java
deleted file mode 100644
index 1183335..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductBomMapper.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProductBomDto;
-import com.ruoyi.production.dto.ProductProcessDto;
-import com.ruoyi.production.pojo.ProductBom;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-/**
- * <p>
- * BOM涓昏〃 Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 09:59:27
- */
-@Mapper
-public interface ProductBomMapper extends BaseMapper<ProductBom> {
-
-    IPage<ProductBomDto> listPage(Page page, @Param("c") ProductBomDto productBomDto);
-
-    ProductBomDto getById(@Param("bomId") Long bomId);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductOrderMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductOrderMapper.java
deleted file mode 100644
index 72aa6cd..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductOrderMapper.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProductBomDto;
-import com.ruoyi.production.dto.ProductOrderDto;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import com.ruoyi.production.pojo.ProductOrder;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-@Mapper
-public interface ProductOrderMapper extends BaseMapper<ProductOrder> {
-
-    IPage<ProductOrderDto> pageProductOrder(Page page, @Param("c") ProductOrderDto productOrder);
-
-    List<ProcessRoute> listProcessRoute(@Param("productModelId") Long productModelId);
-
-    List<ProductStructureDto> listProcessBom(@Param("orderId") Long orderId);
-
-    Integer countCreated(@Param("startDate") String startDate, @Param("endDate") String endDate);
-
-    Integer countCompleted(@Param("startDate") String startDate, @Param("endDate") String endDate);
-
-    Integer countPending(@Param("startDate") String startDate, @Param("endDate") String endDate);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductProcessMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductProcessMapper.java
deleted file mode 100644
index b2168c3..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductProcessMapper.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.home.dto.processDataProductionStatisticsDto;
-import com.ruoyi.production.dto.ProductProcessDto;
-import com.ruoyi.production.pojo.ProductProcess;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Mapper
-public interface ProductProcessMapper extends BaseMapper<ProductProcess> {
-    IPage<ProductProcessDto> listPage(Page page,@Param("productProcessDto") ProductProcessDto productProcessDto);
-
-    List<processDataProductionStatisticsDto> calculateProductionStatistics(LocalDateTime startDateTime, LocalDateTime endDateTime, Long userId, List<Long> processIds);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductProcessRouteItemMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductProcessRouteItemMapper.java
deleted file mode 100644
index 48b38ec..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductProcessRouteItemMapper.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.production.dto.ProductProcessRouteItemDto;
-import com.ruoyi.production.pojo.ProductProcessRouteItem;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-@Mapper
-public interface ProductProcessRouteItemMapper extends BaseMapper<ProductProcessRouteItem> {
-    List<ProductProcessRouteItemDto> listItem(@Param("orderId") Long orderId);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductProcessRouteMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductProcessRouteMapper.java
deleted file mode 100644
index 06ae748..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductProcessRouteMapper.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.pojo.ProductProcessRoute;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-/**
- * <p>
- *  Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:51:09
- */
-@Mapper
-public interface ProductProcessRouteMapper extends BaseMapper<ProductProcessRoute> {
-
-    ProcessRouteDto listMain(@Param("orderId") Long orderId);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java
deleted file mode 100644
index bd59242..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.pojo.ProductStructure;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-@Mapper
-public interface ProductStructureMapper  extends BaseMapper<ProductStructure> {
-
-    List<ProductStructureDto> listBybomId(@Param("bomId") Integer bomId);
-
-    List<ProductStructureDto> listBybomAndProcess(@Param("bomId") Integer bomId, @Param("processId") Long processId);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductWorkOrderFileMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductWorkOrderFileMapper.java
deleted file mode 100644
index 72b8f94..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductWorkOrderFileMapper.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.ruoyi.production.pojo.ProductWorkOrderFile;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * <p>
- * 鐢熶骇宸ュ崟闄勪欢琛� Mapper 鎺ュ彛
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-23 03:28:32
- */
-@Mapper
-public interface ProductWorkOrderFileMapper extends BaseMapper<ProductWorkOrderFile> {
-
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductWorkOrderMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductWorkOrderMapper.java
deleted file mode 100644
index d637f7d..0000000
--- a/src/main/java/com/ruoyi/production/mapper/ProductWorkOrderMapper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProductWorkOrderDto;
-import com.ruoyi.production.pojo.ProductWorkOrder;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-import java.util.Map;
-
-@Mapper
-public interface ProductWorkOrderMapper extends BaseMapper<ProductWorkOrder> {
-
-    IPage<ProductWorkOrderDto> pageProductWorkOrder(Page<ProductWorkOrderDto> page, @Param("c") ProductWorkOrderDto productWorkOrder);
-
-    ProductWorkOrderDto getProductWorkOrderFlowCard(@Param("id") Long id);
-
-    List<ProductWorkOrderDto> selectWorkOrderStartStats(@Param("startDate") String startDate, @Param("endDate") String endDate);
-
-    ProductWorkOrder selectMax(@Param("datePrefix") String datePrefix);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java
new file mode 100644
index 0000000..2cdc8d0
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionAccountMapper.java
@@ -0,0 +1,32 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.UserAccountDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
+import com.ruoyi.production.pojo.ProductionAccount;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 鐢熶骇鏍哥畻琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionAccountMapper extends BaseMapper<ProductionAccount> {
+    IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, @Param("c") ProductionAccountDto dto);
+
+    UserAccountDto selectUserAccount(@Param("userId") Long userId, @Param("date") String date);
+
+    List<Map<String, Object>> selectDailyWagesStats(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java
new file mode 100644
index 0000000..bb9ad78
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionBomStructureMapper.java
@@ -0,0 +1,30 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
+import com.ruoyi.production.pojo.ProductionBomStructure;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionBomStructureMapper extends BaseMapper<ProductionBomStructure> {
+
+    List<ProductionBomStructureVo> listByBomId(@Param("bomId") Long bomId);
+
+    /**
+     * 棰嗘枡bom
+     * @param bomId
+     * @return
+     */
+    List<ProductionBomStructureVo> pickByBomId(@Param("bomId") Long bomId);
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOperationMainParamMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOperationMainParamMapper.java
new file mode 100644
index 0000000..356a810
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOperationMainParamMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.pojo.ProductionOperationMainParam;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鐢熶骇宸ュ崟鎶ュ伐鍙傛暟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOperationMainParamMapper extends BaseMapper<ProductionOperationMainParam> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
new file mode 100644
index 0000000..a09dd6f
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
@@ -0,0 +1,46 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.home.dto.ProductionTaskStatisticsDto;
+import com.ruoyi.home.dto.processDataProductionStatisticsDto;
+import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
+import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇宸ュ崟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOperationTaskMapper extends BaseMapper<ProductionOperationTask> {
+
+    IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskVo> page,
+                                                                 @Param("c") ProductionOperationTaskDto dto);
+
+    List<ProductionTaskStatisticsDto> selectTaskStatisticsByDate(@Param("startDate") LocalDate startDate,
+                                                                 @Param("endDate") LocalDate endDate);
+
+    List<ProductionTaskStatisticsDto> selectTaskStartStats(@Param("startDateTime") String startDateTime,
+                                                           @Param("endDateTime") String endDateTime);
+
+    List<processDataProductionStatisticsDto> calculateProductionStatistics(@Param("startDateTime") LocalDateTime startDateTime,
+                                                                           @Param("endDateTime") LocalDateTime endDateTime,
+                                                                           @Param("userId") Long userId,
+                                                                           @Param("processIds") List<Long> processIds);
+
+    ProductionOperationTaskDto getProductWorkOrderFlowCard(@Param("id") Long id);
+
+    List<ProductionOperationTaskVo> getOperation(@Param("c") ProductionOperationTaskDto dto);
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java
new file mode 100644
index 0000000..65c02ff
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderBomMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.pojo.ProductionOrderBom;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOrderBomMapper extends BaseMapper<ProductionOrderBom> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java
new file mode 100644
index 0000000..e52df0c
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderMapper.java
@@ -0,0 +1,42 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.home.dto.ProductionProgressOrderDto;
+import com.ruoyi.production.bean.dto.ProductionOrderDto;
+import com.ruoyi.production.bean.vo.ProductionOrderVo;
+import com.ruoyi.production.pojo.ProductionOrder;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOrderMapper extends BaseMapper<ProductionOrder> {
+
+    IPage<ProductionOrderVo> pageProductionOrder(Page<?> page, @Param("c") ProductionOrderDto dto);
+
+    List<ProductionOrderVo> listProductionOrder(@Param("c") ProductionOrderDto dto);
+
+    ProductionOrderVo getProductionOrderInfo(@Param("id") Long id);
+
+    List<ProductionProgressOrderDto> selectProgressOrders(@Param("startTime") LocalDateTime startTime,
+                                                          @Param("endTime") LocalDateTime endTime);
+
+    Integer countCreated(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    Integer countCompleted(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    Integer countPending(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java
new file mode 100644
index 0000000..3f2b9cc
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickMapper.java
@@ -0,0 +1,23 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.pojo.ProductionOrderPick;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璁㈠崟棰嗘枡绾胯竟浠� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOrderPickMapper extends BaseMapper<ProductionOrderPick> {
+
+    List<ProductionOrderPickVo> listPickedDetailByOrderId(@Param("productionOrderId") Long productionOrderId);
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java
new file mode 100644
index 0000000..6b18e1c
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderPickRecordMapper.java
@@ -0,0 +1,27 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.pojo.ProductionOrderPickRecord;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 绾胯竟浠撳嚭鍏ュ簱璁板綍 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOrderPickRecordMapper extends BaseMapper<ProductionOrderPickRecord> {
+
+    List<ProductionOrderPickVo> listPickedDetailByOrderId(@Param("productionOrderId") Long productionOrderId);
+
+    List<ProductionOrderPickRecordVo> listFeedingRecord(ProductionOrderPickRecordDto dto);
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingMapper.java
new file mode 100644
index 0000000..14a1468
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.pojo.ProductionOrderRouting;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOrderRoutingMapper extends BaseMapper<ProductionOrderRouting> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationMapper.java
new file mode 100644
index 0000000..8b34b08
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.bean.vo.ProductionOrderRoutingOperationVo;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOrderRoutingOperationMapper extends BaseMapper<ProductionOrderRoutingOperation> {
+
+    List<ProductionOrderRoutingOperationVo> selectVoListByOrderId(@Param("orderId") Long orderId);
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationParamMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationParamMapper.java
new file mode 100644
index 0000000..efcc3ca
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionOrderRoutingOperationParamMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Mapper
+public interface ProductionOrderRoutingOperationParamMapper extends BaseMapper<ProductionOrderRoutingOperationParam> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionPlanMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionPlanMapper.java
new file mode 100644
index 0000000..15358f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionPlanMapper.java
@@ -0,0 +1,32 @@
+package com.ruoyi.production.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.bean.dto.ProductionPlanDto;
+import com.ruoyi.production.bean.vo.ProductionPlanVo;
+import com.ruoyi.production.pojo.ProductionPlan;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁″垝琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 02:11:10
+ */
+@Mapper
+public interface ProductionPlanMapper extends BaseMapper<ProductionPlan> {
+
+    IPage<ProductionPlanVo> listPage(Page<ProductionPlanDto> page, @Param("c") ProductionPlanDto productionPlanDto);
+
+    List<ProductionPlanDto> selectWithMaterialByIds(@Param("ids") List<Long> ids);
+
+    ProductionPlanDto selectProductionPlanDtoById(@Param("productionPlanId") Long productionPlanId);
+
+    List<ProductionPlanVo> getSource(@Param("ids") List<Long> planIds);
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionProductInputMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionProductInputMapper.java
index be90d7a..cbd6998 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionProductInputMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionProductInputMapper.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProductionProductInputDto;
+import com.ruoyi.production.bean.dto.ProductionProductInputDto;
 import com.ruoyi.production.pojo.ProductionProductInput;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
index e63e032..01b9912 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionProductMainMapper.java
@@ -3,9 +3,9 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProductionProductMainDto;
-import com.ruoyi.production.dto.SalesLedgerProductionAccountingDto;
-import com.ruoyi.production.pojo.ProductOrder;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.pojo.ProductionOrder;
 import com.ruoyi.production.pojo.ProductionProductMain;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -28,9 +28,9 @@
      * @param productMainId
      * @return
      */
-    ProductOrder getOrderByMainId(@Param("productMainId") Long productMainId);
+    ProductionOrder getOrderByMainId(@Param("productMainId") Long productMainId);
 
-    IPage<ProductionProductMainDto> listProductionDetails(@Param("ew") SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page);
+    IPage<ProductionProductMainDto> listProductionDetails(@Param("c") ProductionAccountDto productionAccountDto, Page page);
 
     ArrayList<Long> listMain(List<Long> idList);
 }
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionProductOutputMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionProductOutputMapper.java
index cbb32fd..06a87de 100644
--- a/src/main/java/com/ruoyi/production/mapper/ProductionProductOutputMapper.java
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionProductOutputMapper.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.ProductionProductOutputDto;
+import com.ruoyi.production.bean.dto.ProductionProductOutputDto;
 import com.ruoyi.production.pojo.ProductionProductOutput;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
diff --git a/src/main/java/com/ruoyi/production/mapper/SalesLedgerProductionAccountingMapper.java b/src/main/java/com/ruoyi/production/mapper/SalesLedgerProductionAccountingMapper.java
deleted file mode 100644
index 8dec95c..0000000
--- a/src/main/java/com/ruoyi/production/mapper/SalesLedgerProductionAccountingMapper.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.SalesLedgerProductionAccountingDto;
-import com.ruoyi.production.dto.UserAccountDto;
-import com.ruoyi.production.dto.UserProductionAccountingDto;
-import com.ruoyi.production.pojo.SalesLedgerProductionAccounting;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:38
- */
-public interface SalesLedgerProductionAccountingMapper extends BaseMapper<SalesLedgerProductionAccounting> {
-
-
-    IPage<SalesLedgerProductionAccountingDto> listPage(Page page,@Param("salesLedgerDto") SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto);
-
-
-    IPage<SalesLedgerProductionAccountingDto> pageProductionAccounting(Page page, @Param("ew") SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto);
-
-    List<Map<String, Object>> selectDailyWagesStats(@Param("startDate") String startDate, @Param("endDate") String endDate);
-
-    UserAccountDto getByUserId(@Param( "ew") UserProductionAccountingDto userProductionAccountingDto);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/SalesLedgerSchedulingMapper.java b/src/main/java/com/ruoyi/production/mapper/SalesLedgerSchedulingMapper.java
deleted file mode 100644
index 140de3d..0000000
--- a/src/main/java/com/ruoyi/production/mapper/SalesLedgerSchedulingMapper.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.SalesLedgerSchedulingDto;
-import com.ruoyi.production.dto.SalesLedgerSchedulingProcessDto;
-import com.ruoyi.production.pojo.SalesLedgerScheduling;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:37
- */
-public interface SalesLedgerSchedulingMapper  extends BaseMapper<SalesLedgerScheduling> {
-
-    /**
-     * 鍒嗛〉鏌ヨ
-     * @param page
-     * @param salesLedgerSchedulingDto
-     * @return
-     */
-    IPage<SalesLedgerSchedulingDto> listPage(Page page,@Param("salesLedgerDto") SalesLedgerSchedulingDto salesLedgerSchedulingDto);
-
-    /**
-     * 瀵煎嚭
-     * @return
-     */
-    List<SalesLedgerSchedulingDto> list();
-
-    /**
-     * 鍒嗛〉鏌ヨ宸ュ簭鎺掍骇
-     * @param page
-     * @param salesLedgerSchedulingDto
-     * @return
-     */
-    IPage<SalesLedgerSchedulingProcessDto> listPageProcess(Page page,@Param("salesLedgerDto") SalesLedgerSchedulingProcessDto salesLedgerSchedulingDto);
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/SalesLedgerWorkMapper.java b/src/main/java/com/ruoyi/production/mapper/SalesLedgerWorkMapper.java
deleted file mode 100644
index adf5dc3..0000000
--- a/src/main/java/com/ruoyi/production/mapper/SalesLedgerWorkMapper.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.production.dto.SalesLedgerWorkDto;
-import com.ruoyi.production.pojo.SalesLedgerWork;
-import org.apache.ibatis.annotations.Param;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:37
- */
-public interface SalesLedgerWorkMapper extends BaseMapper<SalesLedgerWork> {
-
-    /**
-     * 鍒嗛〉鏌ヨ
-     * @param page
-     * @param salesLedgerWorkDto
-     * @return
-     */
-    IPage<SalesLedgerWorkDto> listPage(Page page,@Param("salesLedgerDto") SalesLedgerWorkDto salesLedgerWorkDto);
-
-}
diff --git a/src/main/java/com/ruoyi/production/mapper/SpeculativeTradingInfoMapper.java b/src/main/java/com/ruoyi/production/mapper/SpeculativeTradingInfoMapper.java
deleted file mode 100644
index 21d4a11..0000000
--- a/src/main/java/com/ruoyi/production/mapper/SpeculativeTradingInfoMapper.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.ruoyi.production.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ruoyi.production.pojo.SpeculativeTradingInfo;
-
-/**
- * @author :yys
- * @date : 2025/11/11 15:40
- */
-public interface SpeculativeTradingInfoMapper extends BaseMapper<SpeculativeTradingInfo> {
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProcessRoute.java b/src/main/java/com/ruoyi/production/pojo/ProcessRoute.java
deleted file mode 100644
index fe661b3..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProcessRoute.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableName;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@TableName("process_route")
-@Data
-@ApiModel(value = "processRoute", description = "宸ヨ壓璺嚎涓昏〃")
-public class ProcessRoute {
-
-    @ApiModelProperty(value = "搴忓彿")
-    private Long id;
-
-    @ApiModelProperty(value = "浜у搧ID")
-    //product_model
-    private Long productModelId;
-
-    @ApiModelProperty(value = "鎻忚堪")
-    private String description;
-
-    @ApiModelProperty(value = "绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    @ApiModelProperty(value = "鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    @ApiModelProperty(value = "宸ヨ壓璺嚎缂栫爜")
-    private String processRouteCode;
-
-    @ApiModelProperty(value = "BOM鐨処D")
-    private Integer bomId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java b/src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java
deleted file mode 100644
index 973b29e..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Data
-@TableName("process_route_item")
-@ApiModel(value = "processRouteItem", description = "宸ヨ壓璺嚎瀛愯〃")
-public class ProcessRouteItem {
-
-    @TableId(type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "宸ヨ壓璺嚎id")
-    private Long routeId;
-
-    @ApiModelProperty(value = "宸ュ簭id")
-    private Long processId;
-
-    @ApiModelProperty(value ="浜у搧id")
-    private Long productModelId;
-
-    @ApiModelProperty(value = "绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-    @TableField(fill = FieldFill.INSERT)
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
-    private LocalDateTime createTime;
-    @ApiModelProperty(value = "鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.UPDATE)
-    private LocalDateTime updateTime;
-
-    @ApiModelProperty(value ="鎷栧姩鎺掑簭")
-    private Integer dragSort;
-
-
-    @ApiModelProperty(value ="鏄惁璐ㄦ")
-    private Boolean isQuality;
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductBom.java b/src/main/java/com/ruoyi/production/pojo/ProductBom.java
deleted file mode 100644
index 802724a..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductBom.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Getter;
-import lombok.Setter;
-import org.springframework.format.annotation.DateTimeFormat;
-
-/**
- * <p>
- * BOM涓昏〃
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 09:59:27
- */
-@Getter
-@Setter
-@TableName("product_bom")
-@ApiModel(value = "ProductBom瀵硅薄", description = "BOM涓昏〃")
-public class ProductBom implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty("bom缂栧彿")
-    private String bomNo;
-
-    @ApiModelProperty("浜у搧瑙勬牸id")
-    private Long productModelId;
-
-    @ApiModelProperty("澶囨敞")
-    private String remark;
-
-    @ApiModelProperty("鐗堟湰鍙�")
-    private String version;
-
-    @ApiModelProperty("鍒涘缓鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    @ApiModelProperty("鏇存柊鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    @ApiModelProperty("鍒涘缓鑰�")
-    @TableField(fill = FieldFill.INSERT)
-    private Long createUser;
-
-    @ApiModelProperty("鏇存柊鑰�")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private Long updateUser;
-
-    @ApiModelProperty("绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductOrder.java b/src/main/java/com/ruoyi/production/pojo/ProductOrder.java
deleted file mode 100644
index 5286cd3..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductOrder.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@Data
-@TableName("product_order")
-public class ProductOrder  implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 閿�鍞彴璐d
-     */
-    @ApiModelProperty(value = "閿�鍞彴璐d")
-    private Long salesLedgerId;
-
-    /**
-     * 閿�鍞彴璐︿骇鍝乮d(sales_ledger_product)
-     */
-    @ApiModelProperty(value = "閿�鍞彴璐︿骇鍝乮d")
-    private Long saleLedgerProductId;
-
-    /**
-     * 浜у搧瑙勬牸id
-     */
-    @ApiModelProperty(value = "浜у搧瑙勬牸id")
-    private Long productModelId;
-
-    /**
-     * 妯$増鐨勫伐鑹鸿矾绾縤d
-     */
-    @ApiModelProperty(value = "宸ヨ壓璺嚎id")
-    private Long routeId;
-
-    /**
-     * 鐢熶骇璁㈠崟鍙�
-     */
-    @ApiModelProperty(value = "鐢熶骇璁㈠崟鍙�")
-    @Excel(name = "鐢熶骇璁㈠崟鍙�")
-    private String npsNo;
-
-    /**
-     * 绉熸埛id
-     */
-    @ApiModelProperty(value = "绉熸埛id")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-    //鍒涘缓鏃堕棿
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @Excel(name = "鍒涘缓鏃堕棿")
-    private LocalDateTime createTime;
-
-    //淇敼鏃堕棿
-    @ApiModelProperty(value = "淇敼鏃堕棿")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime updateTime;
-
-
-    /**
-     * 闇�姹傛暟閲�
-     */
-    @ApiModelProperty(value = "闇�姹傛暟閲�")
-    @Excel(name = "闇�姹傛暟閲�")
-    private BigDecimal quantity;
-
-    /**
-     * 瀹屾垚鏁伴噺
-     */
-    @ApiModelProperty(value = "瀹屾垚鏁伴噺")
-    @Excel(name = "瀹屾垚鏁伴噺")
-    private BigDecimal completeQuantity;
-
-    @Excel(name = "寮�濮嬫椂闂�")
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime startTime;
-
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
-    @Excel(name = "缁撴潫鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime endTime;
-
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductProcess.java b/src/main/java/com/ruoyi/production/pojo/ProductProcess.java
deleted file mode 100644
index e55ab4f..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductProcess.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@TableName("product_process")
-@Data
-@ExcelIgnoreUnannotated
-@ApiModel(value = "productProcess", description = "宸ュ簭琛�")
-public class ProductProcess implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 宸ュ簭鍚嶇О
-     */
-    @Excel(name = "宸ュ簭鍚嶇О")
-    private String name;
-
-    /**
-     * 宸ュ簭缂栧彿
-     */
-    @Excel(name = "宸ュ簭缂栧彿")
-    private String no;
-
-    /**
-     * 澶囨敞
-     */
-    @Excel(name = "澶囨敞")
-    private String remark;
-
-
-    /**
-     * 宸ヨ祫瀹氶
-     */
-    @Excel(name = "宸ヨ祫瀹氶")
-    @TableField(updateStrategy = FieldStrategy.IGNORED)
-    private BigDecimal salaryQuota;
-
-    @ApiModelProperty("绫诲瀷 鍖哄垎鏄鏃惰繕鏄浠� 0 璁℃椂 1璁′欢")
-    private Long type;
-
-    /**
-     * 鍒涘缓鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime createTime;
-
-    /**
-     * 淇敼鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime updateTime;
-
-    /**
-     * 绉熸埛ID
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-    @ApiModelProperty(value ="鏄惁璐ㄦ")
-    private Boolean isQuality;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.java b/src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.java
deleted file mode 100644
index 5d7ab56..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductProcessRoute.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * <p>
- *
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:51:09
- */
-@Getter
-@Setter
-@TableName("product_process_route")
-@ApiModel(value = "ProductProcessRoute瀵硅薄", description = "")
-public class ProductProcessRoute implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty("浜у搧id")
-    //product_model
-    private Long productModelId;
-
-    @ApiModelProperty("鎻忚堪")
-    private String description;
-
-    @ApiModelProperty("绉熸埛id")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-    @ApiModelProperty("褰曞叆鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    @ApiModelProperty("鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    @ApiModelProperty("鍏宠仈bom鐨刬d")
-    private Integer bomId;
-
-    @ApiModelProperty("宸ヨ壓璺嚎缂栫爜")
-    private String processRouteCode;
-
-    @ApiModelProperty("鐢熶骇璁㈠崟鐨刬d")
-    private Long productOrderId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java b/src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
deleted file mode 100644
index d84a7ce..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Data
-@TableName("product_process_route_item")
-public class ProductProcessRouteItem {
-
-    @TableId(type = IdType.AUTO)
-    private Long id;
-
-    @ApiModelProperty(value = "鐢熶骇璁㈠崟id(product_order_id)")
-    private Long productOrderId;
-
-    @ApiModelProperty(value = "鐢熶骇璁㈠崟鐨勫伐鑹鸿矾绾縤d(product_process_route)")
-    private Long productRouteId;
-
-    @ApiModelProperty(value = "宸ュ簭id")
-    private Long processId;
-
-    @ApiModelProperty(value ="浜у搧id")
-    private Long productModelId;
-
-    @ApiModelProperty(value = "绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-    @TableField(fill = FieldFill.INSERT)
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
-    private LocalDateTime createTime;
-    @ApiModelProperty(value = "鏇存柊鏃堕棿")
-    @TableField(fill = FieldFill.UPDATE)
-    private LocalDateTime updateTime;
-
-    @ApiModelProperty(value ="鎷栧姩鎺掑簭")
-    private Integer dragSort;
-
-    @ApiModelProperty(value ="鏄惁璐ㄦ")
-    private Boolean isQuality;
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductStructure.java b/src/main/java/com/ruoyi/production/pojo/ProductStructure.java
deleted file mode 100644
index 32b39b6..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductStructure.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModel;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-@TableName("product_structure")
-@Data
-@ApiModel(value = "ProductStructure", description = "BOM瀛愯〃")
-public class ProductStructure {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 浜у搧鍚嶇О
-     */
-    private Long productModelId;
-
-    /**
-     * 宸ュ簭id
-     */
-    private Long processId;
-
-    /**
-     * 鍗曚綅浜у嚭闇�瑕佹暟閲�
-     */
-    private BigDecimal unitQuantity;
-
-    /**
-     * 闇�姹傛暟閲�
-     */
-    private BigDecimal demandedQuantity;
-
-    /**
-     * 鍗曚綅
-     */
-    private String unit;
-
-    /**
-     * 绉熸埛ID
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-    /**
-     * 鍏宠仈BOMid
-     */
-    private Integer bomId;
-
-    /**
-     * 鐖惰妭鐐笽D
-     */
-    private Long parentId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java b/src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java
deleted file mode 100644
index 4efc694..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductWorkOrder.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-/**
- * 浜у搧宸ュ崟瀹炰綋绫�
- * 瀵瑰簲鏁版嵁搴撹〃锛歱roduct_work_order
- */
-@Data
-@TableName("product_work_order")
-public class ProductWorkOrder implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 涓婚敭id
-     */
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 宸ヨ壓璺嚎椤圭洰id
-     */
-    @ApiModelProperty(value = "宸ヨ壓璺嚎椤圭洰id")
-    private Long productProcessRouteItemId;
-
-    /**
-     * 鐢熶骇璁㈠崟id
-     */
-    @ApiModelProperty(value = "鐢熶骇璁㈠崟id")
-    private Long productOrderId;
-
-    /**
-     * 鍒涘缓鏃堕棿
-     */
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime createTime;
-
-    /**
-     * 淇敼鏃堕棿
-     */
-    @ApiModelProperty(value = "淇敼鏃堕棿")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime updateTime;
-
-    /**
-     * 宸ュ崟缂栧彿
-     */
-    @ApiModelProperty(value = "宸ュ崟缂栧彿")
-    private String workOrderNo;
-
-    /**
-     * 鐘舵��  1 寰呯‘璁�  2 寰呯敓浜� 3鐢熶骇涓� 4宸插畬鎴�
-     */
-    @ApiModelProperty(value = "鐘舵��  1 寰呯‘璁�  2 寰呯敓浜� 3鐢熶骇涓� 4宸插畬鎴�")
-    private Integer status;
-
-    /**
-     * 绉熸埛id
-     */
-    @ApiModelProperty(value = "绉熸埛id")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-    /**
-     * 璁″垝寮�濮嬫椂闂�
-     */
-    @ApiModelProperty(value = "璁″垝寮�濮嬫椂闂�")
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate planStartTime;
-
-    /**
-     * 璁″垝缁撴潫鏃堕棿
-     */
-    @ApiModelProperty(value = "璁″垝缁撴潫鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate planEndTime;
-
-    /**
-     * 瀹為檯寮�濮嬫椂闂�
-     */
-    @ApiModelProperty(value = "瀹為檯寮�濮嬫椂闂�")
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate actualStartTime;
-
-    /**
-     * 瀹為檯缁撴潫鏃堕棿
-     */
-    @ApiModelProperty(value = "瀹為檯缁撴潫鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @DateTimeFormat(pattern = "yyyy-MM-dd")
-    private LocalDate actualEndTime;
-
-    /**
-     * 闇�姹傞噺
-     */
-    @ApiModelProperty(value = "闇�姹傛暟閲�")
-    private BigDecimal planQuantity;
-
-    /**
-     * 瀹屾垚鏁伴噺
-     */
-    @ApiModelProperty(value = "瀹屾垚鏁伴噺")
-    private BigDecimal completeQuantity;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductWorkOrderFile.java b/src/main/java/com/ruoyi/production/pojo/ProductWorkOrderFile.java
deleted file mode 100644
index 028e1ab..0000000
--- a/src/main/java/com/ruoyi/production/pojo/ProductWorkOrderFile.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import java.io.Serializable;
-import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * <p>
- * 鐢熶骇宸ュ崟闄勪欢琛�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-23 03:28:32
- */
-@Getter
-@Setter
-@TableName("product_work_order_file")
-@ApiModel(value = "ProductWorkOrderFile瀵硅薄", description = "鐢熶骇宸ュ崟闄勪欢琛�")
-public class ProductWorkOrderFile implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty("鍏宠仈宸ュ崟id")
-    private Integer workOrderId;
-
-    @ApiModelProperty("鏂囦欢鍚嶇О")
-    private String name;
-
-    @ApiModelProperty("鏂囦欢璺緞")
-    private String url;
-
-    @ApiModelProperty("鏂囦欢澶у皬")
-    private Integer fileSize;
-
-    @ApiModelProperty("鍒涘缓鏃堕棿")
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
-    @TableField(fill = FieldFill.INSERT)
-    private Long createUser;
-
-    @ApiModelProperty("淇敼鏃堕棿")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    @ApiModelProperty("淇敼鐢ㄦ埛")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private Long updateUser;
-
-    @ApiModelProperty("绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionAccount.java b/src/main/java/com/ruoyi/production/pojo/ProductionAccount.java
new file mode 100644
index 0000000..e205db2
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionAccount.java
@@ -0,0 +1,76 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇鏍哥畻琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_account")
+@Schema(name = "ProductionAccount瀵硅薄", description = "鐢熶骇鏍哥畻琛�")
+public class ProductionAccount implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "閿�鍞彴璐d")
+    private Long salesLedgerId;
+
+    @Schema(description = "閿�鍞骇鍝佽鏍糹d")
+    private Long salesLedgerProductId;
+
+    @Schema(description = "鎶ュ伐琛╥d")
+    private Long productionProductMainId;
+
+    @Schema(description = "鐢熶骇浜篿d")
+    private Long schedulingUserId;
+
+    @Schema(description = "鐢熶骇浜哄悕绉�")
+    private String schedulingUserName;
+
+    @Schema(description = "鐢熶骇鏁伴噺")
+    private BigDecimal finishedNum;
+
+    @Schema(description = "宸ユ椂瀹氶")
+    private BigDecimal workHours;
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String technologyOperationName;
+
+    @Schema(description = "鐢熶骇鏃ユ湡")
+    private LocalDateTime schedulingDate;
+
+    @Schema(description = "鍒涘缓鑰�")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "淇敼鑰�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+
+    @Schema(description = "淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java b/src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java
new file mode 100644
index 0000000..5ba8d22
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionBomStructure.java
@@ -0,0 +1,62 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_bom_structure")
+@Schema(name = "ProductionBomStructure瀵硅薄", description = "鐢熶骇璁㈠崟BOM浜у搧缁撴瀯")
+public class ProductionBomStructure implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鐖惰妭鐐笽D")
+    private Long parentId;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @Schema(description = "宸ュ簭id")
+    private Long technologyOperationId;
+
+    @Schema(description = "鐢熶骇璁㈠崟BOMid")
+    private Long productionOrderBomId;
+
+    @Schema(description = "鍗曚綅浜у嚭闇�瑕佹暟閲�")
+    private BigDecimal unitQuantity;
+
+    @Schema(description = "闇�姹傛暟閲�")
+    private BigDecimal demandedQuantity;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOperationMainParam.java b/src/main/java/com/ruoyi/production/pojo/ProductionOperationMainParam.java
new file mode 100644
index 0000000..08d1807
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOperationMainParam.java
@@ -0,0 +1,95 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇宸ュ崟鎶ュ伐鍙傛暟琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_operation_main_param")
+@Schema(name = "ProductionOperationMainParam瀵硅薄", description = "鐢熶骇宸ュ崟鎶ュ伐鍙傛暟琛�")
+public class ProductionOperationMainParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "宸ヨ壓璺嚎宸ュ簭鍙傛暟琛╥d")
+    private Long technologyRoutingOperationParamId;
+
+    @Schema(description = "鍙傛暟缂栫爜(鍞竴鏍囪瘑)")
+    private String paramCode;
+
+    @Schema(description = "鍙傛暟鍚嶇О")
+    private String paramName;
+
+    @Schema(description = "鍙傛暟绫诲瀷(1鏁板瓧 2鏂囨湰 3涓嬫媺閫夋嫨 4鏃堕棿)")
+    private Byte paramType;
+
+    @Schema(description = "鍙傛暟鏍煎紡")
+    private String paramFormat;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鏄惁蹇呭~")
+    private Byte isRequired;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓浜�")
+    @TableField(fill = FieldFill.INSERT)
+    private String createUser;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "淇敼浜�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String updateUser;
+
+    @Schema(description = "淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "鍩虹鍙傛暟ID")
+    private Long technologyParamId;
+
+    @Schema(description = "宸ュ簭id")
+    private Long technologyOperationId;
+
+    @Schema(description = "宸ュ簭鍙傛暟ID")
+    private Long technologyOperationParamId;
+
+    @Schema(description = "宸ヨ壓璺嚎宸ュ簭ID")
+    private Long technologyRoutingOperationId;
+
+    @Schema(description = "鏍囧噯鍊�")
+    private String standardValue;
+
+    @Schema(description = "杈撳叆鍊�")
+    private String value;
+
+    @Schema(description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟ID")
+    private String productionOrderRoutingOperationParamId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java b/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
new file mode 100644
index 0000000..08399e9
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
@@ -0,0 +1,79 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇宸ュ崟琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_operation_task")
+@Schema(name = "ProductionOperationTask瀵硅薄", description = "鐢熶骇宸ュ崟琛�")
+public class ProductionOperationTask implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鐢熶骇宸ヨ壓璺嚎宸ュ簭琛╥d")
+    private Long productionOrderRoutingOperationId;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "宸ュ崟缂栧彿")
+    private String workOrderNo;
+
+    @Schema(description = "璁″垝寮�濮嬫椂闂�")
+    private LocalDate planStartTime;
+
+    @Schema(description = "璁″垝缁撴潫鏃堕棿")
+    private LocalDate planEndTime;
+
+    @Schema(description = "瀹為檯寮�濮嬫椂闂�")
+    private LocalDate actualStartTime;
+
+    @Schema(description = "瀹為檯缁撴潫鏃堕棿")
+    private LocalDate actualEndTime;
+
+    @Schema(description = "鐘舵�� 1 寰呯‘璁� 2 寰呯敓浜� 3鐢熶骇涓� 4宸茬敓浜�")
+    private Integer status;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "璁″垝鏁伴噺")
+    private BigDecimal planQuantity;
+
+    @Schema(description = "瀹屾垚鏁伴噺")
+    private BigDecimal completeQuantity;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "鏉冮檺鐢ㄦ埛ID鍒楄〃锛屾牸寮忥細[1,2,3]銆傛寚瀹氬涓敤鎴稩D鏃讹紝鐢ㄩ�楀彿鍒嗛殧銆�")
+    private String userIds;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
new file mode 100644
index 0000000..1f882b1
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
@@ -0,0 +1,83 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_order")
+@Schema(name = "ProductionOrder瀵硅薄", description = "鐢熶骇璁㈠崟琛�")
+public class ProductionOrder implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鐢熶骇璁″垝ID鍒楄〃锛屾牸寮忥細[1,2,3]銆傚鏋滄寜鐢熶骇璁″垝鐢熸垚璁㈠崟锛屾柊澧炴椂浼犺繖涓瓧娈靛嵆鍙紝绯荤粺浼氳嚜鍔ㄦ眹鎬讳骇鍝佽鏍煎拰鏁伴噺銆�")
+    private String productionPlanIds;
+
+    @Schema(description = "浜у搧瑙勬牸id銆傛墜鍔ㄦ柊澧炴椂蹇呭~锛涘鏋滀紶浜� productionPlanIds锛屽垯鍙敱绯荤粺鑷姩甯﹀嚭銆�")
+    private Long productModelId;
+
+    @Schema(description = "鐢熶骇璁㈠崟鍙�")
+    private String npsNo;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "宸ヨ壓璺嚎id銆傛柊澧炴椂閫夊~锛屼笉浼犲垯绯荤粺鎸変骇鍝佽鏍艰嚜鍔ㄥ尮閰嶆渶鏂板伐鑹鸿矾绾裤��")
+    private Long technologyRoutingId;
+
+    @Schema(description = "闇�姹傛暟閲忋�傛墜鍔ㄦ柊澧炴椂蹇呭~涓斿繀椤诲ぇ浜� 0锛涘鏋滀紶浜� productionPlanIds锛屽垯鍙敱绯荤粺鑷姩甯﹀嚭銆�")
+    private BigDecimal quantity;
+
+    @Schema(description = "瀹屾垚鏁伴噺")
+    private BigDecimal completeQuantity;
+
+    @Schema(description = "寮�濮嬫棩鏈�")
+    private LocalDateTime startTime;
+
+    @Schema(description = "缁撴潫鏃ユ湡")
+    private LocalDateTime endTime;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "璁″垝瀹屾垚鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate planCompleteTime;
+
+    @Schema(description = "鐘舵�侊紙1.寰呭紑濮� 2.杩涜涓� 3.宸插畬鎴� 4.宸插彇娑� 5.宸茬粨鏉燂級")
+    private Integer status;
+
+    @Schema(description = "鏄惁缁撴潫锛�")
+    @TableField("is_end_order")
+    private Boolean endOrder;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java
new file mode 100644
index 0000000..3915d97
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java
@@ -0,0 +1,53 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_order_bom")
+@Schema(name = "ProductionOrderBom瀵硅薄", description = "鐢熶骇璁㈠崟BOM")
+public class ProductionOrderBom implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @Schema(description = "BOM缂栧彿")
+    private String bomNo;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鐗堟湰鍙�")
+    private String version;
+
+    @Schema(description = "bom鐨刬d")
+    private Long bomId;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java
new file mode 100644
index 0000000..61c5d19
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java
@@ -0,0 +1,85 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 璁㈠崟棰嗘枡绾胯竟浠�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_order_pick")
+@Schema(name = "ProductionOrderPick瀵硅薄", description = "璁㈠崟棰嗘枡绾胯竟浠�")
+public class ProductionOrderPick implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @Schema(description = "鏁伴噺")
+    private BigDecimal quantity;
+
+    @Schema(description = "鎵瑰彿")
+    private String batchNo;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "宸ュ簭id")
+    private Long technologyOperationId;
+
+    @Schema(description = "闇�姹傛暟閲�")
+    private BigDecimal demandedQuantity;
+
+    @Schema(description = "琛ユ枡鎬婚噺")
+    private BigDecimal  feedingQty;
+
+    @Schema(description = "閫�鏂欐暟閲�")
+    private BigDecimal  returnQty;
+
+    @Schema(description = "瀹為檯鏁伴噺")
+    private BigDecimal  actualQty;
+
+    @Schema(description = "鏄惁宸查��鏂�")
+    @TableField("is_returned")
+    private Boolean returned;
+
+    @Schema(description = "鏄惁bom棰嗘枡")
+    @TableField("is_bom")
+    private Boolean bom;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java
new file mode 100644
index 0000000..4f0dc49
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderPickRecord.java
@@ -0,0 +1,78 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 绾胯竟浠撳嚭鍏ュ簱璁板綍
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_order_pick_record")
+@Schema(name = "ProductionOrderPickRecord瀵硅薄", description = "绾胯竟浠撳嚭鍏ュ簱璁板綍")
+public class ProductionOrderPickRecord implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鍏宠仈棰嗘枡鍗昳d锛坧roduction_order_pick.id锛�")
+    private Long pickId;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "鐢熶骇宸ュ崟id")
+    private Long productionOperationTaskId;
+
+    @Schema(description = "浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @Schema(description = "鎵瑰彿")
+    private String batchNo;
+
+    @Schema(description = "棰嗘枡鏁伴噺")
+    private BigDecimal pickQuantity;
+
+    @Schema(description = "棰嗘枡鍓嶆暟閲�")
+    private BigDecimal beforeQuantity;
+
+    @Schema(description = "棰嗘枡鍚庡墿浣欐暟閲�")
+    private BigDecimal afterQuantity;
+
+    @Schema(description = "棰嗘枡绫诲瀷锛�1姝e父棰嗘枡  2琛ユ枡")
+    private Byte pickType;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "琛ユ枡鍘熷洜")
+    private String feedingReason;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java
new file mode 100644
index 0000000..941fb49
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRouting.java
@@ -0,0 +1,64 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_order_routing")
+@Schema(name = "ProductionOrderRouting瀵硅薄", description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎琛�")
+public class ProductionOrderRouting implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "鎻忚堪")
+    private String description;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "宸ヨ壓璺嚎id")
+    private Long technologyRoutingId;
+
+    @Schema(description = "宸ヨ壓璺嚎缂栫爜")
+    private String processRouteCode;
+
+    @Schema(description = "鍩虹bom鐨刬d")
+    private Long bomId;
+
+    @Schema(description = "璁㈠崟bom鐨刬d")
+    private Long orderBomId;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperation.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperation.java
new file mode 100644
index 0000000..fc36725
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperation.java
@@ -0,0 +1,70 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_order_routing_operation")
+@Schema(name = "ProductionOrderRoutingOperation瀵硅薄", description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭琛�")
+public class ProductionOrderRoutingOperation implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "宸ヨ壓璺嚎宸ュ簭琛╥d(棰濆鏂板鐨勬椂鍊欒繖涓瓧娈垫槸绌虹殑)")
+    private Long technologyRoutingOperationId;
+
+    @Schema(description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎id")
+    private Long orderRoutingId;
+
+    @Schema(description = "浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鎷栧姩鎺掑簭")
+    private Integer dragSort;
+
+    @Schema(description = "鏄惁璐ㄦ宸ュ簭")
+    private Boolean isQuality;
+
+    @Schema(description = "鏄惁鐢熶骇")
+    private Boolean isProduction;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "宸ュ簭琛╥d")
+    private Long technologyOperationId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
new file mode 100644
index 0000000..04de53d
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperationParam.java
@@ -0,0 +1,96 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Data
+@TableName("production_order_routing_operation_param")
+@Schema(name = "ProductionOrderRoutingOperationParam瀵硅薄", description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟琛�")
+public class ProductionOrderRoutingOperationParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鐢熶骇璁㈠崟id")
+    private Long productionOrderId;
+
+    @Schema(description = "宸ヨ壓璺嚎宸ュ簭鍙傛暟琛╥d")
+    private Long technologyRoutingOperationParamId;
+
+    @Schema(description = "鍙傛暟缂栫爜(鍞竴鏍囪瘑)")
+    private String paramCode;
+
+    @Schema(description = "鍙傛暟鍚嶇О")
+    private String paramName;
+
+    @Schema(description = "鍙傛暟绫诲瀷(1鏁板瓧 2鏂囨湰 3涓嬫媺閫夋嫨 4鏃堕棿)")
+    private Byte paramType;
+
+    @Schema(description = "鍙傛暟鏍煎紡")
+    private String paramFormat;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鏄惁蹇呭~")
+    private Byte isRequired;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓浜�")
+    @TableField(fill = FieldFill.INSERT)
+    private String createUser;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "淇敼浜�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String updateUser;
+
+    @Schema(description = "淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "鍩虹鍙傛暟ID")
+    private Long paramId;
+
+    @Schema(description = "宸ュ簭id")
+    private Long technologyOperationId;
+
+    @Schema(description = "宸ュ簭鍙傛暟ID")
+    private Long technologyOperationParamId;
+
+    @Schema(description = "鏍囧噯鍊�")
+    private String standardValue;
+
+    @Schema(description = "杈撳叆鍊�")
+    private String inputValue;
+
+    @Schema(description = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭ID")
+    private Long productionOrderRoutingOperationId;
+
+    @Schema(description = "鐢熶骇鎶ュ伐琛↖D")
+    private Long productionProductMainId;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionPlan.java b/src/main/java/com/ruoyi/production/pojo/ProductionPlan.java
new file mode 100644
index 0000000..86b5f4d
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionPlan.java
@@ -0,0 +1,85 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐢熶骇璁″垝琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 02:11:10
+ */
+@Getter
+@Setter
+@TableName("production_plan")
+@Schema(name = "ProductionPlan瀵硅薄", description = "鐢熶骇璁″垝琛�")
+public class ProductionPlan implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "閿�鍞彴璐d")
+    private Long salesLedgerId;
+
+    @Schema(description = "閿�鍞骇鍝佽鏍糹d")
+    private Long salesLedgerProductId;
+
+    @Schema(description = "涓荤敓浜ц鍒掑彿")
+    private String mpsNo;
+
+    @Schema(description = "闇�姹傛棩鏈�")
+    private LocalDate requiredDate;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "淇敼鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "浜у搧鍨嬪彿id")
+    private Long productModelId;
+
+    @Schema(description = "闇�姹傛暟閲�")
+    private BigDecimal qtyRequired;
+
+    @Schema(description = "宸蹭笅鍙戞暟閲�")
+    private BigDecimal quantityIssued;
+
+    @Schema(description = "鏉ユ簮 閿�鍞�/鍐呴儴")
+    private String source;
+
+    @Schema(description = "鎵胯鏃ユ湡")
+    private LocalDate promisedDeliveryDate;
+
+    @Schema(description = "鐘舵�� 0鏈笅鍙� 1閮ㄥ垎涓嬪彂 2宸蹭笅鍙�")
+    private Integer status;
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
index 82bece9..9c6e9d1 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
@@ -1,7 +1,7 @@
 package com.ruoyi.production.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -14,20 +14,38 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鎶ュ伐id")
+    @Schema(description = "鎶ュ伐id")
     private Long productMainId;
 
-    @ApiModelProperty(value = "浜у搧id")
+    @Schema(description = "鐢熶骇鎶ュ伐涓昏〃id")
+    private Long productionProductMainId;
+
+    @Schema(description = "浜у搧id")
     private Long productModelId;
 
-    @ApiModelProperty(value = "鏁伴噺")
+    @Schema(description = "鏁伴噺")
     private BigDecimal quantity;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鎶曞叆鏁伴噺")
+    private BigDecimal inputQuantity;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
+    private Integer createUser;
+
+    @Schema(description = "鏇存柊鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
index 2064e04..0fa00eb 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -16,39 +16,44 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鎶ュ伐鍗曞彿")
+    @Schema(description = "鎶ュ伐鍗曞彿")
     @Excel(name = "鎶ュ伐鍗曞彿")
     private String productNo;
 
-    @ApiModelProperty(value = "鎶ュ伐浜哄憳id")
+    @Schema(description = "鎶ュ伐浜哄憳id")
     private Long userId;
 
-    @ApiModelProperty(value = "鎶ュ伐浜哄憳")
+    @Schema(description = "鎶ュ伐浜哄憳")
     private String userName;
 
-    @ApiModelProperty(value = "鐢熶骇椤圭洰id")
-    private Long productProcessRouteItemId;
+    @Schema(description = "鐢熶骇宸ュ簭宸ュ崟id")
+    private Long productionOperationTaskId;
 
-    @ApiModelProperty(value = "宸ュ崟id")
-    private Long workOrderId;
-
-    @ApiModelProperty(value = "鎶ュ伐鐘舵��")
+    @Schema(description = "鎶ュ伐鐘舵��")
     private Integer status;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "鍒涘缓鏃堕棿")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
+    private Integer createUser;
+
+    @Schema(description = "鏇存柊鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java
index f78df35..5e1daef 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionProductOutput.java
@@ -1,7 +1,7 @@
 package com.ruoyi.production.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -14,23 +14,37 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鎶ュ伐id")
+    @Schema(description = "鎶ュ伐id")
     private Long productMainId;
 
-    @ApiModelProperty(value = "浜у搧id")
+    @Schema(description = "鐢熶骇鎶ュ伐涓昏〃id")
+    private Long productionProductMainId;
+
+    @Schema(description = "浜у搧id")
     private Long productModelId;
 
-    @ApiModelProperty(value = "鎶ュ伐鏁伴噺(鎬绘暟閲�)")
+    @Schema(description = "鍚堟牸鏁伴噺")
     private BigDecimal quantity;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "绉熸埛ID")
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鎶ュ簾鏁伴噺")
+    @Schema(description = "鎶ュ簾鏁伴噺")
     private BigDecimal scrapQty;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @Schema(description = "鏇存柊鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/SalesLedgerProductionAccounting.java b/src/main/java/com/ruoyi/production/pojo/SalesLedgerProductionAccounting.java
deleted file mode 100644
index cb56f29..0000000
--- a/src/main/java/com/ruoyi/production/pojo/SalesLedgerProductionAccounting.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Builder;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-/**
- * @author :yys
- * @date : 2025/7/8 13:24
- */
-@TableName("sales_ledger_production_accounting")
-@Data
-@Builder
-public class SalesLedgerProductionAccounting {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 鎶ュ伐琛╥d
-     */
-    private Long productMainId;
-
-    /**
-     * 鐢熶骇浜篿d
-     */
-    private Long schedulingUserId;
-
-    /**
-     * 鐢熶骇浜哄悕绉�
-     */
-    private String schedulingUserName;
-
-    /**
-     * 鐢熶骇鏁伴噺
-     */
-    private BigDecimal finishedNum;
-
-    /**
-     * 宸ユ椂瀹氶
-     */
-    private BigDecimal workHours;
-
-    /**
-     * 宸ュ簭
-     */
-    private String process;
-    /**
-     * 鐢熶骇鏃ユ湡
-     */
-    private LocalDate schedulingDate;
-
-    /**
-     * 鍒涘缓鑰�
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Integer createUser;
-
-    /**
-     * 鍒涘缓鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    /**
-     * 淇敼鑰�
-     */
-    @TableField(fill = FieldFill.UPDATE)
-    private Integer updateUser;
-
-    /**
-     * 淇敼鏃堕棿
-     */
-    @TableField(fill = FieldFill.UPDATE)
-    private LocalDateTime updateTime;
-
-    /**
-     * 绉熸埛ID
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/SalesLedgerScheduling.java b/src/main/java/com/ruoyi/production/pojo/SalesLedgerScheduling.java
deleted file mode 100644
index ac86061..0000000
--- a/src/main/java/com/ruoyi/production/pojo/SalesLedgerScheduling.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import lombok.Builder;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-/**
- * @author :yys
- * @date : 2025/7/8 13:24
- */
-@TableName("sales_ledger_scheduling")
-@Data
-@Builder
-public class SalesLedgerScheduling {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 閿�鍞彴璐d
-     */
-    private Long salesLedgerId;
-
-    /**
-     * 閿�鍞骇鍝乮d
-     */
-    private Long salesLedgerProductId;
-
-    /**
-     * 娲惧伐浜篿d
-     */
-    private Long schedulingUserId;
-
-    /**
-     * 鐢熶骇鐐掓満
-     */
-    private String speculativeTradingName;
-
-    /**
-     * 浜х嚎
-     */
-    private String productionLine;
-
-    /**
-     * 娲惧伐浜哄悕绉�
-     */
-    private String schedulingUserName;
-
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    private BigDecimal schedulingNum;
-
-    /**
-     * 宸叉帓浜ф暟閲�
-     */
-    private BigDecimal finishedNum;
-    /**
-     * 娲惧伐鏃ユ湡
-     */
-    private LocalDate schedulingDate;
-
-    /**
-     * 鎺掍骇鐘舵�侊紙1-寰呮帓浜� 2-鎺掍骇涓� 3-宸叉帓浜э級
-     */
-    private Integer status;
-
-    /**
-     * 鍒涘缓鑰�
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Integer createUser;
-
-    /**
-     * 鍒涘缓鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    /**
-     * 淇敼鑰�
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private Integer updateUser;
-
-    /**
-     * 淇敼鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    /**
-     * 绉熸埛ID
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/SalesLedgerWork.java b/src/main/java/com/ruoyi/production/pojo/SalesLedgerWork.java
deleted file mode 100644
index 42d9e95..0000000
--- a/src/main/java/com/ruoyi/production/pojo/SalesLedgerWork.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Builder;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-/**
- * @author :yys
- * @date : 2025/7/8 13:24
- */
-@TableName("sales_ledger_work")
-@Data
-@Builder
-public class SalesLedgerWork {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 閿�鍞帓浜ц〃id
-     */
-    private Long salesLedgerSchedulingId;
-
-    /**
-     * 閿�鍞彴璐d
-     */
-    private Long salesLedgerId;
-
-    /**
-     * 閿�鍞骇鍝乮d
-     */
-    private Long salesLedgerProductId;
-
-    /**
-     * 鎺掍骇浜篿d
-     */
-    private Long schedulingUserId;
-
-    /**
-     * 鎺掍骇浜哄悕绉�
-     */
-    private String schedulingUserName;
-
-
-    /**
-     * 鎺掍骇鏁伴噺
-     */
-    private BigDecimal schedulingNum;
-
-    /**
-     * 鐢熶骇鏁伴噺
-     */
-    private BigDecimal finishedNum;
-
-    /**
-     * 宸ユ椂瀹氶
-     */
-    private BigDecimal workHours;
-
-    /**
-     * 宸ュ簭
-     */
-    private String process;
-
-
-    /**
-     * 浜х嚎
-     */
-    private String productionLine;
-    /**
-     * 鎺掍骇鏃ユ湡
-     */
-    private LocalDate schedulingDate;
-
-    /**
-     * 鎶ュ伐鐘舵�侊紙1-寰呯敓浜� 2-鐢熶骇涓� 3-宸叉姤宸ワ級
-     */
-    private Integer status;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    /**
-     * 鎹熻��
-     */
-    private String loss;
-
-    /**
-     * 鍙e懗鍒嗙被
-     */
-    private String type;
-
-    /**
-     * 棰嗙敤
-     */
-    private String receive;
-
-    /**
-     * 鍒涘缓鑰�
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Integer createUser;
-
-    /**
-     * 鍒涘缓鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    /**
-     * 淇敼鑰�
-     */
-    @TableField(fill = FieldFill.UPDATE)
-    private Integer updateUser;
-
-    /**
-     * 淇敼鏃堕棿
-     */
-    @TableField(fill = FieldFill.UPDATE)
-    private LocalDateTime updateTime;
-
-    /**
-     * 绉熸埛ID
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-}
diff --git a/src/main/java/com/ruoyi/production/pojo/SpeculativeTradingInfo.java b/src/main/java/com/ruoyi/production/pojo/SpeculativeTradingInfo.java
deleted file mode 100644
index 4ac0567..0000000
--- a/src/main/java/com/ruoyi/production/pojo/SpeculativeTradingInfo.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.ruoyi.production.pojo;
-
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * @author :yys
- * @date : 2025/11/11 15:38
- */
-@TableName("speculative_trading_info")
-@Data
-public class SpeculativeTradingInfo {
-
-    private static final long serialVersionUID = 1L;
-
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
-    /**
-     * 鐐掓満鍚嶇О
-     */
-    private String name;
-
-    /**
-     * 鐐掓満宸ヤ綔閲�(鍗曚綅kg)
-     */
-    private BigDecimal workLoad;
-
-
-    /**
-     * 鎺掑簭
-     */
-    private Integer sort;
-
-    /**
-     * 鐐掓満姝e湪宸ヤ綔閲�(鍗曚綅kg)
-     */
-    @TableField(exist = false)
-    private BigDecimal currentWorkLoad;
-
-    /**
-     * 鐐掓満绌轰綑宸ヤ綔閲�(鍗曚綅kg)
-     */
-    @TableField(exist = false)
-    private BigDecimal vacant;
-
-    /**
-     * 鍒涘缓鑰�
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Integer createUser;
-
-    /**
-     * 鍒涘缓鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-
-    /**
-     * 淇敼鑰�
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private Integer updateUser;
-
-    /**
-     * 淇敼鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-
-    /**
-     * 绉熸埛ID
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long tenantId;
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProcessRouteItemService.java b/src/main/java/com/ruoyi/production/service/ProcessRouteItemService.java
deleted file mode 100644
index 3299048..0000000
--- a/src/main/java/com/ruoyi/production/service/ProcessRouteItemService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProcessRouteItemDto;
-import com.ruoyi.production.pojo.ProcessRouteItem;
-
-import java.util.List;
-
-public interface ProcessRouteItemService extends IService<ProcessRouteItem> {
-    List<ProcessRouteItemDto> listProcessRouteItemDto( ProcessRouteItemDto processRouteItemDto);
-
-    int sort(ProcessRouteItem processRouteItem);
-
-    String batchDelete(Long id);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProcessRouteService.java b/src/main/java/com/ruoyi/production/service/ProcessRouteService.java
deleted file mode 100644
index 6b408cf..0000000
--- a/src/main/java/com/ruoyi/production/service/ProcessRouteService.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import io.swagger.models.auth.In;
-
-import java.util.List;
-
-public interface ProcessRouteService extends IService<ProcessRoute> {
-
-    IPage<ProcessRouteDto> pageProcessRouteDto(Page<ProcessRouteDto> page, ProcessRouteDto processRouteDto);
-
-    Integer saveProcessRoute(ProcessRoute processRoute);
-
-    int batchDelete(List<Long> ids);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductBomService.java b/src/main/java/com/ruoyi/production/service/ProductBomService.java
deleted file mode 100644
index d812f9f..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductBomService.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.dto.ProductBomDto;
-import com.ruoyi.production.pojo.ProductBom;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * <p>
- * BOM涓昏〃 鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 09:59:27
- */
-public interface ProductBomService extends IService<ProductBom> {
-
-    IPage<ProductBomDto> listPage(Page page, ProductBomDto productBomDto);
-
-    AjaxResult add(ProductBom productBom);
-
-    AjaxResult uploadBom(MultipartFile file);
-
-    void exportBom(HttpServletResponse response, Integer bomId);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductOrderService.java b/src/main/java/com/ruoyi/production/service/ProductOrderService.java
deleted file mode 100644
index 5a714a6..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductOrderService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProductBomDto;
-import com.ruoyi.production.dto.ProductOrderDto;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.pojo.ProcessRoute;
-import com.ruoyi.production.pojo.ProductOrder;
-
-import java.util.List;
-
-
-public interface ProductOrderService extends IService<ProductOrder> {
-
-    IPage<ProductOrderDto> pageProductOrder(Page page, ProductOrderDto productOrder);
-
-    int bindingRoute(ProductOrder productOrder);
-
-    List<ProcessRoute> listProcessRoute(Long productModelId);
-
-    List<ProductStructureDto> listProcessBom(Long orderId);
-
-    Boolean addProductOrder(ProductOrder productOrder);
-
-    Boolean delete(Long[] id);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductProcessRouteItemService.java b/src/main/java/com/ruoyi/production/service/ProductProcessRouteItemService.java
deleted file mode 100644
index c37eea1..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductProcessRouteItemService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductProcessRouteItemDto;
-import com.ruoyi.production.pojo.ProductProcessRouteItem;
-
-import java.util.List;
-
-public interface ProductProcessRouteItemService extends IService<ProductProcessRouteItem> {
-    List<ProductProcessRouteItemDto> listItem(Long orderId);
-
-    R deleteRouteItem(Long id);
-
-    R addRouteItem(ProductProcessRouteItem productProcessRouteItem);
-
-    int sortRouteItem(ProductProcessRouteItem productProcessRouteItem);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductProcessRouteService.java b/src/main/java/com/ruoyi/production/service/ProductProcessRouteService.java
deleted file mode 100644
index 238aa1e..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductProcessRouteService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.pojo.ProductProcessRoute;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- *  鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:51:09
- */
-public interface ProductProcessRouteService extends IService<ProductProcessRoute> {
-
-    ProcessRouteDto listMain(Long orderId);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductProcessService.java b/src/main/java/com/ruoyi/production/service/ProductProcessService.java
deleted file mode 100644
index 8b61bdd..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductProcessService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.device.pojo.DeviceRepair;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.dto.*;
-import com.ruoyi.production.pojo.ProductProcess;
-import com.ruoyi.production.pojo.SalesLedgerScheduling;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:39
- */
-public interface ProductProcessService extends IService<ProductProcess> {
-    IPage<ProductProcessDto> listPage(Page page, ProductProcessDto productProcessDto);
-
-    AjaxResult add(ProductProcessDto productProcessDto);
-
-    AjaxResult importData(MultipartFile file);
-
-    String batchDelete(List<Integer> ids);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductStructureService.java b/src/main/java/com/ruoyi/production/service/ProductStructureService.java
deleted file mode 100644
index ebdddb1..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductStructureService.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.basic.dto.ProductModelDto;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.pojo.ProductStructure;
-
-import java.util.List;
-
-public interface ProductStructureService extends IService<ProductStructure> {
-
-
-    Boolean addProductStructureDto(ProductStructureDto productStructureDto);
-
-    List<ProductStructureDto> listBybomId(Integer bomId);
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductWorkOrderFileService.java b/src/main/java/com/ruoyi/production/service/ProductWorkOrderFileService.java
deleted file mode 100644
index 0df0a8c..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductWorkOrderFileService.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.ruoyi.production.pojo.ProductWorkOrderFile;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-/**
- * <p>
- * 鐢熶骇宸ュ崟闄勪欢琛� 鏈嶅姟绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-23 03:28:32
- */
-public interface ProductWorkOrderFileService extends IService<ProductWorkOrderFile> {
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductWorkOrderService.java b/src/main/java/com/ruoyi/production/service/ProductWorkOrderService.java
deleted file mode 100644
index 8ef28e6..0000000
--- a/src/main/java/com/ruoyi/production/service/ProductWorkOrderService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProductWorkOrderDto;
-import com.ruoyi.production.pojo.ProductWorkOrder;
-
-import javax.servlet.http.HttpServletResponse;
-
-public interface ProductWorkOrderService extends IService<ProductWorkOrder>{
-
-    IPage<ProductWorkOrderDto> listPage(Page<ProductWorkOrderDto> page, ProductWorkOrderDto productWorkOrder);
-
-    int updateProductWorkOrder(ProductWorkOrderDto productWorkOrderDto);
-
-    void down(HttpServletResponse response, ProductWorkOrder productWorkOrder);
-}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionAccountService.java b/src/main/java/com/ruoyi/production/service/ProductionAccountService.java
new file mode 100644
index 0000000..a02c3a4
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionAccountService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.pojo.ProductionAccount;
+
+/**
+ * <p>
+ * 鐢熶骇鏍哥畻琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+public interface ProductionAccountService extends IService<ProductionAccount> {
+    IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto);
+
+    IPage<ProductionProductMainDto> listProductionDetails(ProductionAccountDto productionAccountDto, Page page);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java b/src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java
new file mode 100644
index 0000000..6e63dfe
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionBomStructureService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.dto.ProductionBomStructureDto;
+import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
+import com.ruoyi.production.pojo.ProductionBomStructure;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+public interface ProductionBomStructureService extends IService<ProductionBomStructure> {
+
+    List<ProductionBomStructureVo> listByBomId(Long bomId);
+
+    Boolean addProductionBomStructure(ProductionBomStructureDto productionBomStructureDto);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOperationMainParamService.java b/src/main/java/com/ruoyi/production/service/ProductionOperationMainParamService.java
new file mode 100644
index 0000000..d05f4e2
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOperationMainParamService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.pojo.ProductionOperationMainParam;
+
+/**
+ * <p>
+ * 鐢熶骇宸ュ崟鎶ュ伐鍙傛暟琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+public interface ProductionOperationMainParamService extends IService<ProductionOperationMainParam> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
new file mode 100644
index 0000000..0945c6a
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
+import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.util.List;
+
+public interface ProductionOperationTaskService extends IService<ProductionOperationTask> {
+
+    IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page,
+                                                                 ProductionOperationTaskDto productionOperationTaskDto);
+
+    List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto productionOperationTaskDto);
+
+    ProductionOperationTaskVo getProductionOperationTaskInfo(Long id);
+
+    boolean saveProductionOperationTask(ProductionOperationTask productionOperationTask);
+
+    boolean removeProductionOperationTask(List<Long> ids);
+
+    int updateProductWorkOrder(ProductionOperationTaskDto dto);
+
+    boolean assign(ProductionOperationTaskDto dto);
+
+    void down(HttpServletResponse response, ProductionOperationTaskDto dto);
+
+    List<ProductionOperationTaskVo> getOperation(ProductionOperationTaskDto dto);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java
new file mode 100644
index 0000000..da4f9fc
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderBomService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.pojo.ProductionOrderBom;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+public interface ProductionOrderBomService extends IService<ProductionOrderBom> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java
new file mode 100644
index 0000000..ebd6e27
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderPickRecordService.java
@@ -0,0 +1,21 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
+import com.ruoyi.production.pojo.ProductionOrderPickRecord;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 绾胯竟浠撳嚭鍏ュ簱璁板綍 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+public interface ProductionOrderPickRecordService extends IService<ProductionOrderPickRecord> {
+
+    List<ProductionOrderPickRecordVo> listFeedingRecord(ProductionOrderPickRecordDto dto);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java
new file mode 100644
index 0000000..82ee298
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderPickService.java
@@ -0,0 +1,25 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.pojo.ProductionOrderPick;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 璁㈠崟棰嗘枡绾胯竟浠� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+public interface ProductionOrderPickService extends IService<ProductionOrderPick> {
+
+    Boolean savePick(ProductionOrderPickDto dto);
+
+    Boolean updatePick(ProductionOrderPickDto dto);
+
+    List<ProductionOrderPickVo> listPickedDetail(Long productionOrderId);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationParamService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationParamService.java
new file mode 100644
index 0000000..25efddb
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationParamService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.dto.ProductionOrderRoutingOperationParamDto;
+import com.ruoyi.production.bean.vo.ProductionOrderRoutingOperationParamVo;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+public interface ProductionOrderRoutingOperationParamService extends IService<ProductionOrderRoutingOperationParam> {
+
+    IPage<ProductionOrderRoutingOperationParamVo> pageProductionOrderRoutingOperationParam(Page<ProductionOrderRoutingOperationParamDto> page,
+                                                                                           ProductionOrderRoutingOperationParamDto dto);
+
+    List<ProductionOrderRoutingOperationParamVo> listProductionOrderRoutingOperationParam(ProductionOrderRoutingOperationParamDto dto);
+
+    ProductionOrderRoutingOperationParamVo getProductionOrderRoutingOperationParamInfo(Long id);
+
+    boolean saveProductionOrderRoutingOperationParam(ProductionOrderRoutingOperationParam item);
+
+    boolean removeProductionOrderRoutingOperationParam(Long id);
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java
new file mode 100644
index 0000000..2377dc3
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingOperationService.java
@@ -0,0 +1,14 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+
+public interface ProductionOrderRoutingOperationService extends IService<ProductionOrderRoutingOperation> {
+
+    R addRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation);
+
+    R deleteRouteItem(Long id);
+
+    int sortRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingService.java
new file mode 100644
index 0000000..de011ef
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderRoutingService.java
@@ -0,0 +1,14 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.vo.ProductionOrderRoutingOperationVo;
+import com.ruoyi.production.pojo.ProductionOrderRouting;
+
+import java.util.List;
+
+public interface ProductionOrderRoutingService extends IService<ProductionOrderRouting> {
+
+    ProductionOrderRouting listMain(Long orderId);
+
+    List<ProductionOrderRoutingOperationVo> listItem(Long orderId);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionOrderService.java b/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
new file mode 100644
index 0000000..deeb0dd
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionOrderService.java
@@ -0,0 +1,38 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.dto.ProductionOrderDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.bean.vo.ProductionOrderVo;
+import com.ruoyi.production.bean.vo.ProductionPlanVo;
+import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo;
+import com.ruoyi.production.pojo.ProductionOrder;
+
+import java.util.List;
+
+public interface ProductionOrderService extends IService<ProductionOrder> {
+
+    IPage<ProductionOrderVo> pageProductionOrder(Page<ProductionOrderDto> page, ProductionOrderDto productionOrderDto);
+
+    List<ProductionOrderVo> listProductionOrder(ProductionOrderDto productionOrderDto);
+
+    ProductionOrderVo getProductionOrderInfo(Long id);
+
+    boolean saveProductionOrder(ProductionOrder productionOrder);
+
+    boolean removeProductionOrder(List<Long> ids);
+
+    int syncProductionOrderSnapshot(Long productionOrderId);
+
+    Object bindingRoute(ProductionOrderDto productionOrderDto);
+
+    List<ProductionPlanVo> getSource(Long id);
+
+    List<ProductionOrderPickVo> pick(Long productionOrderId);
+
+    ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(ProductionOrderDto productionOrderDto);
+
+    int updateOrder(ProductionOrderDto productionOrderDto);
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionPlanService.java b/src/main/java/com/ruoyi/production/service/ProductionPlanService.java
new file mode 100644
index 0000000..052676b
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/ProductionPlanService.java
@@ -0,0 +1,56 @@
+package com.ruoyi.production.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.bean.dto.ProductionPlanDto;
+import com.ruoyi.production.bean.vo.ProductionPlanVo;
+import com.ruoyi.production.pojo.ProductionPlan;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐢熶骇璁″垝琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 02:11:10
+ */
+public interface ProductionPlanService extends IService<ProductionPlan> {
+
+    IPage<ProductionPlanVo> listPage(Page<ProductionPlanDto> page, ProductionPlanDto productionPlanDto);
+
+    /**
+     * 鍚堝苟鐢熶骇璁″垝
+     */
+    boolean combine(ProductionPlanDto productionPlanDto);
+
+    /**
+     * 鍒涘缓鐢熶骇璁″垝
+     */
+    boolean add(ProductionPlanDto productionPlanDto);
+
+    /**
+     * 鏇存柊鐢熶骇璁″垝
+     */
+    boolean update(ProductionPlanDto productionPlanDto);
+
+    /**
+     * 鍒犻櫎鐢熶骇璁″垝
+     */
+    boolean delete(List<Long> ids);
+
+    /**
+     * 瀵煎叆鏁版嵁
+     */
+    void importProdData(MultipartFile file);
+
+    /**
+     * 瀵煎嚭鏁版嵁
+     */
+    void exportProdData(HttpServletResponse response, List<Long> ids);
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductionProductInputService.java b/src/main/java/com/ruoyi/production/service/ProductionProductInputService.java
index 1af1772..42afd89 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionProductInputService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionProductInputService.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProductionProductInputDto;
+import com.ruoyi.production.bean.dto.ProductionProductInputDto;
 import com.ruoyi.production.pojo.ProductionProductInput;
 
 public interface ProductionProductInputService extends IService<ProductionProductInput> {
diff --git a/src/main/java/com/ruoyi/production/service/ProductionProductMainService.java b/src/main/java/com/ruoyi/production/service/ProductionProductMainService.java
index 72d868c..6a07d2b 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionProductMainService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionProductMainService.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
 import com.ruoyi.production.pojo.ProductionProductMain;
 
 import java.util.ArrayList;
@@ -12,8 +12,14 @@
 public interface ProductionProductMainService extends IService<ProductionProductMain> {
     IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto);
 
+    IPage<ProductionProductMainDto> pageProductionProductMain(Page page, ProductionProductMainDto productionProductMainDto);
+
+    ProductionProductMainDto getProductionProductMainInfo(Long id);
+
     Boolean addProductMain(ProductionProductMainDto productionProductMainDto);
 
+    Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto);
+
     Boolean removeProductMain(Long id);
 
     ArrayList<Long> listMain(List<Long> idList);
diff --git a/src/main/java/com/ruoyi/production/service/ProductionProductOutputService.java b/src/main/java/com/ruoyi/production/service/ProductionProductOutputService.java
index dea72b5..b01ae0d 100644
--- a/src/main/java/com/ruoyi/production/service/ProductionProductOutputService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductionProductOutputService.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProductionProductOutputDto;
+import com.ruoyi.production.bean.dto.ProductionProductOutputDto;
 import com.ruoyi.production.pojo.ProductionProductOutput;
 
 public interface ProductionProductOutputService extends IService<ProductionProductOutput> {
diff --git a/src/main/java/com/ruoyi/production/service/SalesLedgerProductionAccountingService.java b/src/main/java/com/ruoyi/production/service/SalesLedgerProductionAccountingService.java
index 4ebd01f..9f844f1 100644
--- a/src/main/java/com/ruoyi/production/service/SalesLedgerProductionAccountingService.java
+++ b/src/main/java/com/ruoyi/production/service/SalesLedgerProductionAccountingService.java
@@ -1,27 +1,8 @@
 package com.ruoyi.production.service;
 
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProductionProductMainDto;
-import com.ruoyi.production.dto.SalesLedgerProductionAccountingDto;
-import com.ruoyi.production.dto.UserAccountDto;
-import com.ruoyi.production.dto.UserProductionAccountingDto;
-import com.ruoyi.production.pojo.SalesLedgerProductionAccounting;
+import com.ruoyi.production.bean.dto.UserAccountDto;
+import com.ruoyi.production.bean.dto.UserProductionAccountingDto;
 
-/**
- * @author :yys
- * @date : 2025/7/21 14:39
- */
-public interface SalesLedgerProductionAccountingService extends IService<SalesLedgerProductionAccounting> {
-
-
-    IPage<SalesLedgerProductionAccountingDto> listPage(Page page, SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto);
-
-
-    IPage<SalesLedgerProductionAccountingDto> pageProductionAccounting(SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page);
-
-    IPage<ProductionProductMainDto> listProductionDetails(SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page);
-
-    UserAccountDto getByUserId(UserProductionAccountingDto userProductionAccountingDto);
+public interface SalesLedgerProductionAccountingService {
+    UserAccountDto getByUserId(UserProductionAccountingDto dto);
 }
diff --git a/src/main/java/com/ruoyi/production/service/SalesLedgerSchedulingService.java b/src/main/java/com/ruoyi/production/service/SalesLedgerSchedulingService.java
deleted file mode 100644
index 813553a..0000000
--- a/src/main/java/com/ruoyi/production/service/SalesLedgerSchedulingService.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.production.dto.ProcessSchedulingDto;
-import com.ruoyi.production.dto.ProductionDispatchAddDto;
-import com.ruoyi.production.dto.SalesLedgerSchedulingDto;
-import com.ruoyi.production.dto.SalesLedgerSchedulingProcessDto;
-import com.ruoyi.production.pojo.SalesLedgerScheduling;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:39
- */
-public interface SalesLedgerSchedulingService extends IService<SalesLedgerScheduling> {
-
-    IPage<SalesLedgerSchedulingDto> listPage(Page page, SalesLedgerSchedulingDto salesLedgerSchedulingDto);
-
-    void export(HttpServletResponse response);
-
-    String productionDispatch(List<ProductionDispatchAddDto> productionDispatchAddDto);
-
-    IPage<SalesLedgerSchedulingProcessDto> listPageProcess(Page page, SalesLedgerSchedulingProcessDto salesLedgerSchedulingDto);
-
-    int productionDispatchDelete(List<Long> ids);
-
-    int processScheduling(List<ProcessSchedulingDto> processSchedulingDto);
-
-    void exportOne(HttpServletResponse response);
-}
diff --git a/src/main/java/com/ruoyi/production/service/SalesLedgerWorkService.java b/src/main/java/com/ruoyi/production/service/SalesLedgerWorkService.java
deleted file mode 100644
index b219515..0000000
--- a/src/main/java/com/ruoyi/production/service/SalesLedgerWorkService.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.production.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.dto.ProductionReportDto;
-import com.ruoyi.production.dto.SalesLedgerWorkDto;
-import com.ruoyi.production.pojo.SalesLedgerWork;
-
-import java.util.List;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:38
- */
-public interface SalesLedgerWorkService extends IService<SalesLedgerWork> {
-
-    IPage<SalesLedgerWorkDto> listPage(Page page, SalesLedgerWorkDto salesLedgerWorkDto);
-
-    int productionReport(ProductionReportDto productionReportDto);
-
-    int productionReportUpdate(ProductionReportDto productionReportDto);
-
-    List<ProductionReportDto> getList(Long id);
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProcessRouteItemServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProcessRouteItemServiceImpl.java
deleted file mode 100644
index 5614366..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProcessRouteItemServiceImpl.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.production.dto.ProcessRouteItemDto;
-import com.ruoyi.production.mapper.ProcessRouteItemMapper;
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import com.ruoyi.production.service.ProcessRouteItemService;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-@Transactional(rollbackFor = Exception.class)
-public class ProcessRouteItemServiceImpl extends ServiceImpl<ProcessRouteItemMapper, ProcessRouteItem> implements ProcessRouteItemService {
-
-    @Autowired
-    private  ProcessRouteItemMapper processRouteItemMapper;
-
-    @Override
-    public List<ProcessRouteItemDto> listProcessRouteItemDto(ProcessRouteItemDto processRouteItemDto) {
-        return processRouteItemMapper.listProcessRouteItemDto( processRouteItemDto);
-    }
-
-    //鎺掑簭
-    @Override
-    public int sort(ProcessRouteItem processRouteItem) {
-        //鏌ヨ琚敼鍔ㄧ殑杩欐潯鏁版嵁
-        ProcessRouteItem oldProcessRouteItem = processRouteItemMapper.selectById(processRouteItem.getId());
-        //鏌ヨ璇ュ伐鑹鸿矾绾跨殑鎵�鏈夊伐搴忓苟鎸夌収椤哄簭鎺掑簭
-        List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(Wrappers.<ProcessRouteItem>lambdaQuery()
-                .eq(ProcessRouteItem::getRouteId, oldProcessRouteItem.getRouteId())
-                .orderByAsc(ProcessRouteItem::getDragSort));
-        // 鑾峰彇鐩爣浣嶇疆锛堢Щ鍔ㄥ埌绗嚑涓箣鍚庯級
-        Integer targetPosition = processRouteItem.getDragSort();
-        if (targetPosition != null && targetPosition >= 0) {
-            // 绉诲姩鍏冪礌鍒版柊鐨勪綅缃�
-            processRouteItems.remove(oldProcessRouteItem);
-            processRouteItems.add(targetPosition-1, oldProcessRouteItem);
-            // 鏇存柊鎵�鏈夊彈褰卞搷鐨勬帓搴忓瓧娈�
-            for (int i = 0; i < processRouteItems.size(); i++) {
-                ProcessRouteItem item = processRouteItems.get(i);
-                if (!item.getId().equals(oldProcessRouteItem.getId())) {
-                    // 妫�鏌ユ槸鍚﹂渶瑕佹洿鏂版帓搴忓��
-                    if (item.getDragSort() != i+1) {
-                        item.setDragSort(i+1);
-                        processRouteItemMapper.updateById(item);
-                    }
-                } else {
-                    // 鏇存柊鍘熻褰曠殑鏂版帓搴忎綅缃�
-                    oldProcessRouteItem.setDragSort(targetPosition);
-                    processRouteItemMapper.updateById(oldProcessRouteItem);
-                }
-            }
-            return 1;
-        }
-        return 0;
-    }
-
-    @Override
-    public String batchDelete(Long id) {
-        // 鏌ヨ瑕佸垹闄ょ殑鏁版嵁
-        ProcessRouteItem deleteProcessRouteItem = processRouteItemMapper.selectById(id);
-        if (deleteProcessRouteItem == null) {
-            return "鍒犻櫎澶辫触锛屾湭鎵惧埌瀵瑰簲鏁版嵁";
-        }
-        Long routeId = deleteProcessRouteItem.getRouteId();
-        // 鍒犻櫎鎸囧畾鏁版嵁
-        processRouteItemMapper.deleteById(id);
-        // 鏌ヨ璇ュ伐鑹鸿矾绾跨殑鎵�鏈夊伐搴忓苟鎸夌収椤哄簭鎺掑簭
-        List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(Wrappers.<ProcessRouteItem>lambdaQuery()
-                .eq(ProcessRouteItem::getRouteId, routeId)
-                .orderByAsc(ProcessRouteItem::getDragSort));
-        // 閲嶆柊璁剧疆鎺掑簭鍊硷紝浣垮簭鍙疯繛缁�
-        for (int i = 0; i < processRouteItems.size(); i++) {
-            ProcessRouteItem item = processRouteItems.get(i);
-            if (!item.getDragSort().equals(i+1)) {
-                item.setDragSort(i+1);
-                processRouteItemMapper.updateById(item);
-            }
-        }
-        return "鍒犻櫎鎴愬姛";
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProcessRouteServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProcessRouteServiceImpl.java
deleted file mode 100644
index b3beded..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProcessRouteServiceImpl.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.mapper.ProcessRouteItemMapper;
-import com.ruoyi.production.mapper.ProcessRouteMapper;
-import com.ruoyi.production.mapper.ProductOrderMapper;
-import com.ruoyi.production.mapper.ProductProcessRouteMapper;
-import com.ruoyi.production.pojo.ProcessRoute;
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import com.ruoyi.production.pojo.ProductOrder;
-import com.ruoyi.production.pojo.ProductProcessRoute;
-import com.ruoyi.production.service.ProcessRouteService;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.Arrays;
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-@Slf4j
-public class ProcessRouteServiceImpl extends ServiceImpl<ProcessRouteMapper, ProcessRoute> implements ProcessRouteService {
-
-    @Autowired
-    private ProcessRouteMapper processRouteMapper;
-
-    @Autowired
-    private ProcessRouteItemMapper processRouteItemMapper;
-
-    @Autowired
-    private ProductOrderMapper productOrderMapper;
-
-    @Override
-    public IPage<ProcessRouteDto> pageProcessRouteDto(Page<ProcessRouteDto> page, ProcessRouteDto processRouteDto) {
-
-        return processRouteMapper.pageProcessRouteDto(page, processRouteDto);
-    }
-
-    @Override
-    public Integer saveProcessRoute(ProcessRoute processRoute) {
-        this.save(processRoute);
-        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
-        String idStr = String.format("%06d", processRoute.getId());
-        String newProductCode = "GYLX" + dateStr + idStr;
-        // 鏇存柊鏁版嵁搴撲腑鐨刾roductCode
-        processRoute.setProcessRouteCode(newProductCode);
-        return processRouteMapper.updateById(processRoute);
-    }
-
-    @Override
-    public int batchDelete(List<Long> ids) {
-        //鍏堝垽鏂槸鍚﹀凡缁忓紩鐢ㄤ簡
-        List<ProductOrder> productOrders = productOrderMapper.selectList(Wrappers.<ProductOrder>lambdaQuery().in(ProductOrder::getRouteId, ids));
-        if (productOrders.size()>0){
-            throw new RuntimeException("璇ュ伐鑹鸿矾绾跨敓浜у凡寮曠敤锛屼笉鑳藉垹闄�");
-        }
-        //鍒犻櫎宸ヨ壓璺嚎璇︽儏
-        processRouteItemMapper.delete(Wrappers.<ProcessRouteItem>lambdaQuery().in(ProcessRouteItem::getRouteId, ids));
-        return processRouteMapper.deleteBatchIds(ids);
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
deleted file mode 100644
index 2554b5e..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
+++ /dev/null
@@ -1,318 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.pojo.Product;
-import com.ruoyi.basic.pojo.ProductModel;
-import com.ruoyi.basic.service.IProductModelService;
-import com.ruoyi.basic.service.IProductService;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.dto.BomImportDto;
-import com.ruoyi.production.dto.ProductBomDto;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.mapper.ProductBomMapper;
-import com.ruoyi.production.pojo.ProductBom;
-import com.ruoyi.production.pojo.ProductProcess;
-import com.ruoyi.production.pojo.ProductStructure;
-import com.ruoyi.production.service.ProductBomService;
-import com.ruoyi.production.service.ProductProcessService;
-import com.ruoyi.production.service.ProductStructureService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * <p>
- * BOM涓昏〃 鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 09:59:27
- */
-@Service
-public class ProductBomServiceImpl extends ServiceImpl<ProductBomMapper, ProductBom> implements ProductBomService {
-
-    @Autowired
-    private IProductService productService;
-
-    @Autowired
-    private ProductBomMapper productBomMapper;
-
-
-    @Autowired
-    private IProductModelService productModelService;
-
-    @Autowired
-    private ProductStructureService productStructureService;
-
-    @Autowired
-    private ProductProcessService productProcessService;
-
-    @Override
-    public IPage<ProductBomDto> listPage(Page page, ProductBomDto productBomDto) {
-        return productBomMapper.listPage(page, productBomDto);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public AjaxResult add(ProductBom productBom) {
-        boolean save = productBomMapper.insert(productBom) > 0;
-        if (save) {
-            String no = "BM." + String.format("%05d", productBom.getId());
-            productBom.setBomNo(no);
-            productBomMapper.updateById(productBom);
-
-            //  鏌ヨ鍑轰骇鍝佹ā鍨嬩俊鎭�
-            if (productBom.getProductModelId() == null) {
-                throw new ServiceException("璇烽�夋嫨浜у搧妯″瀷");
-            }
-
-            ProductModel productModel = productModelService.getById(productBom.getProductModelId());
-            if (productModel == null) {
-                throw new ServiceException("閫夋嫨鐨勪骇鍝佹ā鍨嬩笉瀛樺湪");
-            }
-
-            //  娣诲姞鍒濆鐨勪骇鍝佺粨鏋�
-            ProductStructure productStructure = new ProductStructure();
-            productStructure.setProductModelId(productBom.getProductModelId());
-            productStructure.setUnit(productModel.getUnit());
-            productStructure.setUnitQuantity(BigDecimal.valueOf(1));
-            productStructure.setBomId(productBom.getId());
-
-            productStructureService.save(productStructure);
-
-            return AjaxResult.success();
-        }
-        return AjaxResult.error();
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public AjaxResult uploadBom(MultipartFile file) {
-        ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class);
-        List<BomImportDto> list;
-        try {
-            list = util.importExcel(file.getInputStream());
-        } catch (Exception e) {
-            return AjaxResult.error("Excel瑙f瀽澶辫触");
-        }
-
-        if (list == null || list.isEmpty()) return AjaxResult.error("鏁版嵁涓虹┖");
-
-        //  澶勭悊宸ュ簭
-        list.forEach(dto -> {
-            dto.setParentName(clean(dto.getParentName()));
-            dto.setParentSpec(clean(dto.getParentSpec()));
-            dto.setChildName(clean(dto.getChildName()));
-            dto.setChildSpec(clean(dto.getChildSpec()));
-        });
-        handleProcess(list);
-        Map<String, Long> processMap = productProcessService.list().stream()
-                .collect(Collectors.toMap(ProductProcess::getName, ProductProcess::getId, (k1, k2) -> k1));
-
-        //  鍒涘缓 BOM 鏁版嵁
-        BomImportDto first = list.get(0);
-        ProductModel rootModel = findModel(first.getParentName(), first.getParentSpec());
-        ProductBom bom = new ProductBom();
-        bom.setProductModelId(rootModel.getId());
-        bom.setVersion("1.0");
-        productBomMapper.insert(bom);
-        bom.setBomNo("BM." + String.format("%05d", bom.getId()));
-        productBomMapper.updateById(bom);
-
-        // 璁板綍宸茬粡鎻掑叆缁撴瀯鐨勮妭鐐癸細Key = "鍚嶇О+瑙勬牸", Value = structure_id
-        Map<String, Long> treePathMap = new HashMap<>();
-
-        for (int i = 0; i < list.size(); i++) {
-            BomImportDto dto = list.get(i);
-            String parentKey = dto.getParentName() + "|" + dto.getParentSpec();
-            String childKey = dto.getChildName() + "|" + dto.getChildSpec();
-
-            //澶勭悊鏍硅妭鐐�,绗竴琛屼笖瀛愰」涓虹┖
-            if (i == 0 && StringUtils.isBlank(dto.getChildName())) {
-                ProductStructure rootNode = new ProductStructure();
-                rootNode.setBomId(bom.getId());
-                rootNode.setParentId(null); // 椤跺眰娌℃湁鐖惰妭鐐�
-                rootNode.setProductModelId(rootModel.getId());
-                rootNode.setUnitQuantity(BigDecimal.ONE);
-                rootNode.setUnit(rootModel.getUnit());
-                productStructureService.save(rootNode);
-
-                treePathMap.put(parentKey, rootNode.getId());
-                continue;
-            }
-
-            //  澶勭悊瀛愬眰绾ц妭鐐�
-            //  鎵惧埌鐖惰妭鐐瑰湪鏁版嵁搴撻噷鐨� ID
-            Long parentStructureId = treePathMap.get(parentKey);
-            if (parentStructureId == null) {
-                // 濡傛灉 Map 閲屾壘涓嶅埌锛岃鏄� Excel 椤哄簭涔变簡鎴栬�呮暟鎹湁璇�
-                throw new ServiceException("瀵煎叆澶辫触: 鐖堕」[" + dto.getParentName() + "]蹇呴』鍦ㄥ叾瀛愰」涔嬪墠瀹氫箟");
-            }
-
-            //  鑾峰彇瀛愰」妯″瀷淇℃伅
-            ProductModel childModel = findModel(dto.getChildName(), dto.getChildSpec());
-
-            //  鎻掑叆缁撴瀯琛�
-            ProductStructure node = new ProductStructure();
-            node.setBomId(bom.getId());
-            node.setParentId(parentStructureId); // 鐖惰妭鐐笽D
-            node.setProductModelId(childModel.getId());
-            node.setUnitQuantity(dto.getUnitQty());
-            node.setUnit(childModel.getUnit());
-            if (processMap.containsKey(dto.getProcess())) {
-                node.setProcessId(processMap.get(dto.getProcess()));
-            }
-            productStructureService.save(node);
-
-            //  鎶婂綋鍓嶅瓙椤硅褰曞埌 Map,浣滀负浠ュ悗鏇存繁灞傜骇鐨勭埗椤规煡鎵句緷鎹�
-            //  鍚屼竴鐖堕」涓嬬殑鍚屽悕瀛愰」涓嶉渶瑕侀噸澶嶈褰�
-            treePathMap.put(childKey, node.getId());
-        }
-
-        return AjaxResult.success("BOM瀵煎叆鎴愬姛");
-    }
-
-
-    @Override
-    public void exportBom(HttpServletResponse response, Integer bomId) {
-        if (bomId == null) {
-            return;
-        }
-
-        List<ProductStructureDto> treeData = productStructureService.listBybomId(bomId);
-        if (treeData == null || treeData.isEmpty()) {
-            return;
-        }
-
-        //  灏嗘爲褰㈢粨鏋勬墎骞冲寲 浣跨敤 BFS绠楁硶 瀵煎嚭,鎸夊眰绾ч『搴�
-        List<BomImportDto> exportList = new ArrayList<>();
-
-        // Map<ID, Node> idMap 鐢ㄤ簬鏌ユ壘鐖惰妭鐐�
-        Map<Long, ProductStructureDto> idMap = new HashMap<>();
-        populateMap(treeData, idMap);
-
-        //  treeData 鐨勭涓�涓槸鏍硅妭鐐�
-        for (ProductStructureDto root : treeData) {
-            //  娣诲姞鏍硅妭鐐�
-            BomImportDto rootRow = new BomImportDto();
-            rootRow.setParentName(root.getProductName());
-            rootRow.setParentSpec(root.getModel());
-            rootRow.setUnitQty(root.getUnitQuantity());
-            rootRow.setRemark("");
-            exportList.add(rootRow);
-
-            //  BFS 閬嶅巻-闃熷垪
-            Queue<ProductStructureDto> queue = new LinkedList<>();
-            if (root.getChildren() != null) {
-                queue.addAll(root.getChildren());
-            }
-
-            while (!queue.isEmpty()) {
-                ProductStructureDto child = queue.poll();
-
-                // 鏌ユ壘鐖惰妭鐐�
-                ProductStructureDto parent = idMap.get(child.getParentId());
-                if (parent == null) {
-                    // 闄や簡鏈�澶栧眰鑺傜偣,鍏朵粬鑺傜偣鐨勭埗绫昏偗瀹氭槸涓嶄細涓虹┖鐨�
-                    continue;
-                }
-
-                BomImportDto row = new BomImportDto();
-                // 鐖剁被淇℃伅
-                row.setParentName(parent.getProductName());
-                row.setParentSpec(parent.getModel());
-                // 瀛愮被淇℃伅
-                row.setChildName(child.getProductName());
-                row.setChildSpec(child.getModel());
-                row.setUnitQty(child.getUnitQuantity());
-                row.setProcess(child.getProcessName());
-
-                exportList.add(row);
-
-                //  灏嗗瓙鑺傜偣鐨勫瓙鑺傜偣鍔犲叆闃熷垪-涓嬩竴灞�
-                if (child.getChildren() != null && !child.getChildren().isEmpty()) {
-                    queue.addAll(child.getChildren());
-                }
-            }
-        }
-
-        ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class);
-        util.exportExcel(response, exportList, "BOM缁撴瀯瀵煎嚭");
-    }
-
-    private void populateMap(List<ProductStructureDto> nodes, Map<Long, ProductStructureDto> map) {
-        if (nodes == null || nodes.isEmpty()) {
-            return;
-        }
-        for (ProductStructureDto node : nodes) {
-            map.put(node.getId(), node);
-            populateMap(node.getChildren(), map);
-        }
-    }
-
-    private ProductModel findModel(String name, String spec) {
-        Product product = productService.getOne(new LambdaQueryWrapper<Product>()
-                .eq(Product::getProductName, name).last("limit 1"));
-        if (product == null) throw new ServiceException("浜у搧鏈淮鎶わ細" + name);
-
-        ProductModel model = productModelService.getOne(new LambdaQueryWrapper<ProductModel>()
-                .eq(ProductModel::getProductId, product.getId())
-                .eq(ProductModel::getModel, spec).last("limit 1"));
-        if (model == null) throw new ServiceException("瑙勬牸鏈淮鎶わ細" + name + "[" + spec + "]");
-        return model;
-    }
-
-    private void handleProcess(List<BomImportDto> list) {
-
-        Set<String> processNames = list.stream()
-                .map(BomImportDto::getProcess)
-                .filter(StringUtils::isNotBlank)
-                .collect(Collectors.toSet());
-
-        if (processNames.isEmpty()) {
-            return;
-        }
-
-        List<ProductProcess> exists = productProcessService.list(
-                new LambdaQueryWrapper<ProductProcess>().in(ProductProcess::getName, processNames)
-        );
-
-        Set<String> existNames = exists.stream()
-                .map(ProductProcess::getName)
-                .collect(Collectors.toSet());
-
-        List<ProductProcess> needSave = processNames.stream()
-                .filter(n -> !existNames.contains(n))
-                .map(n -> {
-                    ProductProcess p = new ProductProcess();
-                    p.setName(n);
-                    return p;
-                })
-                .collect(Collectors.toList());
-
-        if (!needSave.isEmpty()) {
-            productProcessService.saveBatch(needSave);
-            needSave.forEach(p -> p.setNo("GX" + String.format("%08d", p.getId())));
-            productProcessService.updateBatchById(needSave);
-        }
-    }
-
-    private String clean(String s) {
-        if (s == null) return null;
-        return s.replaceAll("[\\u00A0\\u3000]", "").trim();
-    }
-}
-
-
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
deleted file mode 100644
index 8a1099c..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
-import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.dto.ProductOrderDto;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.mapper.*;
-import com.ruoyi.production.pojo.*;
-import com.ruoyi.production.service.ProductOrderService;
-import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.pojo.QualityInspect;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.List;
-import java.util.stream.Collectors;
-
-@Service
-public class ProductOrderServiceImpl extends ServiceImpl<ProductOrderMapper, ProductOrder> implements ProductOrderService {
-
-    @Autowired
-    private ProductOrderMapper productOrderMapper;
-
-    @Autowired
-    private ProcessRouteMapper processRouteMapper;
-
-    @Autowired
-    private ProductProcessRouteMapper productProcessRouteMapper;
-
-    @Autowired
-    private ProcessRouteItemMapper processRouteItemMapper;
-
-    @Autowired
-    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
-
-    @Autowired
-    private ProductWorkOrderMapper productWorkOrderMapper;
-
-    @Autowired
-    private ProductionProductMainMapper productionProductMainMapper;
-
-    @Autowired
-    private ProductionProductOutputMapper productionProductOutputMapper;
-
-    @Autowired
-    private ProductionProductInputMapper productionProductInputMapper;
-
-    @Autowired
-    private QualityInspectMapper qualityInspectMapper;
-
-    @Autowired
-    private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-
-    @Autowired
-    private StockUtils stockUtils;
-
-    @Override
-    public IPage<ProductOrderDto> pageProductOrder(Page page, ProductOrderDto productOrder) {
-        return productOrderMapper.pageProductOrder(page, productOrder);
-    }
-
-    @Override
-    public int bindingRoute(ProductOrder productOrder) {
-        //鏂板鐢熶骇璁㈠崟涓嬬殑宸ヨ壓璺嚎涓昏〃
-        ProcessRoute processRoute = processRouteMapper.selectById(productOrder.getRouteId());
-        ProductProcessRoute productProcessRoute = new ProductProcessRoute();
-        productProcessRoute.setProductModelId(processRoute.getProductModelId());
-        productProcessRoute.setProcessRouteCode(processRoute.getProcessRouteCode());
-        productProcessRoute.setProductOrderId(productOrder.getId());
-        productProcessRoute.setBomId(processRoute.getBomId());
-        productProcessRouteMapper.insert(productProcessRoute);
-        //鏂板鐢熶骇璁㈠崟涓嬬殑宸ヨ壓璺嚎瀛愯〃
-        List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(new QueryWrapper<ProcessRouteItem>().lambda().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
-        // 鐢熸垚褰撳墠鏃ユ湡鐨勫墠缂�锛氬勾鏈堟棩
-        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
-        for (ProcessRouteItem processRouteItem : processRouteItems) {
-            ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
-            productProcessRouteItem.setProductModelId(processRouteItem.getProductModelId());
-            productProcessRouteItem.setProcessId(processRouteItem.getProcessId());
-            productProcessRouteItem.setProductOrderId(productOrder.getId());
-            productProcessRouteItem.setProductRouteId(productProcessRoute.getId());
-            productProcessRouteItem.setDragSort(processRouteItem.getDragSort());
-            int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
-            if (insert > 0) {
-                // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶у伐鍗曞彿
-                ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectMax(datePrefix);
-                int sequenceNumber = 1; // 榛樿搴忓彿
-                if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
-                    String lastNo = lastWorkOrder.getWorkOrderNo().toString();
-                    if (lastNo.startsWith(datePrefix)) {
-                        String seqStr = lastNo.substring(datePrefix.length());
-                        try {
-                            sequenceNumber = Integer.parseInt(seqStr) + 1;
-                        } catch (NumberFormatException e) {
-                            sequenceNumber = 1;
-                        }
-                    }
-                }
-                // 鐢熸垚瀹屾暣鐨勫伐鍗曞彿
-                String workOrderNoStr = "GD" + String.format("%s%03d", datePrefix, sequenceNumber);
-                ProductWorkOrder productWorkOrder = new ProductWorkOrder();
-                productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
-                productWorkOrder.setProductOrderId(productOrder.getId());
-                ProductOrder order = productOrderMapper.selectById(productOrder.getId());
-                productWorkOrder.setPlanQuantity(order.getQuantity());
-                productWorkOrder.setWorkOrderNo(workOrderNoStr);
-                productWorkOrder.setStatus(1);
-                productWorkOrderMapper.insert(productWorkOrder);
-            }
-        }
-        return productOrderMapper.updateById(productOrder);
-    }
-
-    @Override
-    public List<ProcessRoute> listProcessRoute(Long productModelId) {
-        return productOrderMapper.listProcessRoute(productModelId);
-    }
-
-    @Override
-    public List<ProductStructureDto> listProcessBom(Long orderId) {
-        return productOrderMapper.listProcessBom(orderId);
-    }
-
-    @Override
-    public Boolean addProductOrder(ProductOrder productOrder) {
-        String string = generateNextOrderNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
-        productOrder.setNpsNo(string);
-        productOrder.setCompleteQuantity(BigDecimal.ZERO);
-        this.save(productOrder);
-        if (ObjectUtils.isNotEmpty(productOrder.getRouteId())) {
-            this.bindingRoute(productOrder);
-        }
-        return true;
-    }
-
-    @Override
-    public Boolean delete(Long[] ids) {
-        //濡傛灉宸茬粡寮�濮嬬敓浜�,涓嶈兘鍒犻櫎
-        //鏌ヨ鐢熶骇璁㈠崟涓嬬殑宸ュ崟
-        List<ProductWorkOrder> productWorkOrders = productWorkOrderMapper.selectList(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids));
-        if (productWorkOrders.size()>0){
-            //鍒ゆ柇鏄惁鏈夋姤宸ユ暟鎹�
-            List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(Wrappers.<ProductionProductMain>lambdaQuery()
-                    .in(ProductionProductMain::getWorkOrderId, productWorkOrders.stream().map(ProductWorkOrder::getId).collect(Collectors.toList())));
-            if (productionProductMains.size()>0){
-                throw new RuntimeException("鐢熶骇璁㈠崟宸茬粡寮�濮嬬敓浜�,涓嶈兘鍒犻櫎");
-            }
-            //鍒犻櫎宸ュ崟
-            productWorkOrderMapper.delete(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids));
-        }
-        //鍒犻櫎宸ヨ壓璺嚎
-        productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>()
-                .in(ProductProcessRouteItem::getProductOrderId, ids));
-        productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>()
-                .in(ProductProcessRoute::getProductOrderId, ids));
-        //鍒犻櫎鐢熶骇璁㈠崟
-        productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>()
-                .in(ProductOrder::getId, ids));
-        return true;
-    }
-
-    //鑾峰彇褰撳墠鐢熶骇璁㈠崟鍙�
-    public String getMaxOrderNoByDate(String datePrefix) {
-        QueryWrapper<ProductOrder> queryWrapper = new QueryWrapper<>();
-        // 鍖归厤浠� SC + 鏃ユ湡寮�澶寸殑璁㈠崟鍙�
-        queryWrapper.likeRight("nps_no", "SC" + datePrefix);
-        // 鎸夎鍗曞彿鍊掑簭鎺掑垪
-        queryWrapper.orderByDesc("nps_no");
-        queryWrapper.last("LIMIT 1");
-
-        ProductOrder latestOrder = this.getOne(queryWrapper);
-        return latestOrder != null ? latestOrder.getNpsNo() : null;
-    }
-
-    public String generateNextOrderNo(String datePrefix) {
-        String maxOrderNo = getMaxOrderNoByDate(datePrefix);
-        int sequence = 1; // 榛樿璧峰搴忓彿
-        if (maxOrderNo != null && !maxOrderNo.isEmpty()) {
-            // 鎻愬彇娴佹按鍙烽儴鍒嗭紙鍋囪鏍煎紡涓� SC + 鏃ユ湡 + 娴佹按鍙凤級
-            String sequenceStr = maxOrderNo.substring(("SC" + datePrefix).length());
-            try {
-                sequence = Integer.parseInt(sequenceStr) + 1;
-            } catch (NumberFormatException e) {
-                // 寮傚父鎯呭喌涓嬮噸缃负1
-                sequence = 1;
-            }
-        }
-        // 鐢熸垚鏂拌鍗曞彿
-        return "SC" + datePrefix + String.format("%04d", sequence);
-    }
-
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteItemServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteItemServiceImpl.java
deleted file mode 100644
index c5fbac0..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteItemServiceImpl.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProductProcessRouteItemDto;
-import com.ruoyi.production.dto.ProductionProductMainDto;
-import com.ruoyi.production.mapper.*;
-import com.ruoyi.production.pojo.*;
-import com.ruoyi.production.service.ProductProcessRouteItemService;
-import com.ruoyi.production.service.ProductionProductMainService;
-import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.pojo.QualityInspect;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import lombok.AllArgsConstructor;
-import org.apache.poi.ss.formula.functions.T;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-@Service
-@Transactional(rollbackFor = Exception.class)
-@AllArgsConstructor
-public class ProductProcessRouteItemServiceImpl extends ServiceImpl<ProductProcessRouteItemMapper, ProductProcessRouteItem> implements ProductProcessRouteItemService {
-
-
-    private ProductionProductMainService productionProductMainService;
-    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
-
-    private ProductionProductMainMapper productionProductMainMapper;
-
-    private ProductionProductInputMapper productionProductInputMapper;
-
-    private ProductionProductOutputMapper productionProductOutputMapper;
-
-    private QualityInspectMapper qualityInspectMapper;
-
-    private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-
-    private ProductWorkOrderMapper productWorkOrderMapper;
-
-    private ProductOrderMapper productOrderMapper;
-
-    private ProductProcessRouteMapper productProcessRouteMapper;
-
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-
-
-    @Override
-    public List<ProductProcessRouteItemDto> listItem(Long orderId) {
-        return productProcessRouteItemMapper.listItem(orderId);
-    }
-
-    @Override
-    public R deleteRouteItem(Long id) {
-        Long routeItemId = id;
-        try {
-            // 鏌ヨ宸ュ崟
-            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectOne(
-                    new LambdaQueryWrapper<ProductWorkOrder>()
-                            .eq(ProductWorkOrder::getProductProcessRouteItemId, routeItemId)
-                            .last("LIMIT 1")
-            );
-            if (productWorkOrder == null) {
-                throw new RuntimeException("鍒犻櫎澶辫触锛氭湭鎵惧埌鍏宠仈鐨勭敓浜у伐鍗�");
-            }
-            if (BigDecimal.ZERO.compareTo(productWorkOrder.getCompleteQuantity()) < 0) {
-                throw new RuntimeException("鍒犻櫎澶辫触锛氳宸ュ崟宸插紑濮嬬敓浜э紝璇峰厛鍒犻櫎鐢熶骇鎶ュ伐");
-            }
-            Long workOrderId = productWorkOrder.getId();
-            Long productOrderId = productWorkOrder.getProductOrderId();
-            // 鏌ヨ鐢熶骇涓昏〃
-            List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(
-                    new LambdaQueryWrapper<ProductionProductMain>()
-                            .eq(ProductionProductMain::getWorkOrderId, workOrderId)
-            );
-            if (!productionProductMains.isEmpty()) {
-                // 鎵归噺鍒犻櫎瀛愯〃
-                for (ProductionProductMain main : productionProductMains) {
-                    productionProductMainService.removeProductMain(main.getId());
-//                    Long mainId = main.getId();
-//                    // 鍒犻櫎鎶曞叆
-//                    productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
-//                            .eq(ProductionProductInput::getProductMainId, mainId));
-//                    // 鍒犻櫎浜у嚭
-//                    productionProductOutputMapper.delete(new LambdaQueryWrapper<ProductionProductOutput>()
-//                            .eq(ProductionProductOutput::getProductMainId, mainId));
-//                    // 鍒犻櫎璐ㄦ
-//                    qualityInspectMapper.delete(new LambdaQueryWrapper<QualityInspect>()
-//                            .eq(QualityInspect::getProductMainId, mainId));
-                    salesLedgerProductionAccountingMapper.delete(new LambdaQueryWrapper<SalesLedgerProductionAccounting>()
-                            .eq(SalesLedgerProductionAccounting::getProductMainId, main.getId()));
-                }
-            }
-            // 鏌ヨ璁㈠崟 + 鍒犻櫎鏍哥畻
-
-            // 鍒犻櫎鍏宠仈宸ュ崟
-            productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>()
-                    .eq(ProductWorkOrder::getProductProcessRouteItemId, routeItemId));
-
-            // 鍒犻櫎涓昏〃鏁版嵁
-            ProductProcessRouteItem deleteProductProcessRouteItem = productProcessRouteItemMapper.selectById(routeItemId);
-            Long productRouteId = deleteProductProcessRouteItem.getProductRouteId();
-            // 鍒犻櫎鎸囧畾鏁版嵁
-            productProcessRouteItemMapper.deleteById(id);
-            // 鏌ヨ璇ュ伐鑹鸿矾绾跨殑鎵�鏈夊伐搴忓苟鎸夌収椤哄簭鎺掑簭
-            List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery()
-                    .eq(ProductProcessRouteItem::getProductRouteId, productRouteId)
-                    .orderByAsc(ProductProcessRouteItem::getDragSort));
-            // 閲嶆柊璁剧疆鎺掑簭鍊硷紝浣垮簭鍙疯繛缁�
-            for (int i = 0; i < productProcessRouteItems.size(); i++) {
-                ProductProcessRouteItem item = productProcessRouteItems.get(i);
-                if (!item.getDragSort().equals(i + 1)) {
-                    item.setDragSort(i + 1);
-                    productProcessRouteItemMapper.updateById(item);
-                }
-            }
-            return R.ok();
-        } catch (Exception e) {
-            throw new RuntimeException("鍒犻櫎鐢熶骇宸ヨ壓璺嚎澶辫触锛�" + e.getMessage());
-        }
-    }
-
-    @Override
-    public R addRouteItem(ProductProcessRouteItem productProcessRouteItem) {
-        ProductOrder productOrder = productOrderMapper.selectById(productProcessRouteItem.getProductOrderId());
-        int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
-        // 鐢熸垚褰撳墠鏃ユ湡鐨勫墠缂�锛氬勾鏈堟棩
-        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
-        if (insert > 0) {
-            // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶у伐鍗曞彿
-            ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectMax(datePrefix);
-            int sequenceNumber = 1; // 榛樿搴忓彿
-            if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
-                String lastNo = lastWorkOrder.getWorkOrderNo().toString();
-                if (lastNo.startsWith(datePrefix)) {
-                    String seqStr = lastNo.substring(datePrefix.length());
-                    try {
-                        sequenceNumber = Integer.parseInt(seqStr) + 1;
-                    } catch (NumberFormatException e) {
-                        sequenceNumber = 1;
-                    }
-                }
-            }
-            // 鐢熸垚瀹屾暣鐨勫伐鍗曞彿
-            String workOrderNoStr = "GD" +String.format("%s%03d", datePrefix, sequenceNumber);
-            ProductWorkOrder productWorkOrder = new ProductWorkOrder();
-            productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
-            productWorkOrder.setProductOrderId(productProcessRouteItem.getProductOrderId());
-            productWorkOrder.setPlanQuantity(productOrder.getQuantity());
-            productWorkOrder.setWorkOrderNo(workOrderNoStr);
-            productWorkOrder.setStatus(1);
-            productWorkOrderMapper.insert(productWorkOrder);
-        }
-        return R.ok();
-    }
-
-    @Override
-    public int sortRouteItem(ProductProcessRouteItem productProcessRouteItem) {
-        //鏌ヨ琚敼鍔ㄧ殑杩欐潯鏁版嵁
-        ProductProcessRouteItem oldProductProcessRouteItem = productProcessRouteItemMapper.selectById(productProcessRouteItem.getId());
-        //鏌ヨ璇ュ伐鑹鸿矾绾跨殑鎵�鏈夊伐搴忓苟鎸夌収椤哄簭鎺掑簭
-        List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery()
-                .eq(ProductProcessRouteItem::getProductRouteId, oldProductProcessRouteItem.getProductRouteId())
-                .orderByAsc(ProductProcessRouteItem::getDragSort));
-        // 鑾峰彇鐩爣浣嶇疆锛堢Щ鍔ㄥ埌绗嚑涓箣鍚庯級
-        Integer targetPosition = productProcessRouteItem.getDragSort();
-        if (targetPosition != null && targetPosition >= 0) {
-            // 绉诲姩鍏冪礌鍒版柊鐨勪綅缃�
-            productProcessRouteItems.remove(oldProductProcessRouteItem);
-            productProcessRouteItems.add(targetPosition-1, oldProductProcessRouteItem);
-            // 鏇存柊鎵�鏈夊彈褰卞搷鐨勬帓搴忓瓧娈�
-            for (int i = 0; i < productProcessRouteItems.size(); i++) {
-                ProductProcessRouteItem item = productProcessRouteItems.get(i);
-                if (!item.getId().equals(oldProductProcessRouteItem.getId())) {
-                    // 妫�鏌ユ槸鍚﹂渶瑕佹洿鏂版帓搴忓��
-                    if (item.getDragSort() != i+1) {
-                        item.setDragSort(i+1);
-                        productProcessRouteItemMapper.updateById(item);
-                    }
-                } else {
-                    // 鏇存柊鍘熻褰曠殑鏂版帓搴忎綅缃�
-                    oldProductProcessRouteItem.setDragSort(targetPosition);
-                    productProcessRouteItemMapper.updateById(oldProductProcessRouteItem);
-                }
-            }
-            return 1;
-        }
-        return 0;
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteServiceImpl.java
deleted file mode 100644
index f5b2e92..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductProcessRouteServiceImpl.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.pojo.ProductProcessRoute;
-import com.ruoyi.production.mapper.ProductProcessRouteMapper;
-import com.ruoyi.production.service.ProductProcessRouteService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- *  鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-15 02:51:09
- */
-@Service
-public class ProductProcessRouteServiceImpl extends ServiceImpl<ProductProcessRouteMapper, ProductProcessRoute> implements ProductProcessRouteService {
-
-    @Autowired
-    private ProductProcessRouteMapper productProcessRouteMapper;
-
-    @Override
-    public ProcessRouteDto listMain(Long orderId) {
-        return productProcessRouteMapper.listMain(orderId);
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductProcessServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductProcessServiceImpl.java
deleted file mode 100644
index 3be9086..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductProcessServiceImpl.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.pojo.Customer;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.dto.ProductProcessDto;
-import com.ruoyi.production.mapper.ProcessRouteItemMapper;
-import com.ruoyi.production.mapper.ProductProcessMapper;
-import com.ruoyi.production.mapper.ProductProcessRouteItemMapper;
-import com.ruoyi.production.pojo.ProcessRouteItem;
-import com.ruoyi.production.pojo.ProductProcess;
-import com.ruoyi.production.pojo.ProductProcessRouteItem;
-import com.ruoyi.production.service.ProductProcessService;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.util.List;
-
-@Service
-public class ProductProcessServiceImpl extends ServiceImpl<ProductProcessMapper, ProductProcess> implements ProductProcessService {
-    @Autowired
-    private ProductProcessMapper productProcessMapper;
-    @Autowired
-    private ProcessRouteItemMapper processRouteItemMapper;
-    @Autowired
-    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
-
-    @Override
-    public IPage<ProductProcessDto> listPage(Page page, ProductProcessDto productProcessDto) {
-        return productProcessMapper.listPage(page, productProcessDto);
-    }
-
-    @Override
-    public AjaxResult add(ProductProcessDto productProcessDto) {
-        ProductProcess productProcess = new ProductProcess();
-        BeanUtils.copyProperties(productProcessDto,productProcess);
-        boolean save = productProcessMapper.insert(productProcess) > 0;
-        if (save && ObjectUtils.isNull(productProcessDto.getNo())) {
-            // 鏍规嵁id鐢熸垚no瀛楁锛欸X + 8浣嶆暟瀛楋紙涓嶈冻8浣嶅墠闈㈣ˉ0锛�
-            String no = "GX" + String.format("%08d", productProcess.getId());
-            productProcess.setNo(no);
-
-            productProcessMapper.updateById(productProcess);
-            return AjaxResult.success();
-        }
-        return AjaxResult.success();
-    }
-
-    @Override
-    public AjaxResult importData(MultipartFile file) {
-        try {
-            ExcelUtil<ProductProcess> util = new ExcelUtil<ProductProcess>(ProductProcess.class);
-            List<ProductProcess> productProcessList = util.importExcel(file.getInputStream());
-            if(CollectionUtils.isEmpty(productProcessList)){
-                return AjaxResult.warn("妯℃澘閿欒鎴栧鍏ユ暟鎹负绌�");
-            }
-            productProcessList.forEach(productProcess -> {
-                if (ObjectUtils.isEmpty(productProcess)) {
-                    throw new RuntimeException("浣跨敤妯℃澘杩涜瀵煎叆");
-                }
-                if (ObjectUtils.isEmpty(productProcess.getName())) {
-                    throw new RuntimeException("宸ュ簭鍚嶇О涓嶈兘涓虹┖");
-                }
-            });
-            this.saveOrUpdateBatch(productProcessList);
-            return AjaxResult.success(true);
-        }catch (Exception e){
-            e.printStackTrace();
-            return AjaxResult.error(e.getMessage());
-        }
-    }
-
-    @Override
-    public String batchDelete(List<Integer> ids) {
-        //鏌ヨ鏄惁鐢熶骇涓凡缁忓紩鐢ㄤ簡杩欎簺宸ュ簭
-        List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(Wrappers.<ProcessRouteItem>lambdaQuery().in(ProcessRouteItem::getProcessId, ids));
-        List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().in(ProductProcessRouteItem::getProcessId, ids));
-        if (!CollectionUtils.isEmpty(processRouteItems) || !CollectionUtils.isEmpty(productProcessRouteItems)){
-            throw new RuntimeException("璇ュ伐搴忓凡缁忚浣跨敤锛屾棤娉曞垹闄�");
-        }
-        productProcessMapper.deleteBatchIds(ids);
-        return null;
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
deleted file mode 100644
index 381b642..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductStructureServiceImpl.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.mapper.ProductStructureMapper;
-import com.ruoyi.production.pojo.ProductStructure;
-import com.ruoyi.production.service.ProductStructureService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-@Slf4j
-@Service
-public class ProductStructureServiceImpl extends ServiceImpl<ProductStructureMapper, ProductStructure> implements ProductStructureService {
-
-    @Autowired
-    private ProductStructureMapper productStructureMapper;
-
-
-    @Override
-    @Transactional
-    public Boolean addProductStructureDto(ProductStructureDto dto) {
-
-        Integer bomId = dto.getBomId();
-
-        //  灏嗘爲鎵佸钩鍖�
-        List<ProductStructureDto> flatDtoList = new ArrayList<>();
-        flattenTree(dto.getChildren(), flatDtoList);
-
-        //  鏌ヨ鏁版嵁搴撲腑宸叉湁鐨� BOM 鏁版嵁
-        List<ProductStructure> dbList = this.list(new LambdaQueryWrapper<ProductStructure>().eq(ProductStructure::getBomId, bomId));
-
-        //  鏌ユ壘宸插瓨鍦ㄧ殑鑺傜偣 - ID
-        Set<Long> frontendIds = flatDtoList.stream()
-                .map(ProductStructureDto::getId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-
-        //  闇�瑕佸垹闄ょ殑鑺傜偣 - ID
-        Set<Long> deleteIds = dbList.stream()
-                .map(ProductStructure::getId)
-                .filter(id -> !frontendIds.contains(id))
-                .collect(Collectors.toSet());
-
-        if (!deleteIds.isEmpty()) {
-            this.removeByIds(deleteIds);
-        }
-
-        //  鏂板 / 鏇存柊
-        List<ProductStructure> insertList = new ArrayList<>();
-        List<ProductStructure> updateList = new ArrayList<>();
-
-        // 鐢ㄤ簬鍥炲啓 parentId
-        Map<String, ProductStructure> tempEntityMap = new HashMap<>();
-
-        for (ProductStructureDto psDto : flatDtoList) {
-            ProductStructure entity = new ProductStructure();
-            BeanUtils.copyProperties(psDto, entity);
-            entity.setBomId(bomId);
-
-            if (psDto.getId() == null) {
-                // 鏂板
-                entity.setId(null);
-                entity.setParentId(null);
-                insertList.add(entity);
-                tempEntityMap.put(psDto.getTempId(), entity);
-            } else {
-                // 鏇存柊
-                updateList.add(entity);
-            }
-        }
-
-        //  鎻掑叆鏂拌妭鐐�
-        if (!insertList.isEmpty()) {
-            this.saveBatch(insertList);
-        }
-
-        //  鍥炲啓鏂板鑺傜偣 parentId
-        List<ProductStructure> parentFixList = new ArrayList<>();
-        //  鐪熷疄鐨勭埗鑺傜偣 ID
-        Long realParentId;
-        for (ProductStructureDto psDto : flatDtoList) {
-            if (psDto.getId() == null && psDto.getParentTempId() != null) {
-                ProductStructure child = tempEntityMap.get(psDto.getTempId());
-                if (tempEntityMap.containsKey(psDto.getParentTempId())) {
-                    // 鐖惰妭鐐规槸鏂拌妭鐐�
-                    realParentId = tempEntityMap.get(psDto.getParentTempId()).getId();
-                } else {
-                    // 鐖惰妭鐐规槸鑰佽妭鐐�
-                    realParentId = Long.valueOf(psDto.getParentTempId());
-                }
-
-                child.setParentId(realParentId);
-                parentFixList.add(child);
-            }
-        }
-
-        if (!parentFixList.isEmpty()) {
-            this.updateBatchById(parentFixList);
-        }
-
-        if (!updateList.isEmpty()) {
-            this.updateBatchById(updateList);
-        }
-
-        return true;
-    }
-
-    /**
-     * 灏嗗墠绔紶鍏ョ殑鏍戣繘琛屾墎骞冲寲
-     *
-     * @param source 鏁版嵁鏍�
-     * @param result 鎵佸钩鍖栨暟鎹�
-     */
-    private void flattenTree(List<ProductStructureDto> source, List<ProductStructureDto> result) {
-        if (source == null) {
-            return;
-        }
-        for (ProductStructureDto node : source) {
-            result.add(node);
-            flattenTree(node.getChildren(), result);
-        }
-    }
-
-
-    @Override
-    public List<ProductStructureDto> listBybomId(Integer bomId) {
-        List<ProductStructureDto> list = productStructureMapper.listBybomId(bomId);
-
-        Map<Long, ProductStructureDto> map = new HashMap<>();
-        for (ProductStructureDto node : list) {
-            node.setChildren(new ArrayList<>());
-            map.put(node.getId(), node);
-        }
-
-        List<ProductStructureDto> tree = new ArrayList<>();
-        for (ProductStructureDto node : list) {
-            Long parentId = node.getParentId();
-            if (parentId == null || parentId == 0) {
-                tree.add(node);
-            } else {
-                ProductStructureDto parent = map.get(parentId);
-                if (parent != null) {
-                    parent.getChildren().add(node);
-                }
-            }
-        }
-        return tree;
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderFileServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderFileServiceImpl.java
deleted file mode 100644
index b0391ea..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderFileServiceImpl.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.ruoyi.production.pojo.ProductWorkOrderFile;
-import com.ruoyi.production.mapper.ProductWorkOrderFileMapper;
-import com.ruoyi.production.service.ProductWorkOrderFileService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 鐢熶骇宸ュ崟闄勪欢琛� 鏈嶅姟瀹炵幇绫�
- * </p>
- *
- * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
- * @since 2026-01-23 03:28:32
- */
-@Service
-public class ProductWorkOrderFileServiceImpl extends ServiceImpl<ProductWorkOrderFileMapper, ProductWorkOrderFile> implements ProductWorkOrderFileService {
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
deleted file mode 100644
index 4a68ce8..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.deepoove.poi.XWPFTemplate;
-import com.deepoove.poi.config.Configure;
-import com.deepoove.poi.data.PictureRenderData;
-import com.deepoove.poi.data.Pictures;
-import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
-import com.ruoyi.common.utils.MatrixToImageWriter;
-import com.ruoyi.production.dto.ProductWorkOrderDto;
-import com.ruoyi.production.mapper.ProductWorkOrderFileMapper;
-import com.ruoyi.production.mapper.ProductWorkOrderMapper;
-import com.ruoyi.production.pojo.ProductWorkOrder;
-import com.ruoyi.production.pojo.ProductWorkOrderFile;
-import com.ruoyi.production.service.ProductWorkOrderService;
-import com.ruoyi.quality.pojo.QualityInspectParam;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.servlet.http.HttpServletResponse;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Service
-@Transactional(rollbackFor = Exception.class)
-public class ProductWorkOrderServiceImpl extends ServiceImpl<ProductWorkOrderMapper, ProductWorkOrder> implements ProductWorkOrderService {
-
-    @Autowired
-    private ProductWorkOrderMapper productWorkOrdermapper;
-    @Autowired
-    private ProductWorkOrderFileMapper productWorkOrderFileMapper;
-
-    @Value("${file.temp-dir}")
-    private String tempDir;
-
-    @Override
-    public IPage<ProductWorkOrderDto> listPage(Page<ProductWorkOrderDto> page, ProductWorkOrderDto productWorkOrder) {
-        return productWorkOrdermapper.pageProductWorkOrder(page, productWorkOrder);
-    }
-
-    @Override
-    public int updateProductWorkOrder(ProductWorkOrderDto productWorkOrderDto) {
-        return productWorkOrdermapper.updateById(productWorkOrderDto);
-    }
-
-    @Override
-    public void down(HttpServletResponse response, ProductWorkOrder productWorkOrder) {
-        ProductWorkOrderDto productWorkOrderDto = productWorkOrdermapper.getProductWorkOrderFlowCard(productWorkOrder.getId());
-        String codePath;
-        try {
-            codePath = new MatrixToImageWriter().code(productWorkOrderDto.getId().toString(), tempDir);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        /*鑾峰彇闄勪欢鍥剧墖绫诲瀷*/
-        List<Map<String, Object>> images = new ArrayList<>();
-        List<ProductWorkOrderFile> productWorkOrderFiles = productWorkOrderFileMapper.selectList(Wrappers.<ProductWorkOrderFile>lambdaQuery().eq(ProductWorkOrderFile::getWorkOrderId, productWorkOrder.getId()));
-        if (CollectionUtils.isNotEmpty(productWorkOrderFiles)) {
-            productWorkOrderFiles.forEach(productWorkOrderFile -> {
-                Map<String, Object> image = new HashMap<>();
-                PictureRenderData pictureRenderData = Pictures.ofLocal( productWorkOrderFile.getUrl()).sizeInCm(17, 20).create();
-                image.put("url", pictureRenderData);
-                images.add(image);
-            });
-        }
-        InputStream inputStream = this.getClass().getResourceAsStream("/static/work-order-template.docx");
-        XWPFTemplate template = XWPFTemplate.compile(inputStream).render(
-                new HashMap<String, Object>() {{
-                    put("process", productWorkOrderDto.getProcessName());
-                    put("workOrderNo", productWorkOrderDto.getWorkOrderNo());
-                    put("productOrderNpsNo", productWorkOrderDto.getProductOrderNpsNo());
-                    put("productName", productWorkOrderDto.getProductName());
-                    put("planQuantity", productWorkOrderDto.getPlanQuantity());
-                    put("model", productWorkOrderDto.getModel());
-                    put("completeQuantity", productWorkOrderDto.getCompleteQuantity());
-                    put("scrapQty", productWorkOrderDto.getScrapQty());
-                    put("planStartTime", productWorkOrderDto.getPlanStartTime());
-                    put("planEndTime", productWorkOrderDto.getPlanEndTime());
-                    put("actualStartTime", productWorkOrderDto.getActualStartTime());
-                    put("actualEndTime", productWorkOrderDto.getActualEndTime());
-                    put("twoCode", Pictures.ofLocal(codePath).create());
-                    put("images", images.isEmpty()?null:images);
-                }});
-
-        try {
-            response.setContentType("application/msword");
-            String fileName = URLEncoder.encode(
-                    "娴佽浆鍗�", "UTF-8");
-            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
-            response.setHeader("Content-disposition",
-                    "attachment;filename=" + fileName + ".docx");
-            OutputStream os = response.getOutputStream();
-            template.write(os);
-            os.flush();
-            os.close();
-            inputStream.close();
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new RuntimeException("瀵煎嚭澶辫触");
-        }
-    }
-
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java
new file mode 100644
index 0000000..9c1843c
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionAccountServiceImpl.java
@@ -0,0 +1,73 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.bean.dto.ProductionAccountDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.vo.ProductionAccountVo;
+import com.ruoyi.production.mapper.ProductionAccountMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
+import com.ruoyi.production.pojo.ProductionAccount;
+import com.ruoyi.production.service.ProductionAccountService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+
+@Service
+@RequiredArgsConstructor
+public class ProductionAccountServiceImpl extends ServiceImpl<ProductionAccountMapper, ProductionAccount> implements ProductionAccountService {
+
+
+    private final ProductionProductMainMapper productionProductMainMapper;
+
+    @Override
+    public IPage<ProductionAccountVo> listPage(Page<ProductionAccountDto> page, ProductionAccountDto dto) {
+        ProductionAccountDto queryDto = normalizeDateQuery(dto);
+        return baseMapper.listPage(page, queryDto);
+    }
+
+    @Override
+    public IPage<ProductionProductMainDto> listProductionDetails(ProductionAccountDto dto, Page page) {
+        return productionProductMainMapper.listProductionDetails(normalizeDateQuery(dto), page);
+    }
+
+    private ProductionAccountDto normalizeDateQuery(ProductionAccountDto dto) {
+        if (dto == null) {
+            return new ProductionAccountDto();
+        }
+        LocalDate[] dateRange = dto.getDateRange();
+        if ((dto.getEntryDateStart() == null || dto.getEntryDateEnd() == null)
+                && dateRange != null
+                && dateRange.length > 0) {
+            if (dto.getEntryDateStart() == null) {
+                dto.setEntryDateStart(dateRange[0]);
+            }
+            if (dto.getEntryDateEnd() == null) {
+                dto.setEntryDateEnd(dateRange.length > 1 ? dateRange[1] : dateRange[0]);
+            }
+        }
+
+        String dateType = dto.getDateType();
+        if ("day".equalsIgnoreCase(dateType)) {
+            if (dto.getEntryDate() == null && dateRange != null && dateRange.length > 0) {
+                dto.setEntryDate(dateRange[0]);
+            }
+            if (dto.getEntryDate() == null) {
+                dto.setEntryDate(dto.getEntryDateStart());
+            }
+            dto.setEntryDateStart(null);
+            dto.setEntryDateEnd(null);
+        } else if ("month".equalsIgnoreCase(dateType)) {
+            if ((dto.getEntryDateStart() == null || dto.getEntryDateEnd() == null) && dto.getEntryDate() != null) {
+                LocalDate monthDate = dto.getEntryDate();
+                dto.setEntryDateStart(monthDate.withDayOfMonth(1));
+                dto.setEntryDateEnd(monthDate.withDayOfMonth(monthDate.lengthOfMonth()));
+            }
+            dto.setEntryDate(null);
+        }
+        return dto;
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
new file mode 100644
index 0000000..cbae0dc
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionBomStructureServiceImpl.java
@@ -0,0 +1,142 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.bean.dto.ProductionBomStructureDto;
+import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
+import com.ruoyi.production.mapper.ProductionBomStructureMapper;
+import com.ruoyi.production.pojo.ProductionBomStructure;
+import com.ruoyi.production.service.ProductionBomStructureService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM浜у搧缁撴瀯 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Service
+@RequiredArgsConstructor()
+public class ProductionBomStructureServiceImpl extends ServiceImpl<ProductionBomStructureMapper, ProductionBomStructure> implements ProductionBomStructureService {
+
+    private  final ProductionBomStructureMapper productionBomStructureMapper;
+
+    /**
+     * 鏍规嵁BOM鏌ヨ骞剁粍瑁呯粨鏋勬爲銆�
+     */
+    @Override
+    public List<ProductionBomStructureVo> listByBomId(Long bomId) {
+        List<ProductionBomStructureVo> list = productionBomStructureMapper.listByBomId(bomId);
+        Map<Long, ProductionBomStructureVo> map = new HashMap<>();
+        for (ProductionBomStructureVo node : list) {
+            node.setChildren(new ArrayList<>());
+            map.put(node.getId(), node);
+        }
+
+        List<ProductionBomStructureVo> tree = new ArrayList<>();
+        for (ProductionBomStructureVo node : list) {
+            Long parentId = node.getParentId();
+            if (parentId == null || parentId == 0L) {
+                tree.add(node);
+                continue;
+            }
+            ProductionBomStructureVo parent = map.get(parentId);
+            if (parent != null) {
+                parent.getChildren().add(node);
+            }
+        }
+        return tree;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addProductionBomStructure(ProductionBomStructureDto dto) {
+        Long orderBomId = dto.getProductionOrderBomId();
+        List<ProductionBomStructureDto> flatDtoList = new ArrayList<>();
+        flattenTree(dto.getChildren(), flatDtoList);
+
+        List<ProductionBomStructure> dbList = this.list(new LambdaQueryWrapper<ProductionBomStructure>()
+                .eq(ProductionBomStructure::getProductionOrderBomId, orderBomId));
+
+        Set<Long> frontendIds = new HashSet<>();
+        for (ProductionBomStructureDto item : flatDtoList) {
+            if (item.getId() != null) {
+                frontendIds.add(item.getId());
+            }
+        }
+
+        Set<Long> deleteIds = new HashSet<>();
+        for (ProductionBomStructure dbItem : dbList) {
+            if (!frontendIds.contains(dbItem.getId())) {
+                deleteIds.add(dbItem.getId());
+            }
+        }
+        if (!deleteIds.isEmpty()) {
+            this.removeByIds(deleteIds);
+        }
+
+        List<ProductionBomStructure> insertList = new ArrayList<>();
+        List<ProductionBomStructure> updateList = new ArrayList<>();
+        Map<String, ProductionBomStructure> tempEntityMap = new HashMap<>();
+
+        for (ProductionBomStructureDto item : flatDtoList) {
+            ProductionBomStructure entity = new ProductionBomStructure();
+            BeanUtils.copyProperties(item, entity);
+            entity.setProductionOrderBomId(orderBomId);
+            if (item.getId() == null) {
+                entity.setParentId(null);
+                insertList.add(entity);
+                tempEntityMap.put(item.getTempId(), entity);
+            } else {
+                updateList.add(entity);
+            }
+        }
+
+        if (!insertList.isEmpty()) {
+            this.saveBatch(insertList);
+        }
+
+        List<ProductionBomStructure> parentFixList = new ArrayList<>();
+        for (ProductionBomStructureDto item : flatDtoList) {
+            if (item.getId() == null && item.getParentTempId() != null) {
+                ProductionBomStructure child = tempEntityMap.get(item.getTempId());
+                if (child == null) {
+                    continue;
+                }
+                ProductionBomStructure parent = tempEntityMap.get(item.getParentTempId());
+                Long realParentId = parent != null ? parent.getId() : Long.valueOf(item.getParentTempId());
+                child.setParentId(realParentId);
+                parentFixList.add(child);
+            }
+        }
+
+        if (!parentFixList.isEmpty()) {
+            this.updateBatchById(parentFixList);
+        }
+        if (!updateList.isEmpty()) {
+            this.updateBatchById(updateList);
+        }
+        return true;
+    }
+
+    /**
+     * 灏嗘爲褰㈢粨鏋勬媿骞虫垚鍒楄〃锛屼究浜庣粺涓�淇濆瓨銆�
+     */
+    private void flattenTree(List<ProductionBomStructureDto> source, List<ProductionBomStructureDto> result) {
+        if (source == null) {
+            return;
+        }
+        for (ProductionBomStructureDto node : source) {
+            result.add(node);
+            flattenTree(node.getChildren(), result);
+        }
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationMainParamServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationMainParamServiceImpl.java
new file mode 100644
index 0000000..1f0abf7
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationMainParamServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.mapper.ProductionOperationMainParamMapper;
+import com.ruoyi.production.pojo.ProductionOperationMainParam;
+import com.ruoyi.production.service.ProductionOperationMainParamService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鐢熶骇宸ュ崟鎶ュ伐鍙傛暟琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Service
+public class ProductionOperationMainParamServiceImpl extends ServiceImpl<ProductionOperationMainParamMapper, ProductionOperationMainParam> implements ProductionOperationMainParamService {
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
new file mode 100644
index 0000000..383193b
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
@@ -0,0 +1,355 @@
+package com.ruoyi.production.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.deepoove.poi.XWPFTemplate;
+import com.deepoove.poi.data.PictureRenderData;
+import com.deepoove.poi.data.PictureType;
+import com.deepoove.poi.data.Pictures;
+import com.ruoyi.basic.dto.StorageAttachmentDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.common.config.FileProperties;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MatrixToImageWriter;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
+import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import com.ruoyi.production.service.ProductionOperationTaskService;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class ProductionOperationTaskServiceImpl extends ServiceImpl<ProductionOperationTaskMapper, ProductionOperationTask> implements ProductionOperationTaskService {
+
+    private final SysUserMapper sysUserMapper;
+    private final ProductionOrderMapper productionOrderMapper;
+
+    private final FileUtil fileUtil;
+
+    private final FileProperties fileProperties;
+
+    @Value("${file.temp-dir}")
+    private String tempDir;
+
+    @Override
+    public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) {
+        Page<ProductionOperationTaskVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
+        IPage<ProductionOperationTaskVo> result = baseMapper.pageProductionOperationTask(voPage, dto);
+        fillUserNames(result.getRecords());
+        return result;
+    }
+
+    @Override
+    public List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto dto) {
+        List<ProductionOperationTaskVo> result = BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class);
+        fillUserNames(result);
+        return result;
+    }
+
+    @Override
+    public ProductionOperationTaskVo getProductionOperationTaskInfo(Long id) {
+        ProductionOperationTask item = this.getById(id);
+        if (item == null) {
+            return null;
+        }
+        ProductionOperationTaskVo vo = BeanUtil.copyProperties(item, ProductionOperationTaskVo.class);
+        if (item.getProductionOrderId() != null) {
+            ProductionOrder productionOrder = productionOrderMapper.selectById(item.getProductionOrderId());
+            if (productionOrder != null) {
+                vo.setEndOrder(productionOrder.getEndOrder());
+            }
+        }
+        fillUserNames(Collections.singletonList(vo));
+        return vo;
+    }
+
+    @Override
+    public boolean saveProductionOperationTask(ProductionOperationTask productionOperationTask) {
+        return this.saveOrUpdate(productionOperationTask);
+    }
+
+    @Override
+    public boolean removeProductionOperationTask(List<Long> ids) {
+        return ids != null && !ids.isEmpty() && this.removeByIds(ids);
+    }
+
+    @Override
+    public int updateProductWorkOrder(ProductionOperationTaskDto dto) {
+        return baseMapper.updateById(dto);
+    }
+
+    @Override
+    public boolean assign(ProductionOperationTaskDto dto) {
+        if (dto == null || dto.getId() == null) {
+            throw new ServiceException("宸ュ崟ID涓嶈兘涓虹┖");
+        }
+
+        ProductionOperationTask update = new ProductionOperationTask();
+        update.setId(dto.getId());
+        update.setUserIds(dto.getUserIds());
+        int rows = baseMapper.updateById(update);
+        if (rows <= 0) {
+            throw new ServiceException("宸ュ崟涓嶅瓨鍦ㄦ垨宸插垹闄�");
+        }
+        return true;
+    }
+
+    private LambdaQueryWrapper<ProductionOperationTask> buildQueryWrapper(ProductionOperationTaskDto dto) {
+        ProductionOperationTask query = dto == null ? new ProductionOperationTask() : dto;
+        return Wrappers.<ProductionOperationTask>lambdaQuery()
+                .eq(query.getId() != null, ProductionOperationTask::getId, query.getId())
+                .eq(query.getProductionOrderId() != null, ProductionOperationTask::getProductionOrderId, query.getProductionOrderId())
+                .eq(query.getProductionOrderRoutingOperationId() != null,
+                        ProductionOperationTask::getProductionOrderRoutingOperationId, query.getProductionOrderRoutingOperationId())
+                .eq(query.getStatus() != null, ProductionOperationTask::getStatus, query.getStatus())
+                .like(query.getWorkOrderNo() != null && !query.getWorkOrderNo().trim().isEmpty(),
+                        ProductionOperationTask::getWorkOrderNo, query.getWorkOrderNo())
+                .orderByDesc(ProductionOperationTask::getId);
+    }
+
+    private void fillUserNames(List<ProductionOperationTaskVo> voList) {
+        if (voList == null || voList.isEmpty()) {
+            return;
+        }
+        Set<Long> userIdSet = new LinkedHashSet<>();
+        for (ProductionOperationTaskVo vo : voList) {
+            if (vo == null) {
+                continue;
+            }
+            userIdSet.addAll(parseUserIdList(vo.getUserIds(), false));
+        }
+        if (userIdSet.isEmpty()) {
+            return;
+        }
+        List<SysUser> userList = sysUserMapper.selectUsersByIds(new ArrayList<>(userIdSet));
+        if (userList == null || userList.isEmpty()) {
+            return;
+        }
+        Map<Long, String> userNameById = userList.stream()
+                .filter(item -> item.getUserId() != null)
+                .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName, (left, right) -> left));
+
+        for (ProductionOperationTaskVo vo : voList) {
+            if (vo == null) {
+                continue;
+            }
+            List<Long> userIds = parseUserIdList(vo.getUserIds(), false);
+            if (userIds.isEmpty()) {
+                vo.setUserNames(null);
+                continue;
+            }
+            String userNames = userIds.stream()
+                    .map(userNameById::get)
+                    .filter(StringUtils::isNotBlank)
+                    .collect(Collectors.joining(","));
+            vo.setUserNames(userNames);
+        }
+    }
+
+    private List<Long> parseUserIdList(String userIds, boolean strict) {
+        if (StringUtils.isBlank(userIds)) {
+            if (strict) {
+                throw new ServiceException("userIds鏍煎紡涓嶆纭紝蹇呴』涓篔SON鏁板瓧鏁扮粍");
+            }
+            return new ArrayList<>();
+        }
+
+        String text = userIds.trim();
+        try {
+            List<Long> parsed = JSON.parseArray(text, Long.class);
+            LinkedHashSet<Long> idSet = parsed == null ? new LinkedHashSet<>() : parsed.stream()
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toCollection(LinkedHashSet::new));
+            if (strict && idSet.isEmpty()) {
+                throw new ServiceException("userIds鏍煎紡涓嶆纭紝蹇呴』涓篔SON鏁板瓧鏁扮粍");
+            }
+            return new ArrayList<>(idSet);
+        } catch (Exception e) {
+            if (strict) {
+                throw new ServiceException("userIds鏍煎紡涓嶆纭紝蹇呴』涓篔SON鏁板瓧鏁扮粍");
+            }
+            return new ArrayList<>();
+        }
+    }
+
+    @Override
+    public void down(HttpServletResponse response, ProductionOperationTaskDto dto) {
+        if (dto == null || dto.getId() == null) {
+            throw new ServiceException("宸ュ崟ID涓嶈兘涓虹┖");
+        }
+
+        ProductionOperationTaskDto taskDto = baseMapper.getProductWorkOrderFlowCard(dto.getId());
+        if (taskDto == null) {
+            throw new ServiceException("宸ュ崟涓嶅瓨鍦紝ID=" + dto.getId());
+        }
+        String codePath;
+        try {
+            codePath = new MatrixToImageWriter().code(taskDto.getId().toString(), tempDir);
+        } catch (Exception e) {
+            throw new ServiceException("鐢熸垚浜岀淮鐮佸け璐�");
+        }
+
+        List<Map<String, Object>> images = buildTaskAttachmentImages(taskDto.getId());
+        Map<String, Object> renderData = new HashMap<>();
+        renderData.put("process", taskDto.getProcessName());
+        renderData.put("workOrderNo", taskDto.getWorkOrderNo());
+        renderData.put("productOrderNpsNo", taskDto.getProductOrderNpsNo());
+        renderData.put("productName", taskDto.getProductName());
+        renderData.put("planQuantity", taskDto.getPlanQuantity());
+        renderData.put("model", taskDto.getModel());
+        renderData.put("completeQuantity", taskDto.getCompleteQuantity());
+        renderData.put("scrapQty", taskDto.getScrapQty());
+        renderData.put("planStartTime", taskDto.getPlanStartTime());
+        renderData.put("planEndTime", taskDto.getPlanEndTime());
+        renderData.put("actualStartTime", taskDto.getActualStartTime());
+        renderData.put("actualEndTime", taskDto.getActualEndTime());
+        renderData.put("twoCode", Pictures.ofLocal(codePath).create());
+        renderData.put("images", images.isEmpty() ? null : images);
+
+        try (InputStream inputStream = this.getClass().getResourceAsStream("/static/work-order-template.docx")) {
+            if (inputStream == null) {
+                throw new ServiceException("娴佽浆鍗℃ā鏉夸笉瀛樺湪");
+            }
+            XWPFTemplate template = XWPFTemplate.compile(inputStream).render(renderData);
+            response.setContentType("application/msword");
+            String fileName = URLEncoder.encode("娴佽浆鍗�", "UTF-8");
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx");
+            try (OutputStream os = response.getOutputStream()) {
+                template.write(os);
+                os.flush();
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("瀵煎嚭澶辫触");
+        }
+    }
+
+    private List<Map<String, Object>> buildTaskAttachmentImages(Long taskId) {
+        List<Map<String, Object>> images = new ArrayList<>();
+        StorageAttachmentDTO storageAttachmentDTO = new StorageAttachmentDTO();
+        storageAttachmentDTO.setRecordType(RecordTypeEnum.PRODUCTION_OPERATION_TASK.getType());
+        storageAttachmentDTO.setRecordId(taskId);
+        List<StorageBlobVO> taskWorkOrderFiles =
+                fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(storageAttachmentDTO);
+        if (CollectionUtils.isEmpty(taskWorkOrderFiles)) {
+            return images;
+        }
+        for (StorageBlobVO blobVO : taskWorkOrderFiles) {
+            if (blobVO == null) {
+                continue;
+            }
+            PictureType pictureType = resolvePictureType(blobVO);
+            if (pictureType == null) {
+                continue;
+            }
+            File imageFile = resolveImageFile(blobVO);
+            if (imageFile == null || !imageFile.exists() || !imageFile.isFile()) {
+                continue;
+            }
+            try (InputStream imageInputStream = new FileInputStream(imageFile)) {
+                Map<String, Object> image = new HashMap<>();
+                PictureRenderData pictureRenderData = Pictures.ofStream(imageInputStream, pictureType)
+                        .sizeInCm(17, 20)
+                        .create();
+                image.put("url", pictureRenderData);
+                images.add(image);
+            } catch (Exception ignored) {
+                // 鍗曚釜闄勪欢瑙f瀽澶辫触鏃惰烦杩囷紝閬垮厤褰卞搷鏁翠釜娴佽浆鍗″鍑�
+            }
+        }
+        return images;
+    }
+
+    private File resolveImageFile(StorageBlobVO blobVO) {
+        if (blobVO == null || StringUtils.isBlank(blobVO.getUidFilename())) {
+            return null;
+        }
+        if (StringUtils.isBlank(blobVO.getPath())) {
+            return new File(fileProperties.getPath(), blobVO.getUidFilename());
+        }
+        return new File(new File(fileProperties.getPath(), blobVO.getPath()), blobVO.getUidFilename());
+    }
+
+    private PictureType resolvePictureType(StorageBlobVO blobVO) {
+        if (blobVO == null) {
+            return null;
+        }
+        PictureType type = parsePictureTypeByFileName(blobVO.getOriginalFilename());
+        if (type != null) {
+            return type;
+        }
+        type = parsePictureTypeByFileName(blobVO.getUidFilename());
+        if (type != null) {
+            return type;
+        }
+        return parsePictureTypeByContentType(blobVO.getContentType());
+    }
+
+    private PictureType parsePictureTypeByFileName(String fileName) {
+        if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
+            return null;
+        }
+        try {
+            return PictureType.suggestFileType(fileName);
+        } catch (Exception ex) {
+            return null;
+        }
+    }
+
+    private PictureType parsePictureTypeByContentType(String contentType) {
+        if (StringUtils.isBlank(contentType)) {
+            return null;
+        }
+        String normalized = contentType.trim().toLowerCase(Locale.ROOT);
+        switch (normalized) {
+            case "image/jpeg":
+            case "image/jpg":
+            case "image/pjpeg":
+                return PictureType.JPEG;
+            case "image/png":
+                return PictureType.PNG;
+            case "image/gif":
+                return PictureType.GIF;
+            case "image/bmp":
+            case "image/x-ms-bmp":
+                return PictureType.BMP;
+            case "image/tiff":
+            case "image/tif":
+                return PictureType.TIFF;
+            case "image/svg+xml":
+                return PictureType.SVG;
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public List<ProductionOperationTaskVo> getOperation(ProductionOperationTaskDto dto) {
+        return baseMapper.getOperation(dto);
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java
new file mode 100644
index 0000000..800e987
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderBomServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.mapper.ProductionOrderBomMapper;
+import com.ruoyi.production.pojo.ProductionOrderBom;
+import com.ruoyi.production.service.ProductionOrderBomService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟BOM 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Service
+public class ProductionOrderBomServiceImpl extends ServiceImpl<ProductionOrderBomMapper, ProductionOrderBom> implements ProductionOrderBomService {
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java
new file mode 100644
index 0000000..1cf7c1e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickRecordServiceImpl.java
@@ -0,0 +1,32 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.bean.dto.ProductionOrderPickRecordDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo;
+import com.ruoyi.production.mapper.ProductionOrderPickRecordMapper;
+import com.ruoyi.production.pojo.ProductionOrderPickRecord;
+import com.ruoyi.production.service.ProductionOrderPickRecordService;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * 绾胯竟浠撳嚭鍏ュ簱璁板綍 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-21 03:55:52
+ */
+@Service
+public class ProductionOrderPickRecordServiceImpl extends ServiceImpl<ProductionOrderPickRecordMapper, ProductionOrderPickRecord> implements ProductionOrderPickRecordService {
+
+    @Override
+    public List<ProductionOrderPickRecordVo> listFeedingRecord(ProductionOrderPickRecordDto dto) {
+        if (dto == null || dto.getProductionOrderId() == null || dto.getPickId() == null) {
+            return Collections.emptyList();
+        }
+        return baseMapper.listFeedingRecord(dto);
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
new file mode 100644
index 0000000..f45c117
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderPickServiceImpl.java
@@ -0,0 +1,919 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionOrderPickMapper;
+import com.ruoyi.production.mapper.ProductionOrderPickRecordMapper;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionOrderPick;
+import com.ruoyi.production.pojo.ProductionOrderPickRecord;
+import com.ruoyi.production.service.ProductionOrderPickService;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.pojo.StockInventory;
+import com.ruoyi.stock.service.StockInventoryService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 鐠併垹宕熸0鍡樻灐缁捐儻绔熸禒?閺堝秴濮熺�圭偟骞囩猾?
+ * </p>
+ *
+ * @author 閼侯垰顕辨潪顖欐閿涘牊鐫欓懟蹇ョ礆閺堝妾洪崗顒�寰�
+ * @since 2026-04-21 03:55:52
+ */
+@Service
+@RequiredArgsConstructor
+public class ProductionOrderPickServiceImpl extends ServiceImpl<ProductionOrderPickMapper, ProductionOrderPick> implements ProductionOrderPickService {
+
+    private static final byte PICK_TYPE_NORMAL = 1;
+    private static final byte PICK_TYPE_FEEDING = 2;
+
+    private final ProductionOrderMapper productionOrderMapper;
+    private final ProductionOperationTaskMapper productionOperationTaskMapper;
+    private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper;
+    private final StockInventoryMapper stockInventoryMapper;
+    private final StockInventoryService stockInventoryService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean savePick(ProductionOrderPickDto dto) {
+        List<ProductionOrderPickDto> pickItems = resolvePickItems(dto);
+        for (int i = 0; i < pickItems.size(); i++) {
+            int rowNo = i + 1;
+            ProductionOrderPickDto resolvedDto = mergeDto(dto, pickItems.get(i));
+            validatePickParam(resolvedDto, rowNo);
+
+            List<String> batchNoList = resolveBatchNoList(resolvedDto);
+            String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
+            String storedBatchNo = formatBatchNoStorage(batchNoList);
+            subtractInventory(resolvedDto.getProductModelId(), storedBatchNo, resolvedDto.getPickQuantity(), rowNo);
+
+            ProductionOrderPick orderPick = new ProductionOrderPick();
+            orderPick.setProductionOrderId(resolvedDto.getProductionOrderId());
+            orderPick.setProductModelId(resolvedDto.getProductModelId());
+            orderPick.setBatchNo(storedBatchNo);
+            orderPick.setQuantity(resolvedDto.getPickQuantity());
+            orderPick.setRemark(resolvedDto.getRemark());
+            orderPick.setOperationName(resolvedDto.getOperationName());
+            orderPick.setTechnologyOperationId(resolvedDto.getTechnologyOperationId());
+            orderPick.setDemandedQuantity(resolvedDto.getDemandedQuantity());
+            orderPick.setBom(resolvedDto.getBom());
+            orderPick.setReturned(false);
+            baseMapper.insert(orderPick);
+
+            insertPickRecord(orderPick.getId(),
+                    resolvedDto.getProductionOrderId(),
+                    resolvedDto.getProductionOperationTaskId(),
+                    resolvedDto.getProductModelId(),
+                    inventoryBatchNo,
+                    resolvedDto.getPickQuantity(),
+                    BigDecimal.ZERO,
+                    resolvedDto.getPickQuantity(),
+                    resolvedDto.getPickType(),
+                    resolvedDto.getRemark(),
+                    resolvedDto.getFeedingReason());
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean updatePick(ProductionOrderPickDto dto) {
+        if (dto == null) {
+            throw new ServiceException("鍙樻洿鍙傛暟涓嶈兘涓虹┖");
+        }
+        Long productionOrderId = resolveProductionOrderId(dto);
+        if (productionOrderId == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟ID涓嶈兘涓虹┖");
+        }
+        ProductionOrder productionOrder = productionOrderMapper.selectById(productionOrderId);
+        if (productionOrder == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+
+        List<ProductionOrderPick> existingPickList = baseMapper.selectList(
+                Wrappers.<ProductionOrderPick>lambdaQuery()
+                        .eq(ProductionOrderPick::getProductionOrderId, productionOrderId));
+        Map<Long, ProductionOrderPick> existingPickMap = existingPickList.stream()
+                .filter(item -> item.getId() != null)
+                .collect(Collectors.toMap(ProductionOrderPick::getId, Function.identity(), (a, b) -> a));
+
+        if (isFeedingRequest(dto)) {
+            processFeedingPickItems(dto, existingPickMap, productionOrderId);
+            return true;
+        }
+        if (isReturnRequest(dto)) {
+            processReturnPickItems(dto, existingPickMap, productionOrderId);
+            return true;
+        }
+
+        processDeletePickIds(dto, existingPickMap, productionOrderId);
+
+        List<ProductionOrderPickDto> pickItems = resolveUpdateItems(dto);
+        Set<Long> keepPickIdSet = new HashSet<>();
+        for (int i = 0; i < pickItems.size(); i++) {
+            int rowNo = i + 1;
+            ProductionOrderPickDto resolvedDto = mergeDto(dto, pickItems.get(i));
+            if (isEmptyUpdateItem(resolvedDto)) {
+                continue;
+            }
+            if (resolvedDto.getProductionOrderId() == null) {
+                resolvedDto.setProductionOrderId(productionOrderId);
+            }
+            validatePickParam(resolvedDto, rowNo);
+
+            if (resolvedDto.getId() == null) {
+                addNewPickInUpdate(resolvedDto, rowNo);
+                continue;
+            }
+            keepPickIdSet.add(resolvedDto.getId());
+            updateExistingPick(resolvedDto, rowNo, existingPickMap);
+        }
+        processMissingPickItems(dto, existingPickMap, productionOrderId, keepPickIdSet);
+        return true;
+    }
+
+    @Override
+    public List<ProductionOrderPickVo> listPickedDetail(Long productionOrderId) {
+        if (productionOrderId == null) {
+            return Collections.emptyList();
+        }
+        List<ProductionOrderPickVo> detailList = baseMapper.listPickedDetailByOrderId(productionOrderId);
+        fillBatchNoList(detailList);
+        fillSelectableBatchNoList(detailList);
+        return detailList;
+    }
+
+    private void processDeletePickIds(ProductionOrderPickDto rootDto,
+                                      Map<Long, ProductionOrderPick> existingPickMap,
+                                      Long productionOrderId) {
+        if (rootDto.getDeletePickIds() == null || rootDto.getDeletePickIds().isEmpty()) {
+            return;
+        }
+        Set<Long> deleteIdSet = new LinkedHashSet<>(rootDto.getDeletePickIds());
+        for (Long deleteId : deleteIdSet) {
+            if (deleteId == null) {
+                continue;
+            }
+            ProductionOrderPick existingPick = existingPickMap.get(deleteId);
+            if (existingPick == null || !Objects.equals(existingPick.getProductionOrderId(), productionOrderId)) {
+                throw new ServiceException("瑕佸垹闄ょ殑棰嗘枡璁板綍涓嶅瓨鍦ㄦ垨涓嶅睘浜庡綋鍓嶈鍗曪紝ID=" + deleteId);
+            }
+            String oldBatchNo = resolveInventoryBatchNoFromStored(existingPick.getBatchNo());
+            BigDecimal oldQuantity = defaultDecimal(existingPick.getQuantity());
+            addInventory(existingPick.getProductModelId(), oldBatchNo, oldQuantity);
+            int affected = baseMapper.deleteById(deleteId);
+            if (affected <= 0) {
+                throw new ServiceException("鍒犻櫎棰嗘枡澶辫触锛孖D=" + deleteId);
+            }
+            insertPickRecord(existingPick.getId(),
+                    existingPick.getProductionOrderId(),
+                    rootDto.getProductionOperationTaskId(),
+                    existingPick.getProductModelId(),
+                    oldBatchNo,
+                    oldQuantity,
+                    oldQuantity,
+                    BigDecimal.ZERO,
+                    rootDto.getPickType(),
+                    rootDto.getRemark(),
+                    rootDto.getFeedingReason());
+            existingPickMap.remove(deleteId);
+        }
+    }
+
+    private void processMissingPickItems(ProductionOrderPickDto rootDto,
+                                         Map<Long, ProductionOrderPick> existingPickMap,
+                                         Long productionOrderId,
+                                         Set<Long> keepPickIdSet) {
+        if (rootDto.getPickList() == null) {
+            return;
+        }
+        List<ProductionOrderPick> missingPickList = existingPickMap.values().stream()
+                .filter(Objects::nonNull)
+                .filter(item -> item.getId() != null)
+                .filter(item -> Objects.equals(item.getProductionOrderId(), productionOrderId))
+                .filter(item -> !keepPickIdSet.contains(item.getId()))
+                .toList();
+        for (ProductionOrderPick missingPick : missingPickList) {
+            String oldBatchNo = resolveInventoryBatchNoFromStored(missingPick.getBatchNo());
+            BigDecimal oldQuantity = defaultDecimal(missingPick.getQuantity());
+            addInventory(missingPick.getProductModelId(), oldBatchNo, oldQuantity);
+            int affected = baseMapper.deleteById(missingPick.getId());
+            if (affected <= 0) {
+                throw new ServiceException("鍒犻櫎棰嗘枡澶辫触锛孖D=" + missingPick.getId());
+            }
+            insertPickRecord(missingPick.getId(),
+                    missingPick.getProductionOrderId(),
+                    rootDto.getProductionOperationTaskId(),
+                    missingPick.getProductModelId(),
+                    oldBatchNo,
+                    oldQuantity,
+                    oldQuantity,
+                    BigDecimal.ZERO,
+                    rootDto.getPickType(),
+                    rootDto.getRemark(),
+                    rootDto.getFeedingReason());
+            existingPickMap.remove(missingPick.getId());
+        }
+    }
+
+    private void addNewPickInUpdate(ProductionOrderPickDto dto, int rowNo) {
+        List<String> batchNoList = resolveBatchNoList(dto);
+        String inventoryBatchNo = pickInventoryBatchNo(batchNoList);
+        String storedBatchNo = formatBatchNoStorage(batchNoList);
+        subtractInventory(dto.getProductModelId(), storedBatchNo, dto.getPickQuantity(), rowNo);
+
+        ProductionOrderPick orderPick = new ProductionOrderPick();
+        orderPick.setProductionOrderId(dto.getProductionOrderId());
+        orderPick.setProductModelId(dto.getProductModelId());
+        orderPick.setBatchNo(storedBatchNo);
+        orderPick.setQuantity(dto.getPickQuantity());
+        orderPick.setRemark(dto.getRemark());
+        orderPick.setOperationName(dto.getOperationName());
+        orderPick.setTechnologyOperationId(dto.getTechnologyOperationId());
+        orderPick.setDemandedQuantity(dto.getDemandedQuantity());
+        orderPick.setBom(dto.getBom());
+        orderPick.setReturned(false);
+        baseMapper.insert(orderPick);
+
+        insertPickRecord(orderPick.getId(),
+                dto.getProductionOrderId(),
+                dto.getProductionOperationTaskId(),
+                dto.getProductModelId(),
+                inventoryBatchNo,
+                dto.getPickQuantity(),
+                BigDecimal.ZERO,
+                dto.getPickQuantity(),
+                dto.getPickType(),
+                dto.getRemark(),
+                dto.getFeedingReason());
+    }
+
+    private void processFeedingPickItems(ProductionOrderPickDto rootDto,
+                                         Map<Long, ProductionOrderPick> existingPickMap,
+                                         Long productionOrderId) {
+        List<ProductionOrderPickDto> pickItems = resolveUpdateItems(rootDto);
+        for (int i = 0; i < pickItems.size(); i++) {
+            int rowNo = i + 1;
+            ProductionOrderPickDto resolvedDto = mergeDto(rootDto, pickItems.get(i));
+            if (isEmptyUpdateItem(resolvedDto)) {
+                continue;
+            }
+            if (!isFeedingPick(resolvedDto)) {
+                throw new ServiceException("琛ユ枡璇锋眰涓殑棰嗘枡绫诲瀷蹇呴』鍏ㄩ儴涓�2");
+            }
+            if (resolvedDto.getProductionOrderId() == null) {
+                resolvedDto.setProductionOrderId(productionOrderId);
+            }
+            validateFeedingParam(resolvedDto, rowNo);
+
+            ProductionOrderPick oldPick = existingPickMap.get(resolvedDto.getId());
+            if (oldPick == null || !Objects.equals(oldPick.getProductionOrderId(), productionOrderId)) {
+                throw new ServiceException("绗�" + rowNo + "鏉¢鏂欒褰曚笉瀛樺湪鎴栦笉灞炰簬褰撳墠璁㈠崟");
+            }
+            addFeedingPick(resolvedDto, oldPick, rowNo);
+        }
+    }
+
+    private void addFeedingPick(ProductionOrderPickDto dto, ProductionOrderPick oldPick, int rowNo) {
+        if (dto.getProductModelId() != null && !Objects.equals(dto.getProductModelId(), oldPick.getProductModelId())) {
+            throw new ServiceException("绗�" + rowNo + "鏉¤ˉ鏂欎骇鍝佽鏍间笌棰嗘枡璁板綍涓嶄竴鑷�");
+        }
+        Long productModelId = oldPick.getProductModelId();
+        List<String> batchNoList = resolveBatchNoList(dto);
+        String inventoryBatchNo = batchNoList.isEmpty()
+                ? resolveInventoryBatchNoFromStored(oldPick.getBatchNo())
+                : formatBatchNoStorage(batchNoList);
+        BigDecimal feedingQuantity = dto.getFeedingQuantity();
+
+        subtractInventory(productModelId, inventoryBatchNo, feedingQuantity, rowNo);
+
+        BigDecimal beforeFeedingQty = sumFeedingQuantity(dto.getProductionOrderId(), oldPick.getId());
+        BigDecimal afterFeedingQty = beforeFeedingQty.add(feedingQuantity);
+        insertPickRecord(oldPick.getId(),
+                dto.getProductionOrderId(),
+                dto.getProductionOperationTaskId(),
+                productModelId,
+                inventoryBatchNo,
+                feedingQuantity,
+                beforeFeedingQty,
+                afterFeedingQty,
+                PICK_TYPE_FEEDING,
+                dto.getRemark(),
+                dto.getFeedingReason());
+
+        ProductionOrderPick updatePick = new ProductionOrderPick();
+        updatePick.setId(oldPick.getId());
+        updatePick.setFeedingQty(afterFeedingQty);
+        updatePick.setActualQty(calculateActualQty(oldPick, afterFeedingQty));
+        int affected = baseMapper.updateById(updatePick);
+        if (affected <= 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¤ˉ鏂欐�婚噺鏇存柊澶辫触");
+        }
+        oldPick.setFeedingQty(afterFeedingQty);
+        oldPick.setActualQty(updatePick.getActualQty());
+    }
+
+    private void processReturnPickItems(ProductionOrderPickDto rootDto,
+                                        Map<Long, ProductionOrderPick> existingPickMap,
+                                        Long productionOrderId) {
+        List<ProductionOrderPickDto> pickItems = resolveUpdateItems(rootDto);
+        for (int i = 0; i < pickItems.size(); i++) {
+            int rowNo = i + 1;
+            ProductionOrderPickDto resolvedDto = mergeDto(rootDto, pickItems.get(i));
+            if (isEmptyUpdateItem(resolvedDto)) {
+                continue;
+            }
+            if (resolvedDto.getProductionOrderId() == null) {
+                resolvedDto.setProductionOrderId(productionOrderId);
+            }
+            validateReturnParam(resolvedDto, rowNo);
+
+            ProductionOrderPick oldPick = existingPickMap.get(resolvedDto.getId());
+            if (oldPick == null || !Objects.equals(oldPick.getProductionOrderId(), productionOrderId)) {
+                throw new ServiceException("绗�" + rowNo + "鏉¢鏂欒褰曚笉瀛樺湪鎴栦笉灞炰簬褰撳墠璁㈠崟");
+            }
+            updateReturnPick(resolvedDto, oldPick, rowNo);
+        }
+    }
+
+    private void updateReturnPick(ProductionOrderPickDto dto, ProductionOrderPick oldPick, int rowNo) {
+        ProductionOrderPick updatePick = new ProductionOrderPick();
+        updatePick.setId(oldPick.getId());
+        updatePick.setReturnQty(dto.getReturnQty());
+        updatePick.setActualQty(dto.getActualQty());
+        updatePick.setReturned(true);
+        int affected = baseMapper.updateById(updatePick);
+        if (affected <= 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢��鏂欎俊鎭洿鏂板け璐�");
+        }
+        oldPick.setReturnQty(updatePick.getReturnQty());
+        oldPick.setActualQty(updatePick.getActualQty());
+        oldPick.setReturned(true);
+    }
+
+    private void updateExistingPick(ProductionOrderPickDto dto,
+                                    int rowNo,
+                                    Map<Long, ProductionOrderPick> existingPickMap) {
+        ProductionOrderPick oldPick = existingPickMap.get(dto.getId());
+        if (oldPick == null || !Objects.equals(oldPick.getProductionOrderId(), dto.getProductionOrderId())) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欒褰曚笉瀛樺湪鎴栦笉灞炰簬褰撳墠璁㈠崟");
+        }
+
+        Long oldProductModelId = oldPick.getProductModelId();
+        String oldBatchNo = resolveInventoryBatchNoFromStored(oldPick.getBatchNo());
+        BigDecimal oldQuantity = defaultDecimal(oldPick.getQuantity());
+
+        Long newProductModelId = dto.getProductModelId();
+        List<String> newBatchNoList = resolveBatchNoList(dto);
+        String newBatchNo = pickInventoryBatchNo(newBatchNoList);
+        String newStoredBatchNo = formatBatchNoStorage(newBatchNoList);
+        BigDecimal newQuantity = dto.getPickQuantity();
+
+        boolean sameStockKey = Objects.equals(oldProductModelId, newProductModelId)
+                && Objects.equals(oldBatchNo, newBatchNo);
+        if (sameStockKey) {
+            BigDecimal delta = newQuantity.subtract(oldQuantity);
+            if (delta.compareTo(BigDecimal.ZERO) > 0) {
+                subtractInventory(newProductModelId, newStoredBatchNo, delta, rowNo);
+            } else if (delta.compareTo(BigDecimal.ZERO) < 0) {
+                addInventory(oldProductModelId, oldBatchNo, delta.abs());
+            }
+        } else {
+            addInventory(oldProductModelId, oldBatchNo, oldQuantity);
+            subtractInventory(newProductModelId, newStoredBatchNo, newQuantity, rowNo);
+        }
+
+        oldPick.setProductModelId(newProductModelId);
+        oldPick.setBatchNo(newStoredBatchNo);
+        oldPick.setQuantity(newQuantity);
+        oldPick.setRemark(dto.getRemark());
+        oldPick.setOperationName(dto.getOperationName());
+        oldPick.setTechnologyOperationId(dto.getTechnologyOperationId());
+        if (dto.getDemandedQuantity() != null) {
+            oldPick.setDemandedQuantity(dto.getDemandedQuantity());
+        }
+        if (dto.getBom() != null) {
+            oldPick.setBom(dto.getBom());
+        }
+        int affected = baseMapper.updateById(oldPick);
+        if (affected <= 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐洿鏂板け璐�");
+        }
+
+        BigDecimal recordQuantity = sameStockKey ? oldQuantity.subtract(newQuantity).abs() : newQuantity;
+        if (recordQuantity.compareTo(BigDecimal.ZERO) > 0 || oldQuantity.compareTo(newQuantity) != 0 || !sameStockKey) {
+            insertPickRecord(oldPick.getId(),
+                    dto.getProductionOrderId(),
+                    dto.getProductionOperationTaskId(),
+                    newProductModelId,
+                    newBatchNo,
+                    recordQuantity,
+                    oldQuantity,
+                    newQuantity,
+                    dto.getPickType(),
+                    dto.getRemark(),
+                    dto.getFeedingReason());
+        }
+    }
+
+    private void insertPickRecord(Long pickId,
+                                  Long productionOrderId,
+                                  Long productionOperationTaskId,
+                                  Long productModelId,
+                                  String batchNo,
+                                  BigDecimal pickQuantity,
+                                  BigDecimal beforeQuantity,
+                                  BigDecimal afterQuantity,
+                                  Byte pickType,
+                                  String remark,
+                                  String feedingReason) {
+        ProductionOrderPickRecord pickRecord = new ProductionOrderPickRecord();
+        pickRecord.setPickId(pickId);
+        pickRecord.setProductionOrderId(productionOrderId);
+        pickRecord.setProductionOperationTaskId(productionOperationTaskId);
+        pickRecord.setProductModelId(productModelId);
+        pickRecord.setBatchNo(batchNo);
+        pickRecord.setPickQuantity(defaultDecimal(pickQuantity));
+        pickRecord.setBeforeQuantity(defaultDecimal(beforeQuantity));
+        pickRecord.setAfterQuantity(defaultDecimal(afterQuantity));
+        pickRecord.setPickType(pickType == null ? PICK_TYPE_NORMAL : pickType);
+        pickRecord.setRemark(remark);
+        pickRecord.setFeedingReason(feedingReason);
+        productionOrderPickRecordMapper.insert(pickRecord);
+    }
+
+    private void subtractInventory(Long productModelId, String batchNo, BigDecimal quantity, int rowNo) {
+        BigDecimal deductQuantity = defaultDecimal(quantity);
+        if (deductQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+
+        List<String> batchNoList = parseBatchNoValue(batchNo);
+        if (batchNoList.isEmpty()) {
+            batchNoList = Collections.singletonList(null);
+        }
+
+        Map<String, BigDecimal> availableQuantityMap = new LinkedHashMap<>();
+        BigDecimal totalAvailableQuantity = BigDecimal.ZERO;
+        for (String currentBatchNo : batchNoList) {
+            StockInventory stockInventory = stockInventoryMapper.selectOne(buildStockWrapper(productModelId, currentBatchNo));
+            BigDecimal availableQuantity = BigDecimal.ZERO;
+            if (stockInventory != null) {
+                availableQuantity = defaultDecimal(stockInventory.getQualitity())
+                        .subtract(defaultDecimal(stockInventory.getLockedQuantity()));
+                if (availableQuantity.compareTo(BigDecimal.ZERO) < 0) {
+                    availableQuantity = BigDecimal.ZERO;
+                }
+            }
+            availableQuantityMap.put(currentBatchNo, availableQuantity);
+            totalAvailableQuantity = totalAvailableQuantity.add(availableQuantity);
+        }
+
+        if (deductQuantity.compareTo(totalAvailableQuantity) > 0) {
+            BigDecimal shortQuantity = deductQuantity.subtract(totalAvailableQuantity);
+            throw new ServiceException("棰嗘枡鍙敤搴撳瓨涓嶈冻锛屽彲鐢ㄥ簱瀛樹负" + formatQuantity(totalAvailableQuantity)
+                    + "锛岃繕宸�" + formatQuantity(shortQuantity));
+        }
+
+        BigDecimal remainingQuantity = deductQuantity;
+        for (Map.Entry<String, BigDecimal> entry : availableQuantityMap.entrySet()) {
+            if (remainingQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+                break;
+            }
+            BigDecimal availableQuantity = defaultDecimal(entry.getValue());
+            if (availableQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+                continue;
+            }
+            BigDecimal currentDeductQuantity = remainingQuantity.min(availableQuantity);
+            StockInventoryDto stockInventoryDto = new StockInventoryDto();
+            stockInventoryDto.setProductModelId(productModelId);
+            stockInventoryDto.setBatchNo(entry.getKey());
+            stockInventoryDto.setQualitity(currentDeductQuantity);
+            int affected = stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
+            if (affected <= 0) {
+                throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐墸鍑忓簱瀛樺け璐�");
+            }
+            remainingQuantity = remainingQuantity.subtract(currentDeductQuantity);
+        }
+
+        if (remainingQuantity.compareTo(BigDecimal.ZERO) > 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐墸鍑忓簱瀛樺け璐ワ紝鍓╀綑寰呮墸鍑忔暟閲忎负" + formatQuantity(remainingQuantity));
+        }
+    }
+
+    private void addInventory(Long productModelId, String batchNo, BigDecimal quantity) {
+        BigDecimal addQuantity = defaultDecimal(quantity);
+        if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+        StockInventoryDto stockInventoryDto = new StockInventoryDto();
+        stockInventoryDto.setProductModelId(productModelId);
+        stockInventoryDto.setBatchNo(batchNo);
+        stockInventoryDto.setQualitity(addQuantity);
+        stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PICK_RETURN_IN.getCode()));
+        stockInventoryDto.setRecordId(0L);
+        stockInventoryService.addStockInRecordOnly(stockInventoryDto);
+    }
+
+    private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) {
+        if (dto == null) {
+            throw new ServiceException("棰嗘枡鍙傛暟涓嶈兘涓虹┖");
+        }
+        if (dto.getPickList() != null && !dto.getPickList().isEmpty()) {
+            return dto.getPickList();
+        }
+        return Collections.singletonList(dto);
+    }
+
+    private List<ProductionOrderPickDto> resolveUpdateItems(ProductionOrderPickDto dto) {
+        if (dto.getPickList() != null) {
+            return dto.getPickList();
+        }
+        if (isEmptyUpdateItem(dto)) {
+            return Collections.emptyList();
+        }
+        return Collections.singletonList(dto);
+    }
+
+    private boolean isEmptyUpdateItem(ProductionOrderPickDto dto) {
+        return dto.getId() == null
+                && dto.getProductModelId() == null
+                && dto.getPickQuantity() == null
+                && StringUtils.isEmpty(dto.getBatchNo())
+                && (dto.getBatchNoList() == null || dto.getBatchNoList().isEmpty())
+                && dto.getPickType() == null
+                && dto.getFeedingQuantity() == null
+                && StringUtils.isEmpty(dto.getFeedingReason())
+                && dto.getReturnQty() == null
+                && dto.getActualQty() == null
+                && dto.getReturned() == null
+                && dto.getProductionOperationTaskId() == null
+                && dto.getTechnologyOperationId() == null
+                && StringUtils.isEmpty(dto.getOperationName())
+                && dto.getDemandedQuantity() == null
+                && dto.getBom() == null
+                && StringUtils.isEmpty(dto.getRemark());
+    }
+
+    private Long resolveProductionOrderId(ProductionOrderPickDto dto) {
+        if (dto.getProductionOrderId() != null) {
+            return dto.getProductionOrderId();
+        }
+        if (dto.getPickList() == null || dto.getPickList().isEmpty()) {
+            return null;
+        }
+        return dto.getPickList().stream()
+                .filter(Objects::nonNull)
+                .map(ProductionOrderPickDto::getProductionOrderId)
+                .filter(Objects::nonNull)
+                .findFirst()
+                .orElse(null);
+    }
+
+    private ProductionOrderPickDto mergeDto(ProductionOrderPickDto rootDto, ProductionOrderPickDto itemDto) {
+        ProductionOrderPickDto merged = new ProductionOrderPickDto();
+        if (itemDto != null) {
+            merged.setId(itemDto.getId());
+            merged.setProductionOrderId(itemDto.getProductionOrderId());
+            merged.setProductionOperationTaskId(itemDto.getProductionOperationTaskId());
+            merged.setProductModelId(itemDto.getProductModelId());
+            merged.setBatchNo(itemDto.getBatchNo());
+            merged.setBatchNoList(itemDto.getBatchNoList());
+            merged.setPickQuantity(itemDto.getPickQuantity());
+            merged.setPickType(itemDto.getPickType());
+            merged.setRemark(itemDto.getRemark());
+            merged.setFeedingReason(itemDto.getFeedingReason());
+            merged.setFeedingQuantity(itemDto.getFeedingQuantity());
+            merged.setTechnologyOperationId(itemDto.getTechnologyOperationId());
+            merged.setOperationName(itemDto.getOperationName());
+            merged.setDemandedQuantity(itemDto.getDemandedQuantity());
+            merged.setBom(itemDto.getBom());
+            merged.setReturnQty(itemDto.getReturnQty());
+            merged.setActualQty(itemDto.getActualQty());
+            merged.setReturned(itemDto.getReturned());
+        }
+        if (merged.getId() == null) {
+            merged.setId(rootDto.getId());
+        }
+        if (merged.getProductionOrderId() == null) {
+            merged.setProductionOrderId(rootDto.getProductionOrderId());
+        }
+        if (merged.getProductionOperationTaskId() == null) {
+            merged.setProductionOperationTaskId(rootDto.getProductionOperationTaskId());
+        }
+        if (merged.getProductModelId() == null) {
+            merged.setProductModelId(rootDto.getProductModelId());
+        }
+        if (merged.getBatchNo() == null) {
+            merged.setBatchNo(rootDto.getBatchNo());
+        }
+        if (merged.getBatchNoList() == null || merged.getBatchNoList().isEmpty()) {
+            merged.setBatchNoList(rootDto.getBatchNoList());
+        }
+        if (merged.getPickQuantity() == null) {
+            merged.setPickQuantity(rootDto.getPickQuantity());
+        }
+        if (merged.getPickType() == null) {
+            merged.setPickType(rootDto.getPickType());
+        }
+        if (merged.getRemark() == null) {
+            merged.setRemark(rootDto.getRemark());
+        }
+        if (merged.getFeedingReason() == null) {
+            merged.setFeedingReason(rootDto.getFeedingReason());
+        }
+        if (merged.getFeedingQuantity() == null) {
+            merged.setFeedingQuantity(rootDto.getFeedingQuantity());
+        }
+        if (merged.getTechnologyOperationId() == null) {
+            merged.setTechnologyOperationId(rootDto.getTechnologyOperationId());
+        }
+        if (merged.getOperationName() == null) {
+            merged.setOperationName(rootDto.getOperationName());
+        }
+        if (merged.getDemandedQuantity() == null) {
+            merged.setDemandedQuantity(rootDto.getDemandedQuantity());
+        }
+        if (merged.getBom() == null) {
+            merged.setBom(rootDto.getBom());
+        }
+        if (merged.getReturnQty() == null) {
+            merged.setReturnQty(rootDto.getReturnQty());
+        }
+        if (merged.getActualQty() == null) {
+            merged.setActualQty(rootDto.getActualQty());
+        }
+        if (merged.getReturned() == null) {
+            merged.setReturned(rootDto.getReturned());
+        }
+        return merged;
+    }
+
+    private void validatePickParam(ProductionOrderPickDto dto, int rowNo) {
+        if (dto.getProductionOrderId() == null) {
+            throw new ServiceException("绗�" + rowNo + "鏉$敓浜ц鍗旾D涓嶈兘涓虹┖");
+        }
+        if (dto.getProductModelId() == null) {
+            throw new ServiceException("绗�" + rowNo + "鏉′骇鍝佽鏍糏D涓嶈兘涓虹┖");
+        }
+        if (dto.getPickQuantity() == null || dto.getPickQuantity().compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欐暟閲忎笉鑳藉皬浜�0");
+        }
+        if (dto.getPickType() != null && dto.getPickType() != PICK_TYPE_NORMAL && dto.getPickType() != PICK_TYPE_FEEDING) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂欑被鍨嬪彧鑳芥槸1鎴�2");
+        }
+    }
+
+    private void validateFeedingParam(ProductionOrderPickDto dto, int rowNo) {
+        if (dto.getProductionOrderId() == null) {
+            throw new ServiceException("绗�" + rowNo + "鏉$敓浜ц鍗旾D涓嶈兘涓虹┖");
+        }
+        if (dto.getId() == null) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂橧D涓嶈兘涓虹┖");
+        }
+        if (dto.getFeedingQuantity() == null || dto.getFeedingQuantity().compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉℃湰娆¤ˉ鏂欐暟閲忎笉鑳藉皬浜�0");
+        }
+        if (!isFeedingPick(dto)) {
+            throw new ServiceException("绗�" + rowNo + "鏉¤ˉ鏂欑被鍨嬪繀椤讳负2");
+        }
+    }
+
+    private void validateReturnParam(ProductionOrderPickDto dto, int rowNo) {
+        if (dto.getProductionOrderId() == null) {
+            throw new ServiceException("绗�" + rowNo + "鏉$敓浜ц鍗旾D涓嶈兘涓虹┖");
+        }
+        if (dto.getId() == null) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢鏂橧D涓嶈兘涓虹┖");
+        }
+        if (dto.getReturnQty() == null || dto.getReturnQty().compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉¢��鏂欐暟閲忎笉鑳戒负绌轰笖涓嶈兘灏忎簬0");
+        }
+        if (dto.getActualQty() == null || dto.getActualQty().compareTo(BigDecimal.ZERO) < 0) {
+            throw new ServiceException("绗�" + rowNo + "鏉″疄闄呮暟閲忎笉鑳戒负绌轰笖涓嶈兘灏忎簬0");
+        }
+    }
+
+    private boolean isFeedingRequest(ProductionOrderPickDto dto) {
+        if (isFeedingPick(dto)) {
+            return true;
+        }
+        if (dto.getPickList() == null || dto.getPickList().isEmpty()) {
+            return false;
+        }
+        return dto.getPickList().stream()
+                .filter(Objects::nonNull)
+                .anyMatch(this::isFeedingPick);
+    }
+
+    private boolean isFeedingPick(ProductionOrderPickDto dto) {
+        return dto != null && Objects.equals(dto.getPickType(), PICK_TYPE_FEEDING);
+    }
+
+    private boolean isReturnRequest(ProductionOrderPickDto dto) {
+        if (isReturnPick(dto)) {
+            return true;
+        }
+        if (dto.getPickList() == null || dto.getPickList().isEmpty()) {
+            return false;
+        }
+        return dto.getPickList().stream()
+                .filter(Objects::nonNull)
+                .anyMatch(this::isReturnPick);
+    }
+
+    private boolean isReturnPick(ProductionOrderPickDto dto) {
+        return dto != null && Boolean.TRUE.equals(dto.getReturned());
+    }
+
+    private BigDecimal sumFeedingQuantity(Long productionOrderId, Long pickId) {
+        List<ProductionOrderPickRecord> feedingRecords = productionOrderPickRecordMapper.selectList(
+                Wrappers.<ProductionOrderPickRecord>lambdaQuery()
+                        .eq(ProductionOrderPickRecord::getProductionOrderId, productionOrderId)
+                        .eq(ProductionOrderPickRecord::getPickId, pickId)
+                        .eq(ProductionOrderPickRecord::getPickType, PICK_TYPE_FEEDING));
+        return feedingRecords.stream()
+                .map(ProductionOrderPickRecord::getPickQuantity)
+                .map(this::defaultDecimal)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+    }
+
+    private BigDecimal calculateActualQty(ProductionOrderPick pick, BigDecimal feedingQty) {
+        return defaultDecimal(pick.getQuantity())
+                .add(defaultDecimal(feedingQty))
+                .subtract(defaultDecimal(pick.getReturnQty()));
+    }
+
+    private String normalizeBatchNo(String batchNo) {
+        if (StringUtils.isEmpty(batchNo)) {
+            return null;
+        }
+        String trimBatchNo = batchNo.trim();
+        return trimBatchNo.isEmpty() ? null : trimBatchNo;
+    }
+    private List<String> resolveBatchNoList(ProductionOrderPickDto dto) {
+        List<String> normalizedBatchNoList = normalizeBatchNoList(dto.getBatchNoList());
+        if (!normalizedBatchNoList.isEmpty()) {
+            return normalizedBatchNoList;
+        }
+        return parseBatchNoValue(dto.getBatchNo());
+    }
+
+    private String pickInventoryBatchNo(List<String> batchNoList) {
+        if (batchNoList == null || batchNoList.isEmpty()) {
+            return null;
+        }
+        return batchNoList.get(0);
+    }
+
+    private String resolveInventoryBatchNoFromStored(String storedBatchNo) {
+        return pickInventoryBatchNo(parseBatchNoValue(storedBatchNo));
+    }
+
+    private String formatBatchNoStorage(List<String> batchNoList) {
+        if (batchNoList == null || batchNoList.isEmpty()) {
+            return null;
+        }
+        if (batchNoList.size() == 1) {
+            return batchNoList.get(0);
+        }
+        return String.join(",", batchNoList);
+    }
+
+    private List<String> normalizeBatchNoList(List<String> batchNoList) {
+        if (batchNoList == null || batchNoList.isEmpty()) {
+            return Collections.emptyList();
+        }
+        LinkedHashSet<String> normalizedSet = new LinkedHashSet<>();
+        for (String batchNo : batchNoList) {
+            String normalizedBatchNo = normalizeBatchNo(batchNo);
+            if (!StringUtils.isEmpty(normalizedBatchNo)) {
+                normalizedSet.add(normalizedBatchNo);
+            }
+        }
+        return new ArrayList<>(normalizedSet);
+    }
+
+    private void fillBatchNoList(List<ProductionOrderPickVo> detailList) {
+        if (detailList == null || detailList.isEmpty()) {
+            return;
+        }
+        Map<String, LinkedHashSet<String>> batchNoGroupMap = new HashMap<>();
+        for (ProductionOrderPickVo detail : detailList) {
+            String key = buildBatchNoGroupKey(detail);
+            LinkedHashSet<String> batchSet = batchNoGroupMap.computeIfAbsent(key, k -> new LinkedHashSet<>());
+            batchSet.addAll(parseBatchNoValue(detail.getBatchNo()));
+            if (detail.getBatchNoList() != null && !detail.getBatchNoList().isEmpty()) {
+                batchSet.addAll(normalizeBatchNoList(detail.getBatchNoList()));
+            }
+        }
+        for (ProductionOrderPickVo detail : detailList) {
+            String key = buildBatchNoGroupKey(detail);
+            LinkedHashSet<String> batchSet = batchNoGroupMap.get(key);
+            detail.setBatchNoList(batchSet == null ? Collections.emptyList() : new ArrayList<>(batchSet));
+        }
+    }
+
+    private void fillSelectableBatchNoList(List<ProductionOrderPickVo> detailList) {
+        if (detailList == null || detailList.isEmpty()) {
+            return;
+        }
+        Set<Long> productModelIdSet = detailList.stream()
+                .map(ProductionOrderPickVo::getProductModelId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (productModelIdSet.isEmpty()) {
+            return;
+        }
+        List<StockInventory> stockBatchList = stockInventoryMapper.listSelectableBatchNoByProductModelIds(
+                new ArrayList<>(productModelIdSet));
+        Map<Long, LinkedHashSet<String>> stockBatchMap = new HashMap<>();
+        for (StockInventory stockInventory : stockBatchList) {
+            if (stockInventory == null || stockInventory.getProductModelId() == null) {
+                continue;
+            }
+            String normalizedBatchNo = normalizeBatchNo(stockInventory.getBatchNo());
+            if (StringUtils.isEmpty(normalizedBatchNo)) {
+                continue;
+            }
+            stockBatchMap.computeIfAbsent(stockInventory.getProductModelId(), k -> new LinkedHashSet<>())
+                    .add(normalizedBatchNo);
+        }
+        for (ProductionOrderPickVo detail : detailList) {
+            LinkedHashSet<String> mergedBatchSet = new LinkedHashSet<>();
+            mergedBatchSet.addAll(normalizeBatchNoList(detail.getBatchNoList()));
+            LinkedHashSet<String> selectableBatchSet = stockBatchMap.get(detail.getProductModelId());
+            if (selectableBatchSet != null) {
+                mergedBatchSet.addAll(selectableBatchSet);
+            }
+            detail.setBatchNoList(new ArrayList<>(mergedBatchSet));
+        }
+    }
+
+    private String buildBatchNoGroupKey(ProductionOrderPickVo detail) {
+        return String.valueOf(detail.getProductionOrderId()) + "|"
+                + String.valueOf(detail.getProductModelId()) + "|"
+                + String.valueOf(detail.getTechnologyOperationId()) + "|"
+                + String.valueOf(detail.getOperationName());
+    }
+
+    private List<String> parseBatchNoValue(String rawBatchNoValue) {
+        String normalizedValue = normalizeBatchNo(rawBatchNoValue);
+        if (StringUtils.isEmpty(normalizedValue)) {
+            return Collections.emptyList();
+        }
+        if (normalizedValue.startsWith("[") && normalizedValue.endsWith("]")) {
+            String value = normalizedValue.substring(1, normalizedValue.length() - 1);
+            if (StringUtils.isEmpty(value)) {
+                return Collections.emptyList();
+            }
+            List<String> parsed = Arrays.stream(value.split(","))
+                    .map(item -> item == null ? null : item.trim().replace("\"", "").replace("'", ""))
+                    .collect(Collectors.toList());
+            return normalizeBatchNoList(parsed);
+        }
+        if (normalizedValue.contains(",")) {
+            List<String> parsed = Arrays.stream(normalizedValue.split(","))
+                    .map(item -> item == null ? null : item.trim())
+                    .collect(Collectors.toList());
+            return normalizeBatchNoList(parsed);
+        }
+        return Collections.singletonList(normalizedValue);
+    }
+
+    private LambdaQueryWrapper<StockInventory> buildStockWrapper(Long productModelId, String batchNo) {
+        LambdaQueryWrapper<StockInventory> wrapper = Wrappers.<StockInventory>lambdaQuery()
+                .eq(StockInventory::getProductModelId, productModelId);
+        if (StringUtils.isEmpty(batchNo)) {
+            wrapper.isNull(StockInventory::getBatchNo);
+        } else {
+            wrapper.eq(StockInventory::getBatchNo, batchNo);
+        }
+        return wrapper;
+    }
+
+    private BigDecimal defaultDecimal(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value;
+    }
+
+    private String formatQuantity(BigDecimal value) {
+        return defaultDecimal(value).stripTrailingZeros().toPlainString();
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java
new file mode 100644
index 0000000..a99b194
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationParamServiceImpl.java
@@ -0,0 +1,167 @@
+package com.ruoyi.production.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.production.bean.dto.ProductionOrderRoutingOperationParamDto;
+import com.ruoyi.production.bean.vo.ProductionOrderRoutingOperationParamVo;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingOperationParamMapper;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import com.ruoyi.production.service.ProductionOrderRoutingOperationParamService;
+import com.ruoyi.technology.mapper.TechnologyParamMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationParamMapper;
+import com.ruoyi.technology.pojo.TechnologyParam;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class ProductionOrderRoutingOperationParamServiceImpl extends ServiceImpl<ProductionOrderRoutingOperationParamMapper, ProductionOrderRoutingOperationParam>
+        implements ProductionOrderRoutingOperationParamService {
+
+    private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
+    private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
+    private final ProductionOrderMapper productionOrderMapper;
+    private final TechnologyParamMapper technologyParamMapper;
+    private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper;
+
+    @Override
+    public IPage<ProductionOrderRoutingOperationParamVo> pageProductionOrderRoutingOperationParam(Page<ProductionOrderRoutingOperationParamDto> page,
+                                                                                                  ProductionOrderRoutingOperationParamDto dto) {
+        Page<ProductionOrderRoutingOperationParam> entityPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
+        return this.page(entityPage, buildQueryWrapper(dto))
+                .convert(item -> BeanUtil.copyProperties(item, ProductionOrderRoutingOperationParamVo.class));
+    }
+
+    @Override
+    public List<ProductionOrderRoutingOperationParamVo> listProductionOrderRoutingOperationParam(ProductionOrderRoutingOperationParamDto dto) {
+        return BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOrderRoutingOperationParamVo.class);
+    }
+
+    @Override
+    public ProductionOrderRoutingOperationParamVo getProductionOrderRoutingOperationParamInfo(Long id) {
+        ProductionOrderRoutingOperationParam item = this.getById(id);
+        return item == null ? null : BeanUtil.copyProperties(item, ProductionOrderRoutingOperationParamVo.class);
+    }
+
+    @Override
+    public boolean saveProductionOrderRoutingOperationParam(ProductionOrderRoutingOperationParam item) {
+        ProductionOrderRoutingOperation routingOperation = getRoutingOperation(item.getProductionOrderRoutingOperationId());
+        fillFromSourceParam(item, routingOperation);
+        validateManualFields(item);
+        checkDuplicate(item);
+        return this.saveOrUpdate(item);
+    }
+
+    @Override
+    public boolean removeProductionOrderRoutingOperationParam(Long id) {
+        return this.removeById(id);
+    }
+
+    private LambdaQueryWrapper<ProductionOrderRoutingOperationParam> buildQueryWrapper(ProductionOrderRoutingOperationParamDto dto) {
+        ProductionOrderRoutingOperationParam query = dto == null ? new ProductionOrderRoutingOperationParam() : dto;
+        return Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                .eq(query.getId() != null, ProductionOrderRoutingOperationParam::getId, query.getId())
+                .eq(query.getProductionProductMainId() != null,
+                        ProductionOrderRoutingOperationParam::getProductionProductMainId, query.getProductionProductMainId())
+                .isNull(query.getProductionProductMainId() == null,
+                        ProductionOrderRoutingOperationParam::getProductionProductMainId)
+                .eq(query.getProductionOrderId() != null, ProductionOrderRoutingOperationParam::getProductionOrderId, query.getProductionOrderId())
+                .eq(query.getProductionOrderRoutingOperationId() != null, ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, query.getProductionOrderRoutingOperationId())
+                .eq(query.getTechnologyOperationId() != null,
+                        ProductionOrderRoutingOperationParam::getTechnologyOperationId, query.getTechnologyOperationId())
+                .eq(query.getTechnologyRoutingOperationParamId() != null,
+                        ProductionOrderRoutingOperationParam::getTechnologyRoutingOperationParamId, query.getTechnologyRoutingOperationParamId())
+                .eq(query.getTechnologyOperationParamId() != null,
+                        ProductionOrderRoutingOperationParam::getTechnologyOperationParamId, query.getTechnologyOperationParamId())
+                .like(query.getParamCode() != null && !query.getParamCode().trim().isEmpty(),
+                        ProductionOrderRoutingOperationParam::getParamCode, query.getParamCode())
+                .like(query.getParamName() != null && !query.getParamName().trim().isEmpty(),
+                        ProductionOrderRoutingOperationParam::getParamName, query.getParamName())
+                .orderByAsc(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId)
+                .orderByAsc(ProductionOrderRoutingOperationParam::getId);
+    }
+
+    private ProductionOrderRoutingOperation getRoutingOperation(Long productionOrderRoutingOperationId) {
+        if (productionOrderRoutingOperationId == null) {
+            throw new ServiceException("productionOrderRoutingOperationId is required");
+        }
+        ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOrderRoutingOperationId);
+        if (routingOperation == null) {
+            throw new ServiceException("Production order routing operation not found");
+        }
+        return routingOperation;
+    }
+
+    private void fillFromSourceParam(ProductionOrderRoutingOperationParam item, ProductionOrderRoutingOperation routingOperation) {
+        item.setProductionOrderId(routingOperation.getProductionOrderId());
+        item.setProductionOrderRoutingOperationId(routingOperation.getId());
+        ProductionOrder productionOrder = productionOrderMapper.selectById(routingOperation.getProductionOrderId());
+        if (productionOrder == null) {
+            throw new ServiceException("Production order not found");
+        }
+        if (item.getParamId() == null) {
+            return;
+        }
+        TechnologyParam sourceParam = technologyParamMapper.selectById(item.getParamId());
+        if (sourceParam == null) {
+            throw new ServiceException("Technology  param not found");
+        }
+        if (item.getTechnologyOperationParamId() != null) {
+            TechnologyRoutingOperationParam sourceRoutingOperationParam = technologyRoutingOperationParamMapper.selectById(item.getTechnologyOperationParamId());
+            item.setTechnologyOperationId(sourceRoutingOperationParam.getTechnologyOperationId());
+            item.setTechnologyOperationParamId(sourceRoutingOperationParam.getTechnologyOperationParamId());
+            if (item.getStandardValue() == null) {
+                item.setStandardValue(sourceRoutingOperationParam.getStandardValue());
+            }
+        }
+        item.setParamId(sourceParam.getId());
+        item.setParamCode(sourceParam.getParamCode());
+        item.setParamName(sourceParam.getParamName());
+        item.setParamType(sourceParam.getParamType());
+        item.setParamFormat(sourceParam.getParamFormat());
+        item.setUnit(sourceParam.getUnit());
+        item.setIsRequired(sourceParam.getIsRequired());
+        if (item.getRemark() == null || item.getRemark().trim().isEmpty()) {
+            item.setRemark(sourceParam.getRemark());
+        }
+    }
+
+    private void validateManualFields(ProductionOrderRoutingOperationParam item) {
+        if (item.getParamCode() == null || item.getParamCode().trim().isEmpty()) {
+            throw new ServiceException("paramCode is required");
+        }
+        if (item.getParamName() == null || item.getParamName().trim().isEmpty()) {
+            throw new ServiceException("paramName is required");
+        }
+    }
+
+    private void checkDuplicate(ProductionOrderRoutingOperationParam item) {
+        boolean duplicate = productionOrderRoutingOperationParamMapper.selectCount(
+                Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                        .isNull(ProductionOrderRoutingOperationParam::getProductionProductMainId)
+                        .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, item.getProductionOrderRoutingOperationId())
+                        .eq(item.getTechnologyRoutingOperationParamId() != null,
+                                ProductionOrderRoutingOperationParam::getTechnologyRoutingOperationParamId, item.getTechnologyRoutingOperationParamId())
+                        .eq(item.getTechnologyRoutingOperationParamId() == null && item.getParamCode() != null,
+                                ProductionOrderRoutingOperationParam::getParamCode, item.getParamCode())
+                        .ne(item.getId() != null, ProductionOrderRoutingOperationParam::getId, item.getId())
+        ) > 0;
+        if (duplicate) {
+            throw new ServiceException("Duplicate production order routing operation param");
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
new file mode 100644
index 0000000..886da11
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
@@ -0,0 +1,176 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingOperationParamMapper;
+import com.ruoyi.production.mapper.ProductionProductMainMapper;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam;
+import com.ruoyi.production.pojo.ProductionProductMain;
+import com.ruoyi.production.service.ProductionOrderRoutingOperationService;
+import com.ruoyi.production.service.ProductionProductMainService;
+import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
+import com.ruoyi.technology.mapper.TechnologyParamMapper;
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import com.ruoyi.technology.pojo.TechnologyParam;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class ProductionOrderRoutingOperationServiceImpl extends ServiceImpl<ProductionOrderRoutingOperationMapper, ProductionOrderRoutingOperation>
+        implements ProductionOrderRoutingOperationService {
+
+    private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
+    private final ProductionOperationTaskMapper productionOperationTaskMapper;
+    private final ProductionProductMainMapper productionProductMainMapper;
+    private final ProductionProductMainService productionProductMainService;
+    private final TechnologyOperationParamMapper technologyOperationParamMapper;
+    private final TechnologyParamMapper technologyParamMapper;
+    private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
+
+    @Override
+    public R addRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation) {
+        int insert = productionOrderRoutingOperationMapper.insert(productionOrderRoutingOperation);
+        //宸ュ簭鍏宠仈鐨勫弬鏁伴渶瑕佸悓姝ユ柊澧�
+        List<TechnologyOperationParam> technologyOperationParams = technologyOperationParamMapper.selectList(Wrappers.<TechnologyOperationParam>lambdaQuery()
+                .eq(TechnologyOperationParam::getTechnologyOperationId, productionOrderRoutingOperation.getTechnologyOperationId()));
+        if (CollectionUtils.isNotEmpty(technologyOperationParams)){
+            ArrayList<ProductionOrderRoutingOperationParam> productionOrderRoutingOperationParams = new ArrayList<>();
+            for (TechnologyOperationParam technologyOperationParam : technologyOperationParams) {
+                TechnologyParam technologyParam = technologyParamMapper.selectById(technologyOperationParam.getTechnologyParamId());
+                ProductionOrderRoutingOperationParam productionOrderRoutingOperationParam = new ProductionOrderRoutingOperationParam();
+                productionOrderRoutingOperationParam.setProductionOrderId(productionOrderRoutingOperation.getProductionOrderId());
+                productionOrderRoutingOperationParam.setProductionOrderRoutingOperationId(productionOrderRoutingOperation.getId());
+                productionOrderRoutingOperationParam.setParamCode(technologyParam.getParamCode());
+                productionOrderRoutingOperationParam.setParamName(technologyParam.getParamName());
+                productionOrderRoutingOperationParam.setParamType(technologyParam.getParamType());
+                productionOrderRoutingOperationParam.setParamFormat(technologyParam.getParamFormat());
+                productionOrderRoutingOperationParam.setUnit(technologyParam.getUnit());
+                productionOrderRoutingOperationParam.setIsRequired(technologyParam.getIsRequired());
+                productionOrderRoutingOperationParam.setRemark(technologyParam.getRemark());
+                productionOrderRoutingOperationParam.setParamId(technologyParam.getId());
+                productionOrderRoutingOperationParam.setTechnologyOperationId(productionOrderRoutingOperation.getTechnologyOperationId());
+                productionOrderRoutingOperationParams.add(productionOrderRoutingOperationParam);
+            }
+            productionOrderRoutingOperationParamMapper.insert(productionOrderRoutingOperationParams);
+        }
+        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        if (insert > 0) {
+            ProductionOperationTask lastTask = productionOperationTaskMapper.selectOne(
+                    Wrappers.<ProductionOperationTask>lambdaQuery()
+                            .likeRight(ProductionOperationTask::getWorkOrderNo, "GD" + datePrefix)
+                            .orderByDesc(ProductionOperationTask::getWorkOrderNo)
+                            .last("limit 1"));
+            int sequenceNumber = 1;
+            if (lastTask != null && lastTask.getWorkOrderNo() != null) {
+                String lastNo = lastTask.getWorkOrderNo();
+                if (lastNo.startsWith("GD" + datePrefix)) {
+                    String seqStr = lastNo.substring(("GD" + datePrefix).length());
+                    try {
+                        sequenceNumber = Integer.parseInt(seqStr) + 1;
+                    } catch (NumberFormatException e) {
+                        sequenceNumber = 1;
+                    }
+                }
+            }
+            String workOrderNoStr = "GD" + String.format("%s%03d", datePrefix, sequenceNumber);
+            ProductionOperationTask productionOperationTask = new ProductionOperationTask();
+            productionOperationTask.setProductionOrderRoutingOperationId(productionOrderRoutingOperation.getId());
+            productionOperationTask.setProductionOrderId(productionOrderRoutingOperation.getProductionOrderId());
+            productionOperationTask.setPlanQuantity(BigDecimal.ZERO);
+            productionOperationTask.setCompleteQuantity(BigDecimal.ZERO);
+            productionOperationTask.setWorkOrderNo(workOrderNoStr);
+            productionOperationTask.setStatus(1);
+            productionOperationTaskMapper.insert(productionOperationTask);
+        }
+        return R.ok();
+    }
+
+    @Override
+    public R deleteRouteItem(Long id) {
+        try {
+            ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectOne(
+                    new LambdaQueryWrapper<ProductionOperationTask>()
+                            .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, id)
+                            .last("limit 1"));
+            if (productionOperationTask == null) {
+                throw new RuntimeException("鍒犻櫎澶辫触锛氭湭鎵惧埌鍏宠仈鐨勭敓浜у伐鍗�");
+            }
+            if (productionOperationTask.getCompleteQuantity() != null
+                    && BigDecimal.ZERO.compareTo(productionOperationTask.getCompleteQuantity()) < 0) {
+                throw new RuntimeException("鍒犻櫎澶辫触锛氳宸ュ崟宸插紑濮嬬敓浜э紝璇峰厛鍒犻櫎鐢熶骇鎶ュ伐");
+            }
+            List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(
+                    new LambdaQueryWrapper<ProductionProductMain>()
+                            .eq(ProductionProductMain::getProductionOperationTaskId, productionOperationTask.getId()));
+            for (ProductionProductMain main : productionProductMains) {
+                productionProductMainService.removeProductMain(main.getId());
+            }
+            Long productionOrderId = productionOperationTask.getProductionOrderId();
+            Long routingId = null;
+            ProductionOrderRoutingOperation deleteItem = productionOrderRoutingOperationMapper.selectById(id);
+            if (deleteItem != null) {
+                routingId = deleteItem.getOrderRoutingId();
+            }
+            productionOperationTaskMapper.delete(new LambdaQueryWrapper<ProductionOperationTask>()
+                    .eq(ProductionOperationTask::getProductionOrderRoutingOperationId, id));
+            productionOrderRoutingOperationMapper.deleteById(id);
+            if (routingId != null) {
+                List<ProductionOrderRoutingOperation> operationList = productionOrderRoutingOperationMapper.selectList(
+                        Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
+                                .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingId)
+                                .eq(ProductionOrderRoutingOperation::getProductionOrderId, productionOrderId)
+                                .orderByAsc(ProductionOrderRoutingOperation::getDragSort));
+                for (int i = 0; i < operationList.size(); i++) {
+                    ProductionOrderRoutingOperation item = operationList.get(i);
+                    if (!Integer.valueOf(i + 1).equals(item.getDragSort())) {
+                        item.setDragSort(i + 1);
+                        productionOrderRoutingOperationMapper.updateById(item);
+                    }
+                }
+            }
+            return R.ok();
+        } catch (Exception e) {
+            throw new RuntimeException("鍒犻櫎鐢熶骇宸ヨ壓璺嚎澶辫触锛�" + e.getMessage());
+        }
+    }
+
+    @Override
+    public int sortRouteItem(ProductionOrderRoutingOperation productionOrderRoutingOperation) {
+        ProductionOrderRoutingOperation oldItem = productionOrderRoutingOperationMapper.selectById(productionOrderRoutingOperation.getId());
+        List<ProductionOrderRoutingOperation> operationList = productionOrderRoutingOperationMapper.selectList(
+                Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
+                        .eq(ProductionOrderRoutingOperation::getOrderRoutingId, oldItem.getOrderRoutingId())
+                        .orderByAsc(ProductionOrderRoutingOperation::getDragSort));
+        Integer targetPosition = productionOrderRoutingOperation.getDragSort();
+        if (targetPosition != null && targetPosition >= 1) {
+            operationList.removeIf(item -> item.getId().equals(oldItem.getId()));
+            operationList.add(targetPosition - 1, oldItem);
+            for (int i = 0; i < operationList.size(); i++) {
+                ProductionOrderRoutingOperation item = operationList.get(i);
+                int dragSort = i + 1;
+                if (!Integer.valueOf(dragSort).equals(item.getDragSort())) {
+                    item.setDragSort(dragSort);
+                    productionOrderRoutingOperationMapper.updateById(item);
+                }
+            }
+            return 1;
+        }
+        return 0;
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingServiceImpl.java
new file mode 100644
index 0000000..10443c1
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingServiceImpl.java
@@ -0,0 +1,35 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.bean.vo.ProductionOrderRoutingOperationVo;
+import com.ruoyi.production.mapper.ProductionOrderRoutingMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper;
+import com.ruoyi.production.pojo.ProductionOrderRouting;
+import com.ruoyi.production.service.ProductionOrderRoutingService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class ProductionOrderRoutingServiceImpl extends ServiceImpl<ProductionOrderRoutingMapper, ProductionOrderRouting> implements ProductionOrderRoutingService {
+
+    private final ProductionOrderRoutingMapper productionOrderRoutingMapper;
+    private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
+
+    @Override
+    public ProductionOrderRouting listMain(Long orderId) {
+        return productionOrderRoutingMapper.selectOne(
+                Wrappers.<ProductionOrderRouting>lambdaQuery()
+                        .eq(ProductionOrderRouting::getProductionOrderId, orderId)
+                        .orderByDesc(ProductionOrderRouting::getId)
+                        .last("limit 1"));
+    }
+
+    @Override
+    public List<ProductionOrderRoutingOperationVo> listItem(Long orderId) {
+        return productionOrderRoutingOperationMapper.selectVoListByOrderId(orderId);
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
new file mode 100644
index 0000000..9973d98
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -0,0 +1,952 @@
+package com.ruoyi.production.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.basic.mapper.StorageBlobMapper;
+import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.basic.pojo.StorageBlob;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.common.constant.StorageAttachmentConstants;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.production.bean.dto.ProductionOperationTaskDto;
+import com.ruoyi.production.bean.dto.ProductionOrderDto;
+import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
+import com.ruoyi.production.bean.vo.ProductionOperationTaskVo;
+import com.ruoyi.production.bean.vo.ProductionOrderPickVo;
+import com.ruoyi.production.bean.vo.ProductionOrderVo;
+import com.ruoyi.production.bean.vo.ProductionPlanVo;
+import com.ruoyi.production.bean.vo.ProductionOrderWorkOrderDetailVo;
+import com.ruoyi.production.enums.ProductOrderStatusEnum;
+import com.ruoyi.production.mapper.*;
+import com.ruoyi.production.pojo.*;
+import com.ruoyi.quality.mapper.QualityInspectFileMapper;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.mapper.QualityInspectParamMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectFile;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.production.service.ProductionOrderService;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.pojo.StockInventory;
+import com.ruoyi.technology.mapper.*;
+import com.ruoyi.technology.pojo.*;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class ProductionOrderServiceImpl extends ServiceImpl<ProductionOrderMapper, ProductionOrder> implements ProductionOrderService {
+
+    private final ProductionOrderRoutingMapper productionOrderRoutingMapper;
+    private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
+    private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
+    private final ProductionOperationTaskMapper productionOperationTaskMapper;
+    private final ProductionOrderBomMapper productionOrderBomMapper;
+    private final ProductionBomStructureMapper productionBomStructureMapper;
+    private final ProductionProductMainMapper productionProductMainMapper;
+    private final ProductionProductOutputMapper productionProductOutputMapper;
+    private final ProductionOrderPickMapper productionOrderPickMapper;
+    private final ProductionOrderPickRecordMapper productionOrderPickRecordMapper;
+    private final QualityInspectMapper qualityInspectMapper;
+    private final QualityInspectParamMapper qualityInspectParamMapper;
+    private final QualityInspectFileMapper qualityInspectFileMapper;
+    private final ProductionPlanMapper productionPlanMapper;
+    private final StockInventoryMapper stockInventoryMapper;
+    private final StorageAttachmentMapper storageAttachmentMapper;
+    private final StorageBlobMapper storageBlobMapper;
+    private final SalesLedgerMapper salesLedgerMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final TechnologyRoutingMapper technologyRoutingMapper;
+    private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+    private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper;
+    private final TechnologyOperationMapper technologyOperationMapper;
+    private final TechnologyBomMapper technologyBomMapper;
+    private final TechnologyBomStructureMapper technologyBomStructureMapper;
+    private final FileUtil fileUtil;
+
+    @Override
+    public IPage<ProductionOrderVo> pageProductionOrder(Page<ProductionOrderDto> page, ProductionOrderDto dto) {
+        Page<ProductionOrderVo> result = (Page<ProductionOrderVo>) baseMapper.pageProductionOrder(page, dto);
+        fillProductImages(result.getRecords());
+        return result;
+    }
+
+    @Override
+    public List<ProductionOrderVo> listProductionOrder(ProductionOrderDto dto) {
+        List<ProductionOrderVo> records = baseMapper.listProductionOrder(dto);
+        fillProductImages(records);
+        return records;
+    }
+
+    @Override
+    public ProductionOrderVo getProductionOrderInfo(Long id) {
+        ProductionOrderVo item = baseMapper.getProductionOrderInfo(id);
+        if (item == null) {
+            return null;
+        }
+        fillProductImages(java.util.Collections.singletonList(item));
+        return item;
+    }
+
+    @Override
+    public boolean saveProductionOrder(ProductionOrder productionOrder) {
+        ProductionOrder oldOrder = productionOrder.getId() == null ? null : this.getById(productionOrder.getId());
+        // 涓嬪崟鍏ュ彛缁熶竴琛ラ綈鏉ユ簮鍗曟嵁銆佽鍒掑拰宸ヨ壓淇℃伅锛岄伩鍏嶅墠绔垎鍒紶澶氬瀛楁銆�
+        validateAndFillOrder(productionOrder, oldOrder);
+        if (productionOrder.getNpsNo() == null || productionOrder.getNpsNo().trim().isEmpty()) {
+            productionOrder.setNpsNo(generateNextOrderNo());
+        }
+        if (productionOrder.getCompleteQuantity() == null) {
+            productionOrder.setCompleteQuantity(BigDecimal.ZERO);
+        }
+        if (productionOrder.getStatus() == null) {
+            productionOrder.setStatus(ProductOrderStatusEnum.WAIT.getCode());
+        }
+        boolean saved = this.saveOrUpdate(productionOrder);
+        if (!saved) {
+            return false;
+        }
+        boolean needSync = productionOrder.getTechnologyRoutingId() != null
+                && (oldOrder == null
+                || !Objects.equals(oldOrder.getTechnologyRoutingId(), productionOrder.getTechnologyRoutingId())
+                || !Objects.equals(oldOrder.getProductModelId(), productionOrder.getProductModelId())
+                || compareDecimal(oldOrder.getQuantity(), productionOrder.getQuantity()) != 0
+                || productionOrderRoutingMapper.selectCount(Wrappers.<ProductionOrderRouting>lambdaQuery()
+                        .eq(ProductionOrderRouting::getProductionOrderId, productionOrder.getId())) == 0);
+        if (needSync) {
+            syncProductionOrderSnapshot(productionOrder.getId());
+        }
+        return true;
+    }
+
+    @Override
+    public boolean removeProductionOrder(List<Long> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        for (Long id : ids) {
+            ProductionOrder productionOrder = this.getById(id);
+            clearProductionSnapshot(id);
+            releaseProductionPlanIssueStatus(productionOrder);
+        }
+        return this.removeByIds(ids);
+    }
+
+    @Override
+    public Integer bindingRoute(ProductionOrderDto productionOrderDto) {
+        if (productionOrderDto == null || productionOrderDto.getId() == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟ID涓嶈兘涓虹┖");
+        }
+        ProductionOrder productionOrder = this.getById(productionOrderDto.getId());
+        if (productionOrder == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+
+        Long targetRoutingId = productionOrderDto.getTechnologyRoutingId() == null
+                ? productionOrder.getTechnologyRoutingId()
+                : productionOrderDto.getTechnologyRoutingId();
+        if (targetRoutingId == null) {
+            throw new ServiceException("宸ヨ壓璺嚎ID涓嶈兘涓虹┖");
+        }
+        TechnologyRouting targetRouting = technologyRoutingMapper.selectById(targetRoutingId);
+        if (targetRouting == null) {
+            throw new ServiceException("宸ヨ壓璺嚎涓嶅瓨鍦�");
+        }
+        if (productionOrder.getProductModelId() != null
+                && !Objects.equals(productionOrder.getProductModelId(), targetRouting.getProductModelId())) {
+            throw new ServiceException("宸ヨ壓璺嚎涓庣敓浜ц鍗曚骇鍝佽鏍间笉鍖归厤");
+        }
+
+        if (ProductOrderStatusEnum.isStarted(productionOrder.getStatus())
+                && !Objects.equals(productionOrder.getTechnologyRoutingId(), targetRoutingId)) {
+            throw new ServiceException("鐢熶骇璁㈠崟宸插紑宸ワ紝涓嶈兘淇敼宸ヨ壓璺嚎");
+        }
+
+        if (!Objects.equals(productionOrder.getTechnologyRoutingId(), targetRoutingId)) {
+            ProductionOrder update = new ProductionOrder();
+            update.setId(productionOrder.getId());
+            update.setTechnologyRoutingId(targetRoutingId);
+            if (!this.updateById(update)) {
+                throw new ServiceException("缁戝畾宸ヨ壓璺嚎澶辫触");
+            }
+        }
+
+        // 缁戝畾璺嚎浠呴噸寤鸿鍗曚晶蹇収鏁版嵁
+        return syncProductionOrderSnapshot(productionOrder.getId());
+    }
+
+    @Override
+    public List<ProductionPlanVo> getSource(Long id) {
+        ProductionOrder productionOrder = baseMapper.selectById(id);
+        if (productionOrder != null && productionOrder.getProductionPlanIds() != null) {
+            List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds());
+            return productionPlanMapper.getSource(planIds);
+        }
+        return null;
+    }
+
+    @Override
+    public int syncProductionOrderSnapshot(Long productionOrderId) {
+        ProductionOrder productionOrder = this.getById(productionOrderId);
+        if (productionOrder == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+        if (productionOrder.getTechnologyRoutingId() == null) {
+            throw new ServiceException("宸ヨ壓璺嚎ID涓嶈兘涓虹┖");
+        }
+        TechnologyRouting technologyRouting = technologyRoutingMapper.selectById(productionOrder.getTechnologyRoutingId());
+        if (technologyRouting == null) {
+            throw new ServiceException("宸ヨ壓璺嚎涓嶅瓨鍦�");
+        }
+        // 璁㈠崟蹇収鎸夆�滃厛娓呭悗寤衡�濆鐞嗭紝淇濊瘉宸ヨ壓璺嚎銆佸伐搴忋�佸弬鏁般�丅OM 鍏ㄩ儴鏉ヨ嚜鍚屼竴鐗堟湰銆�
+        clearProductionSnapshot(productionOrderId);
+        ProductionOrderBom orderBom = syncProductionOrderBomSnapshot(productionOrder, technologyRouting);
+
+        ProductionOrderRouting orderRouting = new ProductionOrderRouting();
+        orderRouting.setProductionOrderId(productionOrder.getId());
+        orderRouting.setTechnologyRoutingId(technologyRouting.getId());
+        orderRouting.setProductModelId(technologyRouting.getProductModelId());
+        orderRouting.setProcessRouteCode(technologyRouting.getProcessRouteCode());
+        orderRouting.setDescription(technologyRouting.getDescription());
+        orderRouting.setBomId(technologyRouting.getBomId());
+        orderRouting.setOrderBomId(orderBom == null ? null : orderBom.getId());
+        productionOrderRoutingMapper.insert(orderRouting);
+
+        int syncedParamCount = 0;
+        List<TechnologyRoutingOperation> routingOperations = technologyRoutingOperationMapper.selectList(
+                Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                        .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId())
+                        .orderByDesc(TechnologyRoutingOperation::getDragSort)
+                        .orderByDesc(TechnologyRoutingOperation::getId));
+        Map<Long, String> operationNameMap = technologyOperationMapper.selectBatchIds(
+                        routingOperations.stream()
+                                .map(TechnologyRoutingOperation::getTechnologyOperationId)
+                                .filter(Objects::nonNull)
+                                .collect(Collectors.toSet()))
+                .stream()
+                .collect(Collectors.toMap(TechnologyOperation::getId, TechnologyOperation::getName, (a, b) -> a));
+        Integer lastDragSort = routingOperations.stream()
+                .map(TechnologyRoutingOperation::getDragSort)
+                .filter(Objects::nonNull)
+                .max(Integer::compareTo)
+                .orElse(null);
+        for (TechnologyRoutingOperation sourceOperation : routingOperations) {
+            // 璁㈠崟宸ュ簭淇濆瓨鐨勬槸宸ヨ壓宸ュ簭蹇収锛屽悗缁姤宸ュ彧渚濊禆蹇収锛屼笉鍐嶇洿鎺ュ紩鐢ㄥ伐鑹轰富鏁版嵁銆�
+            ProductionOrderRoutingOperation targetOperation = new ProductionOrderRoutingOperation();
+            targetOperation.setProductionOrderId(productionOrder.getId());
+            targetOperation.setTechnologyRoutingOperationId(sourceOperation.getId());
+            targetOperation.setOrderRoutingId(orderRouting.getId());
+            targetOperation.setProductModelId(sourceOperation.getProductModelId());
+            targetOperation.setDragSort(sourceOperation.getDragSort());
+            targetOperation.setIsProduction(sourceOperation.getIsProduction());
+            targetOperation.setIsQuality(sourceOperation.getIsQuality());
+            targetOperation.setOperationName(operationNameMap.get(sourceOperation.getTechnologyOperationId()));
+            targetOperation.setTechnologyOperationId(sourceOperation.getTechnologyOperationId());
+            productionOrderRoutingOperationMapper.insert(targetOperation);
+
+            boolean isLastOperation = lastDragSort != null && Objects.equals(sourceOperation.getDragSort(), lastDragSort);
+            if (isLastOperation || Boolean.TRUE.equals(targetOperation.getIsProduction())) {
+                ProductionOperationTask task = new ProductionOperationTask();
+                task.setProductionOrderRoutingOperationId(targetOperation.getId());
+                task.setProductionOrderId(productionOrder.getId());
+                task.setPlanQuantity(defaultDecimal(productionOrder.getQuantity()));
+                task.setCompleteQuantity(BigDecimal.ZERO);
+                task.setWorkOrderNo(generateNextTaskNo());
+                task.setStatus(2);
+                productionOperationTaskMapper.insert(task);
+            }
+
+            List<TechnologyRoutingOperationParam> sourceParams = technologyRoutingOperationParamMapper.selectList(
+                    Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
+                            .eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, sourceOperation.getId())
+                            .orderByAsc(TechnologyRoutingOperationParam::getId));
+            for (TechnologyRoutingOperationParam sourceParam : sourceParams) {
+                // 宸ュ簭鎵ц鍙傛暟鍚屾牱鍋氬揩鐓э紝閬垮厤宸ヨ壓鍙傛暟璋冩暣褰卞搷宸蹭笅杈捐鍗曘��
+                ProductionOrderRoutingOperationParam targetParam = new ProductionOrderRoutingOperationParam();
+                targetParam.setProductionOrderId(productionOrder.getId());
+                targetParam.setProductionOrderRoutingOperationId(targetOperation.getId());
+                targetParam.setTechnologyRoutingOperationParamId(sourceParam.getId());
+                targetParam.setParamId(sourceParam.getParamId());
+                targetParam.setTechnologyOperationId(sourceParam.getTechnologyOperationId());
+                targetParam.setTechnologyOperationParamId(sourceParam.getTechnologyOperationParamId());
+                targetParam.setParamCode(sourceParam.getParamCode());
+                targetParam.setParamName(sourceParam.getParamName());
+                targetParam.setParamType(sourceParam.getParamType());
+                targetParam.setParamFormat(sourceParam.getParamFormat());
+                targetParam.setUnit(sourceParam.getUnit());
+                targetParam.setIsRequired(sourceParam.getIsRequired());
+                targetParam.setRemark(sourceParam.getRemark());
+                targetParam.setStandardValue(sourceParam.getStandardValue());
+                productionOrderRoutingOperationParamMapper.insert(targetParam);
+                syncedParamCount++;
+            }
+        }
+        return syncedParamCount;
+    }
+
+    private ProductionOrderBom syncProductionOrderBomSnapshot(ProductionOrder productionOrder, TechnologyRouting technologyRouting) {
+        if (technologyRouting.getBomId() == null) {
+            return null;
+        }
+        TechnologyBom technologyBom = technologyBomMapper.selectById(technologyRouting.getBomId());
+        if (technologyBom == null) {
+            throw new ServiceException("宸ヨ壓BOM涓嶅瓨鍦�");
+        }
+        List<TechnologyBomStructure> structureList = technologyBomStructureMapper.selectList(
+                Wrappers.<TechnologyBomStructure>lambdaQuery()
+                        .eq(TechnologyBomStructure::getBomId, technologyBom.getId())
+                        .orderByAsc(TechnologyBomStructure::getId));
+        TechnologyBomStructure root = structureList.stream().filter(item -> item.getParentId() == null).findFirst().orElse(null);
+        BigDecimal orderQuantity = defaultDecimal(productionOrder.getQuantity());
+
+        ProductionOrderBom orderBom = new ProductionOrderBom();
+        orderBom.setProductionOrderId(productionOrder.getId());
+        orderBom.setBomId(Long.valueOf(technologyBom.getId()));
+        orderBom.setProductModelId(root != null ? root.getProductModelId() : productionOrder.getProductModelId());
+        orderBom.setRemark(technologyBom.getRemark());
+        orderBom.setBomNo(technologyBom.getBomNo());
+        orderBom.setVersion(technologyBom.getVersion());
+        productionOrderBomMapper.insert(orderBom);
+
+        Map<Long, Long> idMap = new HashMap<>();
+        for (TechnologyBomStructure source : structureList) {
+            // 瀛愯妭鐐� parentId 闇�瑕佹槧灏勬垚鏂板揩鐓ц妭鐐� id锛屾墠鑳戒繚鐣欏師濮� BOM 灞傜骇銆�
+            ProductionBomStructure target = new ProductionBomStructure();
+            target.setProductionOrderId(productionOrder.getId());
+            target.setProductionOrderBomId(orderBom.getId());
+            target.setParentId(source.getParentId() == null ? null : idMap.get(source.getParentId()));
+            target.setProductModelId(source.getProductModelId());
+            target.setTechnologyOperationId(source.getOperationId());
+            target.setUnitQuantity(source.getUnitQuantity());
+            target.setDemandedQuantity(source.getUnitQuantity().multiply(orderQuantity));
+            target.setUnit(source.getUnit());
+            productionBomStructureMapper.insert(target);
+            idMap.put(source.getId(), target.getId());
+        }
+        return orderBom;
+    }
+
+    private void clearProductionSnapshot(Long productionOrderId) {
+        // 宸蹭骇鐢熼鏂欒褰曞悗绂佹閲嶅缓锛岄伩鍏嶅鏂�/鎶曟枡渚濇嵁涓庤鍗曞揩鐓ц劚鑺傘��
+        boolean hasPickRecord = productionOrderPickRecordMapper.selectCount(
+                Wrappers.<ProductionOrderPickRecord>lambdaQuery()
+                        .eq(ProductionOrderPickRecord::getProductionOrderId, productionOrderId)) > 0;
+        if (hasPickRecord) {
+            throw new ServiceException("鐢熶骇璁㈠崟宸插瓨鍦ㄩ鏂欒褰曪紝涓嶈兘閲嶆柊鐢熸垚蹇収");
+        }
+        List<Long> taskIds = productionOperationTaskMapper.selectList(
+                        Wrappers.<ProductionOperationTask>lambdaQuery()
+                                .eq(ProductionOperationTask::getProductionOrderId, productionOrderId))
+                .stream().map(ProductionOperationTask::getId).collect(Collectors.toList());
+        if (!taskIds.isEmpty()) {
+            // 宸叉湁鎶ュ伐璁板綍璇存槑璁㈠崟宸插紑宸ワ紝姝ゆ椂涓嶅厑璁稿啀閲嶅缓蹇収銆�
+            boolean started = productionProductMainMapper.selectCount(
+                    Wrappers.<ProductionProductMain>lambdaQuery()
+                            .in(ProductionProductMain::getProductionOperationTaskId, taskIds)) > 0;
+            if (started) {
+                throw new ServiceException("鐢熶骇璁㈠崟宸插紑宸ワ紝涓嶈兘閲嶆柊鐢熸垚蹇収");
+            }
+            productionOperationTaskMapper.delete(Wrappers.<ProductionOperationTask>lambdaQuery()
+                    .eq(ProductionOperationTask::getProductionOrderId, productionOrderId));
+        }
+        productionOrderRoutingOperationParamMapper.delete(Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                .eq(ProductionOrderRoutingOperationParam::getProductionOrderId, productionOrderId));
+        productionOrderRoutingOperationMapper.delete(Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
+                .eq(ProductionOrderRoutingOperation::getProductionOrderId, productionOrderId));
+        productionOrderRoutingMapper.delete(Wrappers.<ProductionOrderRouting>lambdaQuery()
+                .eq(ProductionOrderRouting::getProductionOrderId, productionOrderId));
+        productionBomStructureMapper.delete(Wrappers.<ProductionBomStructure>lambdaQuery()
+                .eq(ProductionBomStructure::getProductionOrderId, productionOrderId));
+        productionOrderBomMapper.delete(Wrappers.<ProductionOrderBom>lambdaQuery()
+                .eq(ProductionOrderBom::getProductionOrderId, productionOrderId));
+        productionOrderPickMapper.delete(Wrappers.<ProductionOrderPick>lambdaQuery()
+                .eq(ProductionOrderPick::getProductionOrderId, productionOrderId));
+    }
+
+    private LambdaQueryWrapper<ProductionOrder> buildQueryWrapper(ProductionOrderDto dto) {
+        ProductionOrder query = dto == null ? new ProductionOrder() : dto;
+        return Wrappers.<ProductionOrder>lambdaQuery()
+                .eq(query.getId() != null, ProductionOrder::getId, query.getId())
+                .eq(query.getProductModelId() != null, ProductionOrder::getProductModelId, query.getProductModelId())
+                .eq(query.getTechnologyRoutingId() != null, ProductionOrder::getTechnologyRoutingId, query.getTechnologyRoutingId())
+                .like(query.getNpsNo() != null && !query.getNpsNo().trim().isEmpty(), ProductionOrder::getNpsNo, query.getNpsNo())
+                .orderByDesc(ProductionOrder::getId);
+    }
+
+    private String generateNextOrderNo() {
+        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        String prefix = "SC" + datePrefix;
+        ProductionOrder latestOrder = this.getOne(Wrappers.<ProductionOrder>lambdaQuery()
+                .likeRight(ProductionOrder::getNpsNo, prefix)
+                .orderByDesc(ProductionOrder::getNpsNo)
+                .last("limit 1"));
+        int sequence = 1;
+        if (latestOrder != null && latestOrder.getNpsNo() != null && latestOrder.getNpsNo().startsWith(prefix)) {
+            try {
+                sequence = Integer.parseInt(latestOrder.getNpsNo().substring(prefix.length())) + 1;
+            } catch (NumberFormatException ignored) {
+                sequence = 1;
+            }
+        }
+        return prefix + String.format("%04d", sequence);
+    }
+
+    private String generateNextTaskNo() {
+        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        String prefix = "GD" + datePrefix;
+        ProductionOperationTask lastTask = productionOperationTaskMapper.selectOne(
+                Wrappers.<ProductionOperationTask>lambdaQuery()
+                        .likeRight(ProductionOperationTask::getWorkOrderNo, prefix)
+                        .orderByDesc(ProductionOperationTask::getWorkOrderNo)
+                        .last("limit 1"));
+        int sequence = 1;
+        if (lastTask != null && lastTask.getWorkOrderNo() != null && lastTask.getWorkOrderNo().startsWith(prefix)) {
+            try {
+                sequence = Integer.parseInt(lastTask.getWorkOrderNo().substring(prefix.length())) + 1;
+            } catch (NumberFormatException ignored) {
+                sequence = 1;
+            }
+        }
+        return prefix + String.format("%03d", sequence);
+    }
+
+    private BigDecimal defaultDecimal(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value;
+    }
+
+    private void validateAndFillOrder(ProductionOrder productionOrder, ProductionOrder oldOrder) {
+        if (productionOrder == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶈兘涓虹┖");
+        }
+        fillFromProductionPlans(productionOrder);
+        if (productionOrder.getProductModelId() == null) {
+            throw new ServiceException("浜у搧瑙勬牸ID涓嶈兘涓虹┖");
+        }
+        if (defaultDecimal(productionOrder.getQuantity()).compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("涓嬪崟鏁伴噺蹇呴』澶т簬0");
+        }
+        if (productionOrder.getTechnologyRoutingId() == null) {
+            // 鏈樉寮忔寚瀹氬伐鑹鸿矾绾挎椂锛屾寜浜у搧瑙勬牸閫夋渶鏂颁竴鏉″伐鑹轰綔涓洪粯璁よ矾绾裤��
+            TechnologyRouting technologyRouting = technologyRoutingMapper.selectOne(
+                    Wrappers.<TechnologyRouting>lambdaQuery()
+                            .eq(TechnologyRouting::getProductModelId, productionOrder.getProductModelId())
+                            .orderByDesc(TechnologyRouting::getId)
+                            .last("limit 1"));
+            if (technologyRouting != null) {
+                productionOrder.setTechnologyRoutingId(technologyRouting.getId());
+            }
+        }
+        if (oldOrder != null && ProductOrderStatusEnum.isStarted(oldOrder.getStatus())) {
+            // 寮�宸ュ悗鍙厑璁镐慨姝i潪鏍稿績瀛楁锛屾牳蹇冪敓浜т緷鎹攣瀹氥��
+            if (!Objects.equals(oldOrder.getProductModelId(), productionOrder.getProductModelId())
+                    || !Objects.equals(oldOrder.getTechnologyRoutingId(), productionOrder.getTechnologyRoutingId())
+                    || compareDecimal(oldOrder.getQuantity(), productionOrder.getQuantity()) != 0) {
+                throw new ServiceException("鐢熶骇璁㈠崟宸插紑宸ワ紝涓嶈兘淇敼浜у搧銆佸伐鑹鸿矾绾挎垨鏁伴噺");
+            }
+        }
+    }
+
+    private void fillFromProductionPlans(ProductionOrder productionOrder) {
+        List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds());
+        if (planIds.isEmpty()) {
+            return;
+        }
+        // 澶氳鍒掑悎骞惰浆鍗曟椂锛屾墍鏈夎鍒掑繀椤诲睘浜庡悓涓�瑙勬牸锛屼笖鍙兘涓嬪彂涓�娆°��
+        List<ProductionPlan> productionPlans = productionPlanMapper.selectBatchIds(planIds);
+        if (productionPlans.size() != planIds.size()) {
+            throw new ServiceException("閮ㄥ垎鐢熶骇璁″垝涓嶅瓨鍦�");
+        }
+        Map<Long, ProductionPlan> planMap = productionPlans.stream()
+                .collect(Collectors.toMap(ProductionPlan::getId, item -> item, (left, right) -> left));
+        ProductionPlan mainPlan = planMap.get(planIds.get(0));
+        if (mainPlan == null) {
+            throw new ServiceException("涓荤敓浜ц鍒掍笉瀛樺湪");
+        }
+        Set<Long> productModelIds = productionPlans.stream()
+                .map(ProductionPlan::getProductModelId)
+                .collect(Collectors.toSet());
+        if (productModelIds.size() > 1) {
+            throw new ServiceException("鎵�閫夌敓浜ц鍒掑繀椤诲睘浜庡悓涓�浜у搧瑙勬牸");
+        }
+        if (productionPlans.stream().anyMatch(item -> item.getStatus() != null && item.getStatus() == 2)) {
+            throw new ServiceException("鎵�閫夌敓浜ц鍒掑凡涓嬪彂");
+        }
+        ProductionPlan firstPlan = mainPlan;
+        if (productionOrder.getProductModelId() == null) {
+            productionOrder.setProductModelId(firstPlan.getProductModelId());
+        } else if (!Objects.equals(productionOrder.getProductModelId(), firstPlan.getProductModelId())) {
+            throw new ServiceException("浜у搧瑙勬牸ID涓庣敓浜ц鍒掍笉涓�鑷�");
+        }
+        if (productionOrder.getQuantity() == null || productionOrder.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+            productionOrder.setQuantity(productionPlans.stream()
+                    .map(ProductionPlan::getQtyRequired)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add));
+        }
+        if (productionOrder.getPlanCompleteTime() == null) {
+            LocalDate planCompleteTime = productionPlans.stream()
+                    .map(this::resolvePlanCompleteDate)
+                    .filter(Objects::nonNull)
+                    .min(Comparator.naturalOrder())
+                    .orElse(null);
+            productionOrder.setPlanCompleteTime(planCompleteTime);
+        }
+        productionOrder.setProductionPlanIds(formatPlanIds(planIds));
+    }
+
+    private void releaseProductionPlanIssueStatus(ProductionOrder productionOrder) {
+        if (productionOrder == null) {
+            return;
+        }
+        List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds());
+        if (!planIds.isEmpty()) {
+            // 鐢熶骇璁㈠崟鍒犻櫎--瀵瑰簲鐨勭敓浜ц鍒掔殑宸蹭笅鍙戞暟閲忚鍑忓幓
+            updatePlanIssuedFlag(planIds, productionOrder.getQuantity());
+        }
+    }
+
+    //鐢熶骇璁㈠崟鍒犻櫎锛岀敓浜ц鍒掔殑宸蹭笅鍙戞暟閲忓搴斿彉鏇�
+    private void updatePlanIssuedFlag(List<Long> planIds, BigDecimal remainingAssignedQuantity) {
+        if (planIds == null || planIds.isEmpty()) {
+            return;
+        }
+        List<ProductionPlan> plans = productionPlanMapper.selectBatchIds(planIds);
+        //涓嬪彂鏁伴噺鍑忓幓
+        List<ProductionPlan> updates = new ArrayList<>();
+        for (ProductionPlan plan : plans) {
+            BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO);
+            if (requiredQuantity.compareTo(BigDecimal.ZERO) < 0) {
+                requiredQuantity = BigDecimal.ZERO;
+            }
+            BigDecimal remainingQuantity = resolveRemainingQuantity(plan);
+            BigDecimal historicalIssuedQuantity = requiredQuantity.subtract(remainingQuantity);
+            BigDecimal issuedQuantity = remainingAssignedQuantity.min(historicalIssuedQuantity);
+            remainingAssignedQuantity = remainingAssignedQuantity.subtract(issuedQuantity);
+            BigDecimal totalIssuedQuantity = historicalIssuedQuantity.subtract(issuedQuantity);
+            int planStatus = resolvePlanStatus(requiredQuantity, totalIssuedQuantity);
+            ProductionPlan update = new ProductionPlan();
+            update.setId(plan.getId());
+            update.setStatus(planStatus);
+            update.setQuantityIssued(totalIssuedQuantity);
+            updates.add(update);
+        }
+        if (!updates.isEmpty()) {
+            productionPlanMapper.updateById(updates);
+        }
+    }
+
+    private BigDecimal resolveRemainingQuantity(ProductionPlan plan) {
+        if (plan == null) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO);
+        if (requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal issuedQuantity = Optional.ofNullable(plan.getQuantityIssued()).orElse(BigDecimal.ZERO);
+        if (issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return requiredQuantity;
+        }
+        if (issuedQuantity.compareTo(requiredQuantity) >= 0) {
+            return BigDecimal.ZERO;
+        }
+        return requiredQuantity.subtract(issuedQuantity);
+    }
+
+    private int resolvePlanStatus(BigDecimal requiredQuantity, BigDecimal issuedQuantity) {
+        if (requiredQuantity == null || requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return 0;
+        }
+        if (issuedQuantity == null || issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return 0;
+        }
+        return issuedQuantity.compareTo(requiredQuantity) < 0 ? 1 : 2;
+    }
+
+    private List<Long> parsePlanIds(String productionPlanIds) {
+        if (productionPlanIds == null || productionPlanIds.trim().isEmpty()) {
+            return new ArrayList<>();
+        }
+        String normalized = productionPlanIds.replace("[", "").replace("]", "").trim();
+        if (normalized.isEmpty()) {
+            return new ArrayList<>();
+        }
+        return java.util.Arrays.stream(normalized.split(","))
+                .map(String::trim)
+                .filter(item -> !item.isEmpty())
+                .map(Long::valueOf)
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
+    private String formatPlanIds(List<Long> planIds) {
+        if (planIds == null || planIds.isEmpty()) {
+            return null;
+        }
+        return planIds.stream()
+                .distinct()
+                .map(String::valueOf)
+                .collect(Collectors.joining(",", "[", "]"));
+    }
+
+    private LocalDate resolvePlanCompleteDate(ProductionPlan productionPlan) {
+        if (productionPlan == null) {
+            return null;
+        }
+        if (productionPlan.getPromisedDeliveryDate() != null) {
+            return productionPlan.getPromisedDeliveryDate();
+        }
+        if (productionPlan.getRequiredDate() != null) {
+            return productionPlan.getRequiredDate();
+        }
+        return null;
+    }
+
+    private int compareDecimal(BigDecimal left, BigDecimal right) {
+        return defaultDecimal(left).compareTo(defaultDecimal(right));
+    }
+
+    private void fillProductImages(List<ProductionOrderVo> records) {
+        if (records == null || records.isEmpty()) {
+            return;
+        }
+        List<Long> productModelIds = records.stream()
+                .map(ProductionOrderVo::getProductModelId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (productModelIds.isEmpty()) {
+            return;
+        }
+
+        List<StorageAttachment> attachments = storageAttachmentMapper.selectList(
+                Wrappers.<StorageAttachment>lambdaQuery()
+                        .in(StorageAttachment::getRecordId, productModelIds)
+                        .eq(StorageAttachment::getApplication, StorageAttachmentConstants.StorageAttachmentImage)
+                        .eq(StorageAttachment::getDeleted, 0L)
+                        .orderByAsc(StorageAttachment::getId));
+        if (attachments == null || attachments.isEmpty()) {
+            return;
+        }
+
+        Map<Long, List<StorageAttachment>> attachmentMap = attachments.stream()
+                .collect(Collectors.groupingBy(StorageAttachment::getRecordId, java.util.LinkedHashMap::new, Collectors.toList()));
+        List<Long> blobIds = attachments.stream()
+                .map(StorageAttachment::getStorageBlobId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (blobIds.isEmpty()) {
+            return;
+        }
+
+        Map<Long, StorageBlob> blobMap = storageBlobMapper.selectBatchIds(blobIds).stream()
+                .filter(Objects::nonNull)
+                .collect(Collectors.toMap(StorageBlob::getId, item -> item));
+        for (ProductionOrderVo record : records) {
+            List<StorageAttachment> modelAttachments = attachmentMap.get(record.getProductModelId());
+            if (modelAttachments == null || modelAttachments.isEmpty()) {
+                continue;
+            }
+            List<StorageBlobVO> images = modelAttachments.stream()
+                    .map(StorageAttachment::getStorageBlobId)
+                    .map(blobMap::get)
+                    .filter(Objects::nonNull)
+                    .map(this::toStorageBlobVO)
+                    .collect(Collectors.toList());
+            if (!images.isEmpty()) {
+                record.setProductImages(images);
+            }
+        }
+    }
+
+    private StorageBlobVO toStorageBlobVO(StorageBlob blob) {
+        StorageBlobVO vo = BeanUtil.copyProperties(blob, StorageBlobVO.class);
+        vo.setPreviewURL(fileUtil.buildSignedPreviewUrl(vo));
+        vo.setDownloadURL(fileUtil.buildSignedDownloadUrl(vo));
+        return vo;
+    }
+
+    @Override
+    public ProductionOrderWorkOrderDetailVo getWorkOrderReportInspectDetail(ProductionOrderDto dto) {
+        Long productionOrderId = resolveProductionOrderId(dto);
+        ProductionOrderVo orderInfo = getProductionOrderInfo(productionOrderId);
+        if (orderInfo == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+
+        ProductionOrderWorkOrderDetailVo detailVo = new ProductionOrderWorkOrderDetailVo();
+        detailVo.setProductionOrder(orderInfo);
+
+        ProductionOperationTaskDto taskQuery = new ProductionOperationTaskDto();
+        taskQuery.setProductionOrderId(productionOrderId);
+        IPage<ProductionOperationTaskVo> workOrderPage = productionOperationTaskMapper.pageProductionOperationTask(
+                new Page<ProductionOperationTaskVo>(1, -1), taskQuery);
+        List<ProductionOperationTaskVo> workOrderList = workOrderPage == null || workOrderPage.getRecords() == null
+                ? Collections.emptyList()
+                : workOrderPage.getRecords().stream()
+                .filter(Objects::nonNull)
+                .sorted(Comparator.comparing(ProductionOperationTaskVo::getId, Comparator.nullsLast(Comparator.naturalOrder())))
+                .collect(Collectors.toList());
+        if (workOrderList == null || workOrderList.isEmpty()) {
+            detailVo.setWorkOrderList(Collections.emptyList());
+            return detailVo;
+        }
+
+        List<Long> workOrderIdList = workOrderList.stream()
+                .map(ProductionOperationTaskVo::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        List<ProductionProductMain> reportMainList = workOrderIdList.isEmpty()
+                ? Collections.emptyList()
+                : productionProductMainMapper.selectList(
+                Wrappers.<ProductionProductMain>lambdaQuery()
+                        .in(ProductionProductMain::getProductionOperationTaskId, workOrderIdList)
+                        .orderByAsc(ProductionProductMain::getId));
+        Map<Long, List<ProductionProductMain>> reportMainByWorkOrderMap = new LinkedHashMap<>();
+        for (ProductionProductMain reportMain : reportMainList) {
+            if (reportMain == null || reportMain.getProductionOperationTaskId() == null) {
+                continue;
+            }
+            reportMainByWorkOrderMap.computeIfAbsent(reportMain.getProductionOperationTaskId(), key -> new ArrayList<>()).add(reportMain);
+        }
+
+        List<Long> reportMainIdList = reportMainList.stream()
+                .map(ProductionProductMain::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        Map<Long, List<ProductionProductOutput>> reportOutputMap = new LinkedHashMap<>();
+        Map<Long, List<ProductionOrderRoutingOperationParam>> reportParamMap = new LinkedHashMap<>();
+        Map<Long, List<QualityInspect>> inspectMap = new LinkedHashMap<>();
+        Map<Long, List<QualityInspectParam>> inspectParamMap = new LinkedHashMap<>();
+        Map<Long, List<QualityInspectFile>> inspectFileMap = new LinkedHashMap<>();
+        if (!reportMainIdList.isEmpty()) {
+            List<ProductionProductOutput> reportOutputList = productionProductOutputMapper.selectList(
+                    Wrappers.<ProductionProductOutput>lambdaQuery()
+                            .in(ProductionProductOutput::getProductionProductMainId, reportMainIdList)
+                            .orderByAsc(ProductionProductOutput::getId));
+            for (ProductionProductOutput reportOutput : reportOutputList) {
+                if (reportOutput == null) {
+                    continue;
+                }
+                Long reportMainId = reportOutput.getProductionProductMainId() != null
+                        ? reportOutput.getProductionProductMainId()
+                        : reportOutput.getProductMainId();
+                if (reportMainId == null) {
+                    continue;
+                }
+                reportOutputMap.computeIfAbsent(reportMainId, k -> new ArrayList<>()).add(reportOutput);
+            }
+
+            List<ProductionOrderRoutingOperationParam> reportParamList = productionOrderRoutingOperationParamMapper.selectList(
+                    Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                            .in(ProductionOrderRoutingOperationParam::getProductionProductMainId, reportMainIdList)
+                            .orderByAsc(ProductionOrderRoutingOperationParam::getId));
+            for (ProductionOrderRoutingOperationParam reportParam : reportParamList) {
+                if (reportParam == null || reportParam.getProductionProductMainId() == null) {
+                    continue;
+                }
+                reportParamMap.computeIfAbsent(reportParam.getProductionProductMainId(), k -> new ArrayList<>()).add(reportParam);
+            }
+
+            List<QualityInspect> inspectList = qualityInspectMapper.selectList(
+                    Wrappers.<QualityInspect>lambdaQuery()
+                            .in(QualityInspect::getProductMainId, reportMainIdList)
+                            .orderByAsc(QualityInspect::getId));
+            for (QualityInspect inspect : inspectList) {
+                if (inspect == null || inspect.getProductMainId() == null) {
+                    continue;
+                }
+                inspectMap.computeIfAbsent(inspect.getProductMainId(), key -> new ArrayList<>()).add(inspect);
+            }
+
+            List<Long> inspectIdList = inspectList.stream()
+                    .map(QualityInspect::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+            if (!inspectIdList.isEmpty()) {
+                List<QualityInspectParam> inspectParamList = qualityInspectParamMapper.selectList(
+                        Wrappers.<QualityInspectParam>lambdaQuery()
+                                .in(QualityInspectParam::getInspectId, inspectIdList)
+                                .orderByAsc(QualityInspectParam::getId));
+                for (QualityInspectParam inspectParam : inspectParamList) {
+                    if (inspectParam == null || inspectParam.getInspectId() == null) {
+                        continue;
+                    }
+                    inspectParamMap.computeIfAbsent(inspectParam.getInspectId(), k -> new ArrayList<>()).add(inspectParam);
+                }
+
+                List<QualityInspectFile> inspectFileList = qualityInspectFileMapper.selectList(
+                        Wrappers.<QualityInspectFile>lambdaQuery()
+                                .in(QualityInspectFile::getInspectId, inspectIdList)
+                                .orderByAsc(QualityInspectFile::getId));
+                for (QualityInspectFile inspectFile : inspectFileList) {
+                    if (inspectFile == null || inspectFile.getInspectId() == null) {
+                        continue;
+                    }
+                    inspectFileMap.computeIfAbsent(inspectFile.getInspectId(), k -> new ArrayList<>()).add(inspectFile);
+                }
+            }
+        }
+
+        List<ProductionOrderWorkOrderDetailVo.WorkOrderDetail> workOrderDetailList = new ArrayList<>();
+        for (ProductionOperationTaskVo workOrder : workOrderList) {
+            ProductionOrderWorkOrderDetailVo.WorkOrderDetail workOrderDetail = new ProductionOrderWorkOrderDetailVo.WorkOrderDetail();
+            workOrderDetail.setWorkOrder(workOrder);
+
+            List<ProductionProductMain> workOrderReportMainList = reportMainByWorkOrderMap.getOrDefault(workOrder.getId(), Collections.emptyList());
+            if (workOrderReportMainList.isEmpty()) {
+                workOrderDetail.setReportList(Collections.emptyList());
+                workOrderDetail.setInspectList(Collections.emptyList());
+                workOrderDetailList.add(workOrderDetail);
+                continue;
+            }
+
+            List<ProductionOrderWorkOrderDetailVo.ReportDetail> reportDetailList = new ArrayList<>();
+            List<ProductionOrderWorkOrderDetailVo.InspectDetail> inspectDetailList = new ArrayList<>();
+            for (ProductionProductMain reportMain : workOrderReportMainList) {
+                Long reportMainId = reportMain.getId();
+
+                ProductionOrderWorkOrderDetailVo.ReportDetail reportDetail = new ProductionOrderWorkOrderDetailVo.ReportDetail();
+                reportDetail.setReportMain(reportMain);
+                reportDetail.setReportOutputList(reportOutputMap.getOrDefault(reportMainId, Collections.emptyList()));
+                reportDetail.setReportParamList(reportParamMap.getOrDefault(reportMainId, Collections.emptyList()));
+                reportDetailList.add(reportDetail);
+
+                List<QualityInspect> reportInspectList = inspectMap.getOrDefault(reportMainId, Collections.emptyList());
+                for (QualityInspect inspect : reportInspectList) {
+                    ProductionOrderWorkOrderDetailVo.InspectDetail inspectDetail = new ProductionOrderWorkOrderDetailVo.InspectDetail();
+                    inspectDetail.setReportId(reportMainId);
+                    inspectDetail.setReportNo(reportMain.getProductNo());
+                    inspectDetail.setReportMain(reportMain);
+                    inspectDetail.setInspect(inspect);
+                    inspectDetail.setInspectParamList(inspectParamMap.getOrDefault(inspect.getId(), Collections.emptyList()));
+                    inspectDetail.setInspectFileList(inspectFileMap.getOrDefault(inspect.getId(), Collections.emptyList()));
+                    inspectDetailList.add(inspectDetail);
+                }
+            }
+
+            workOrderDetail.setReportList(reportDetailList);
+            workOrderDetail.setInspectList(inspectDetailList);
+            workOrderDetailList.add(workOrderDetail);
+        }
+
+        detailVo.setWorkOrderList(workOrderDetailList);
+        return detailVo;
+    }
+
+    private Long resolveProductionOrderId(ProductionOrderDto dto) {
+        if (dto == null) {
+            throw new ServiceException("璇蜂紶鍏ョ敓浜ц鍗旾D鎴栫敓浜ц鍗曞彿");
+        }
+        if (dto.getId() != null) {
+            return dto.getId();
+        }
+        if (dto.getNpsNo() == null || dto.getNpsNo().trim().isEmpty()) {
+            throw new ServiceException("璇蜂紶鍏ョ敓浜ц鍗旾D鎴栫敓浜ц鍗曞彿");
+        }
+        ProductionOrder productionOrder = baseMapper.selectOne(
+                Wrappers.<ProductionOrder>lambdaQuery()
+                        .eq(ProductionOrder::getNpsNo, dto.getNpsNo().trim())
+                        .last("limit 1"));
+        if (productionOrder == null || productionOrder.getId() == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+        return productionOrder.getId();
+    }
+
+    @Override
+    public List<ProductionOrderPickVo> pick(Long productionOrderId) {
+        if (productionOrderId == null) {
+            return Collections.emptyList();
+        }
+
+        ProductionOrderBom orderBom = productionOrderBomMapper.selectOne(
+                Wrappers.<ProductionOrderBom>lambdaQuery()
+                        .eq(ProductionOrderBom::getProductionOrderId, productionOrderId)
+                        .orderByDesc(ProductionOrderBom::getId)
+                        .last("limit 1"));
+        if (orderBom == null || orderBom.getId() == null) {
+            return Collections.emptyList();
+        }
+
+        List<ProductionBomStructureVo> bomStructureList = productionBomStructureMapper.pickByBomId(orderBom.getId());
+        if (bomStructureList == null || bomStructureList.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<Long> productModelIds = bomStructureList.stream()
+                .map(ProductionBomStructureVo::getProductModelId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        Map<Long, BigDecimal> stockQuantityMap = new HashMap<>();
+        Map<Long, LinkedHashSet<String>> stockBatchNoMap = new HashMap<>();
+        if (!productModelIds.isEmpty()) {
+            List<StockInventory> stockList = stockInventoryMapper.selectList(
+                    Wrappers.<StockInventory>lambdaQuery()
+                            .in(StockInventory::getProductModelId, productModelIds));
+            for (StockInventory stockItem : stockList) {
+                if (stockItem == null || stockItem.getProductModelId() == null) {
+                    continue;
+                }
+                Long productModelId = stockItem.getProductModelId();
+                stockQuantityMap.merge(productModelId, defaultDecimal(stockItem.getQualitity()), BigDecimal::add);
+                String batchNo = stockItem.getBatchNo();
+                if (batchNo != null && !batchNo.trim().isEmpty()) {
+                    stockBatchNoMap.computeIfAbsent(productModelId, key -> new LinkedHashSet<>()).add(batchNo);
+                }
+            }
+        }
+
+        Map<String, ProductionOrderPickVo> mergedPickMap = new LinkedHashMap<>();
+        for (ProductionBomStructureVo structure : bomStructureList) {
+            if (structure == null || structure.getProductModelId() == null) {
+                continue;
+            }
+            Long productModelId = structure.getProductModelId();
+            String mergeKey = String.valueOf(structure.getTechnologyOperationId()) + "#" + productModelId;
+            ProductionOrderPickVo vo = mergedPickMap.get(mergeKey);
+            if (vo == null) {
+                vo = new ProductionOrderPickVo();
+                vo.setProductModelId(productModelId);
+                vo.setOperationName(structure.getOperationName());
+                vo.setTechnologyOperationId(structure.getTechnologyOperationId());
+                vo.setProductName(structure.getProductName());
+                vo.setModel(structure.getModel());
+                vo.setDemandedQuantity(BigDecimal.ZERO);
+                vo.setUnit(structure.getUnit());
+                List<String> batchNoList = stockBatchNoMap.get(productModelId) == null
+                        ? Collections.emptyList()
+                        : new ArrayList<>(stockBatchNoMap.get(productModelId));
+                vo.setBatchNoList(batchNoList);
+                vo.setStockQuantity(stockQuantityMap.getOrDefault(productModelId, BigDecimal.ZERO));
+                vo.setBom(true);
+                mergedPickMap.put(mergeKey, vo);
+            }
+            vo.setDemandedQuantity(defaultDecimal(vo.getDemandedQuantity()).add(defaultDecimal(structure.getDemandedQuantity())));
+        }
+        return new ArrayList<>(mergedPickMap.values());
+    }
+
+    @Override
+    public int updateOrder(ProductionOrderDto productionOrderDto) {
+        productionOrderDto.setStatus(5);
+        return baseMapper.updateById(productionOrderDto);
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java
new file mode 100644
index 0000000..b3ad742
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java
@@ -0,0 +1,350 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.production.bean.dto.ProductionPlanDto;
+import com.ruoyi.production.bean.dto.ProductionPlanImportDto;
+import com.ruoyi.production.bean.vo.ProductionPlanVo;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionPlanMapper;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionPlan;
+import com.ruoyi.production.service.ProductionOrderService;
+import com.ruoyi.production.service.ProductionPlanService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class ProductionPlanServiceImpl extends ServiceImpl<ProductionPlanMapper, ProductionPlan> implements ProductionPlanService {
+
+    private static final int PLAN_STATUS_WAIT = 0;
+    private static final int PLAN_STATUS_PARTIAL = 1;
+    private static final int PLAN_STATUS_ISSUED = 2;
+
+    private final ProductionPlanMapper productionPlanMapper;
+    private final ProductionOrderMapper productionOrderMapper;
+    private final ProductionOrderService productionOrderService;
+
+    @Override
+    public IPage<ProductionPlanVo> listPage(Page<ProductionPlanDto> page, ProductionPlanDto productionPlanDto) {
+        return productionPlanMapper.listPage(page, productionPlanDto);
+    }
+
+    /**
+     * 鍚堝苟鐢熶骇璁″垝骞朵笅鍙戠敓浜ц鍗曘��
+     * 涓氬姟绾︽潫锛�
+     * 1. 浠呭厑璁稿悓涓�浜у搧鍨嬪彿鐨勮鍒掑悎骞讹紱
+     * 2. 宸蹭笅鍙戞垨閮ㄥ垎涓嬪彂鐨勮鍒掔姝㈠啀娆″悎骞讹紱
+     * 3. 涓嬪彂鏁伴噺涓嶈兘澶т簬鎵�閫夎鍒掗渶姹傛�婚噺锛�
+     * 4. 璁㈠崟鍒涘缓缁熶竴澶嶇敤 ProductionOrderService.saveProductionOrder锛岀‘淇濆伐鑹�/BOM/棰嗘枡涓诲崟绛夊悗缁�昏緫涓�鑷淬��
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean combine(ProductionPlanDto productionPlanDto) {
+        if (productionPlanDto == null || productionPlanDto.getIds() == null || productionPlanDto.getIds().isEmpty()) {
+            return false;
+        }
+
+        List<Long> planIds = productionPlanDto.getIds().stream()
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (planIds.isEmpty()) {
+            throw new ServiceException("涓嬪彂澶辫触锛屾湭閫夋嫨鐢熶骇璁″垝");
+        }
+
+        List<ProductionPlanDto> planLists = productionPlanMapper.selectWithMaterialByIds(planIds);
+        if (planLists == null || planLists.isEmpty() || planLists.size() != planIds.size()) {
+            throw new ServiceException("涓嬪彂澶辫触锛岀敓浜ц鍒掍笉瀛樺湪鎴栧凡琚垹闄�");
+        }
+
+        ProductionPlanDto firstPlan = planLists.getFirst();
+        if (firstPlan.getProductModelId() == null) {
+            throw new ServiceException("涓嬪彂澶辫触锛岀敓浜ц鍒掔己灏戜骇鍝佸瀷鍙�");
+        }
+
+        boolean hasDifferentModel = planLists.stream()
+                .anyMatch(item -> !Objects.equals(item.getProductModelId(), firstPlan.getProductModelId()));
+        if (hasDifferentModel) {
+            throw new BaseException("鍚堝苟澶辫触锛屾墍閫夌敓浜ц鍒掔殑浜у搧鍨嬪彿涓嶄竴鑷�");
+        }
+
+        boolean hasIssuedPlan = planLists.stream()
+                .anyMatch(item -> item.getStatus() != null && item.getStatus() == PLAN_STATUS_ISSUED);
+        if (hasIssuedPlan) {
+            throw new BaseException("鍚堝苟澶辫触锛屾墍閫夌敓浜ц鍒掑瓨鍦ㄥ凡涓嬪彂鎴栭儴鍒嗕笅鍙戞暟鎹�");
+        }
+
+        BigDecimal totalRequiredQuantity = planLists.stream()
+                .map(this::resolveRemainingQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        if (totalRequiredQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("涓嬪彂澶辫触锛屾墍閫夌敓浜ц鍒掗渶姹傛�婚噺蹇呴』澶т簬0");
+        }
+
+        BigDecimal assignedQuantity = productionPlanDto.getTotalAssignedQuantity();
+        if (assignedQuantity == null || assignedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new ServiceException("涓嬪彂澶辫触锛屼笅鍙戞暟閲忓繀椤诲ぇ浜�0");
+        }
+        if (assignedQuantity.compareTo(totalRequiredQuantity) > 0) {
+            throw new ServiceException("涓嬪彂澶辫触锛屼笅鍙戞暟閲忎笉鑳藉ぇ浜庤鍒掗渶姹傛�婚噺");
+        }
+
+        BigDecimal remainingForOrderBind = assignedQuantity;
+        List<Long> issuedPlanIds = new ArrayList<>();
+        for (ProductionPlanDto plan : planLists) {
+            BigDecimal remainingQuantity = resolveRemainingQuantity(plan);
+            if (remainingForOrderBind.compareTo(BigDecimal.ZERO) <= 0 || remainingQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+                continue;
+            }
+            BigDecimal issueForThisPlan = remainingForOrderBind.min(remainingQuantity);
+            remainingForOrderBind = remainingForOrderBind.subtract(issueForThisPlan);
+            if (issueForThisPlan.compareTo(BigDecimal.ZERO) > 0) {
+                issuedPlanIds.add(plan.getId());
+            }
+        }
+        if (issuedPlanIds.isEmpty()) {
+            throw new ServiceException("Issue failed, no quantity available for dispatch");
+        }
+
+        ProductionOrder productionOrder = new ProductionOrder();
+        productionOrder.setProductionPlanIds(formatPlanIds(issuedPlanIds));
+        productionOrder.setProductModelId(firstPlan.getProductModelId());
+        productionOrder.setQuantity(assignedQuantity);
+        productionOrder.setPlanCompleteTime(productionPlanDto.getPlanCompleteTime());
+
+        boolean saved = productionOrderService.saveProductionOrder(productionOrder);
+        if (!saved) {
+            throw new ServiceException("涓嬪彂澶辫触锛岀敓浜ц鍗曚繚瀛樺け璐�");
+        }
+
+        //宸蹭笅鍙戞暟閲�
+        BigDecimal remainingAssignedQuantity = assignedQuantity;
+        List<ProductionPlan> updates = new ArrayList<>();
+        for (ProductionPlanDto plan : planLists) {
+            BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO);
+            if (requiredQuantity.compareTo(BigDecimal.ZERO) < 0) {
+                requiredQuantity = BigDecimal.ZERO;
+            }
+            BigDecimal remainingQuantity = resolveRemainingQuantity(plan);
+            BigDecimal historicalIssuedQuantity = requiredQuantity.subtract(remainingQuantity);
+            BigDecimal issuedQuantity = BigDecimal.ZERO;
+            if (remainingAssignedQuantity.compareTo(BigDecimal.ZERO) > 0 && remainingQuantity.compareTo(BigDecimal.ZERO) > 0) {
+                issuedQuantity = remainingAssignedQuantity.min(remainingQuantity);
+                remainingAssignedQuantity = remainingAssignedQuantity.subtract(issuedQuantity);
+            }
+
+            BigDecimal totalIssuedQuantity = historicalIssuedQuantity.add(issuedQuantity);
+            int planStatus = resolvePlanStatus(requiredQuantity, totalIssuedQuantity);
+            ProductionPlan update = new ProductionPlan();
+            update.setId(plan.getId());
+            update.setStatus(planStatus);
+            update.setQuantityIssued(totalIssuedQuantity);
+            updates.add(update);
+        }
+        if (!updates.isEmpty()) {
+            this.updateBatchById(updates);
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean add(ProductionPlanDto dto) {
+        if (StringUtils.isBlank(dto.getMpsNo())) {
+            dto.setMpsNo(generateNextPlanNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))));
+        }else checkMpsNoUnique(dto.getMpsNo(), null);
+        dto.setStatus(PLAN_STATUS_WAIT);
+        dto.setSource("鍐呴儴");
+        return productionPlanMapper.insert(dto) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean update(ProductionPlanDto dto) {
+        if (dto == null || dto.getId() == null) {
+            throw new ServiceException("缂栬緫澶辫触锛屾暟鎹笉鑳戒负绌�");
+        }
+
+        ProductionPlan old = getById(dto.getId());
+        if (old == null) {
+            throw new ServiceException("缂栬緫澶辫触锛岀敓浜ц鍒掍笉瀛樺湪");
+        }
+
+        if (old.getStatus() != PLAN_STATUS_WAIT) {
+            throw new BaseException("缂栬緫澶辫触锛岃鐢熶骇璁″垝宸蹭笅鍙戞垨閮ㄥ垎涓嬪彂锛岀姝㈢紪杈�");
+        }
+
+        if (StringUtils.isNotBlank(dto.getMpsNo()) && !dto.getMpsNo().equals(old.getMpsNo())) {
+            checkMpsNoUnique(dto.getMpsNo(), dto.getId());
+        }
+
+        return productionPlanMapper.updateById(dto) > 0;
+    }
+
+    private void checkMpsNoUnique(String mpsNo, Long excludeId) {
+        LambdaQueryWrapper<ProductionPlan> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(ProductionPlan::getMpsNo, mpsNo);
+        if (excludeId != null) {
+            wrapper.ne(ProductionPlan::getId, excludeId);
+        }
+        if (productionPlanMapper.selectCount(wrapper) > 0) {
+            throw new ServiceException("鐢熶骇璁″垝鍙� " + mpsNo + " 宸插瓨鍦�");
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean delete(List<Long> ids) {
+        if (productionPlanMapper.selectList(Wrappers.<ProductionPlan>lambdaQuery().in(ProductionPlan::getId, ids))
+                .stream()
+                .anyMatch(p -> p.getStatus() == PLAN_STATUS_PARTIAL || p.getStatus() == PLAN_STATUS_ISSUED)) {
+            throw new BaseException("鍒犻櫎澶辫触锛屽瓨鍦ㄥ凡涓嬪彂鎴栭儴鍒嗕笅鍙戠殑璁″垝");
+        }
+
+        if (productionOrderMapper.selectList(Wrappers.<ProductionOrder>lambdaQuery().in(ProductionOrder::getProductionPlanIds, ids))
+                .stream()
+                .anyMatch(p -> p.getId() != null)) {
+            throw new BaseException("鍒犻櫎澶辫触锛屽瓨鍦ㄥ叧鑱旂敓浜ц鍗�");
+        }
+
+        return productionPlanMapper.deleteBatchIds(ids) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void importProdData(MultipartFile file) {
+        if (file == null || file.isEmpty()) {
+            throw new ServiceException("瀵煎叆鏁版嵁涓嶈兘涓虹┖");
+        }
+        ExcelUtil<ProductionPlanImportDto> excelUtil = new ExcelUtil<>(ProductionPlanImportDto.class);
+        List<ProductionPlanImportDto> list;
+        try {
+            list = excelUtil.importExcel(file.getInputStream());
+        } catch (Exception e) {
+            throw new ServiceException("Excel瑙f瀽澶辫触");
+        }
+        if (list == null || list.isEmpty()) {
+            throw new ServiceException("Excel娌℃湁鏁版嵁");
+        }
+        Set<String> mpsNos = new HashSet<>();
+        for (int i = 0; i < list.size(); i++) {
+            ProductionPlanImportDto dto = list.get(i);
+            String mpsNo = dto.getMpsNo();
+            if (StringUtils.isEmpty(mpsNo)) {
+                generateNextPlanNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+            }
+            if (!mpsNos.add(mpsNo)) {
+                throw new ServiceException("瀵煎叆澶辫触锛欵xcel 涓瓨鍦ㄩ噸澶嶇殑鐢宠鍗曠紪鍙� " + mpsNo);
+            }
+        }
+        Long existApplyNoCount = baseMapper.selectCount(Wrappers.<ProductionPlan>lambdaQuery()
+                .in(ProductionPlan::getMpsNo, mpsNos));
+        if (existApplyNoCount > 0) {
+            List<String> existMpsNos = baseMapper.selectList(Wrappers.<ProductionPlan>lambdaQuery()
+                            .in(ProductionPlan::getMpsNo, mpsNos))
+                    .stream()
+                    .map(ProductionPlan::getMpsNo)
+                    .collect(Collectors.toList());
+            throw new ServiceException("瀵煎叆澶辫触锛岀敓浜ц鍒掑彿宸插瓨鍦�: " + String.join(", ", existMpsNos));
+        }
+        LocalDateTime now = LocalDateTime.now();
+        List<ProductionPlan> entityList = list.stream().map(dto -> {
+            ProductionPlan entity = new ProductionPlan();
+            BeanUtils.copyProperties(dto, entity);
+            entity.setStatus(PLAN_STATUS_WAIT);
+            entity.setSource("鍐呴儴");
+            entity.setCreateTime(now);
+            entity.setUpdateTime(now);
+            return entity;
+        }).collect(Collectors.toList());
+        this.saveBatch(entityList);
+    }
+
+    @Override
+    public void exportProdData(HttpServletResponse response, List<Long> ids) {
+        List<ProductionPlanDto> list = productionPlanMapper.selectWithMaterialByIds(ids);
+        List<ProductionPlanImportDto> exportList = new ArrayList<>();
+        for (ProductionPlanDto entity : list) {
+            ProductionPlanImportDto dto = new ProductionPlanImportDto();
+            BeanUtils.copyProperties(entity, dto);
+            exportList.add(dto);
+        }
+        ExcelUtil<ProductionPlanImportDto> util = new ExcelUtil<>(ProductionPlanImportDto.class);
+        util.exportExcel(response, exportList, "涓荤敓浜ц鍒�");
+    }
+
+    private BigDecimal resolveRemainingQuantity(ProductionPlan plan) {
+        if (plan == null) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO);
+        if (requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal issuedQuantity = Optional.ofNullable(plan.getQuantityIssued()).orElse(BigDecimal.ZERO);
+        if (issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return requiredQuantity;
+        }
+        if (issuedQuantity.compareTo(requiredQuantity) >= 0) {
+            return BigDecimal.ZERO;
+        }
+        return requiredQuantity.subtract(issuedQuantity);
+    }
+
+    private int resolvePlanStatus(BigDecimal requiredQuantity, BigDecimal issuedQuantity) {
+        if (requiredQuantity == null || requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return PLAN_STATUS_WAIT;
+        }
+        if (issuedQuantity == null || issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
+            return PLAN_STATUS_WAIT;
+        }
+        return issuedQuantity.compareTo(requiredQuantity) < 0 ? PLAN_STATUS_PARTIAL : PLAN_STATUS_ISSUED;
+    }
+
+    private String formatPlanIds(List<Long> planIds) {
+        return planIds.stream()
+                .filter(Objects::nonNull)
+                .distinct()
+                .map(String::valueOf)
+                .collect(Collectors.joining(",", "[", "]"));
+    }
+
+    private String generateNextPlanNo(String datePrefix) {
+        QueryWrapper<ProductionPlan> queryWrapper = new QueryWrapper<>();
+        queryWrapper.likeRight("mps_no", "JH" + datePrefix);
+        queryWrapper.orderByDesc("mps_no");
+        queryWrapper.last("LIMIT 1");
+        ProductionPlan latestPlan = productionPlanMapper.selectOne(queryWrapper);
+        int sequence = 1;
+        if (latestPlan != null && latestPlan.getMpsNo() != null && !latestPlan.getMpsNo().isEmpty()) {
+            String sequenceStr = latestPlan.getMpsNo().substring(("JH" + datePrefix).length());
+            try {
+                sequence = Integer.parseInt(sequenceStr) + 1;
+            } catch (NumberFormatException e) {
+                sequence = 1;
+            }
+        }
+        return "JH" + datePrefix + String.format("%04d", sequence);
+    }
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java
index 49765c0..38e0baf 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java
@@ -3,19 +3,17 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.production.dto.ProductionProductInputDto;
+import com.ruoyi.production.bean.dto.ProductionProductInputDto;
 import com.ruoyi.production.mapper.ProductionProductInputMapper;
 import com.ruoyi.production.pojo.ProductionProductInput;
 import com.ruoyi.production.service.ProductionProductInputService;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 public class ProductionProductInputServiceImpl extends ServiceImpl<ProductionProductInputMapper, ProductionProductInput> implements ProductionProductInputService {
-    @Autowired
-    private ProductionProductInputMapper productionProductInputMapper;
+    private final ProductionProductInputMapper productionProductInputMapper;
 
     @Override
     public IPage<ProductionProductInputDto> listPageProductionProductInputDto(Page page, ProductionProductInputDto productionProductInputDto) {
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index fa34114..150fc89 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -12,13 +12,14 @@
 import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.dto.ProductStructureDto;
-import com.ruoyi.production.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.dto.ProductStructureDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.enums.ProductOrderStatusEnum;
 import com.ruoyi.production.mapper.*;
 import com.ruoyi.production.pojo.*;
 import com.ruoyi.production.service.ProductionProductMainService;
@@ -26,19 +27,29 @@
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.quality.mapper.*;
 import com.ruoyi.quality.pojo.*;
-import com.ruoyi.quality.service.IQualityInspectService;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.service.StockInventoryService;
+import com.ruoyi.technology.mapper.TechnologyOperationMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
+import com.ruoyi.technology.pojo.TechnologyOperation;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import com.ruoyi.production.mapper.ProductionProductMainMapper;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 @Service
@@ -46,140 +57,258 @@
 @Transactional(rollbackFor = Exception.class)
 public class ProductionProductMainServiceImpl extends ServiceImpl<ProductionProductMainMapper, ProductionProductMain> implements ProductionProductMainService {
 
-    private IQualityInspectService qualityInspectService;
-    private ProductionProductMainMapper productionProductMainMapper;
-
-
-    private ProductWorkOrderMapper productWorkOrderMapper;
-
-    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
-    private SysUserMapper userMapper;
-
-    private ProductionProductOutputMapper productionProductOutputMapper;
-
-
-    private ProductModelMapper productModelMapper;
-
-    private QualityInspectMapper qualityInspectMapper;
-    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
-
-    private ProductProcessMapper productProcessMapper;
-    private ProductProcessRouteMapper productProcessRouteMapper;
-
-    private ProductMapper productMapper;
-
-
-    private QualityTestStandardParamMapper qualityTestStandardParamMapper;
-    private QualityTestStandardMapper qualityTestStandardMapper;
-
-    private QualityInspectParamMapper qualityInspectParamMapper;
-
-    private ProductStructureMapper productStructureMapper;
-
-    private ProductionProductInputMapper productionProductInputMapper;
-
-    private ProductOrderMapper productOrderMapper;
-
-    private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-
-    private StockUtils stockUtils;
-
+    private final ProductionProductMainMapper productionProductMainMapper;
+    private final SysUserMapper userMapper;
+    private final ProductionProductOutputMapper productionProductOutputMapper;
+    private final ProductModelMapper productModelMapper;
+    private final QualityInspectMapper qualityInspectMapper;
+    private final QualityUnqualifiedMapper qualityUnqualifiedMapper;
+    private final ProductMapper productMapper;
+    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
+    private final QualityTestStandardMapper qualityTestStandardMapper;
+    private final QualityInspectParamMapper qualityInspectParamMapper;
+    private final ProductionProductInputMapper productionProductInputMapper;
+    private final ProductionAccountMapper productionAccountMapper;
+    private final ProductionOperationTaskMapper productionOperationTaskMapper;
+    private final ProductionOrderMapper productionOrderMapper;
+    private final ProductionOrderBomMapper productionOrderBomMapper;
+    private final ProductionBomStructureMapper productionBomStructureMapper;
+    private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
+    private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper;
+    private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+    private final TechnologyOperationMapper technologyOperationMapper;
+    private final StockUtils stockUtils;
+    private final StockInventoryService stockInventoryService;
 
     @Override
     public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) {
-        return productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
+        IPage<ProductionProductMainDto> result = productionProductMainMapper.listPageProductionProductMainDto(page, productionProductMainDto);
+        fillOperationParamList(result.getRecords());
+        return result;
+    }
+
+    @Override
+    public IPage<ProductionProductMainDto> pageProductionProductMain(Page page, ProductionProductMainDto productionProductMainDto) {
+        return listPageProductionProductMainDto(page, productionProductMainDto);
+    }
+
+    @Override
+    public ProductionProductMainDto getProductionProductMainInfo(Long id) {
+        return listPageProductionProductMainDto(new Page<>(1, 1), new ProductionProductMainDto() {{
+            setId(id);
+        }}).getRecords().stream().findFirst().orElse(null);
+    }
+
+    private void fillOperationParamList(List<ProductionProductMainDto> recordList) {
+        if (recordList == null || recordList.isEmpty()) {
+            return;
+        }
+        Set<Long> mainIdSet = recordList.stream()
+                .map(ProductionProductMainDto::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (mainIdSet.isEmpty()) {
+            recordList.forEach(item -> item.setProductionOperationParamList(Collections.emptyList()));
+            return;
+        }
+
+        List<ProductionOrderRoutingOperationParam> paramList = productionOrderRoutingOperationParamMapper.selectList(
+                Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                        .in(ProductionOrderRoutingOperationParam::getProductionProductMainId, mainIdSet)
+                        .orderByAsc(ProductionOrderRoutingOperationParam::getId));
+        Map<Long, List<ProductionOrderRoutingOperationParam>> paramGroupMap = new HashMap<>();
+        for (ProductionOrderRoutingOperationParam param : paramList) {
+            if (param == null || param.getProductionProductMainId() == null) {
+                continue;
+            }
+            paramGroupMap.computeIfAbsent(param.getProductionProductMainId(), key -> new ArrayList<>()).add(param);
+        }
+
+        Set<Long> missingMainIdSet = new LinkedHashSet<>();
+        for (ProductionProductMainDto item : recordList) {
+            Long mainId = item.getId();
+            if (mainId == null) {
+                item.setProductionOperationParamList(Collections.emptyList());
+                continue;
+            }
+            List<ProductionOrderRoutingOperationParam> params = paramGroupMap.get(mainId);
+            if (params != null && !params.isEmpty()) {
+                item.setProductionOperationParamList(params);
+                continue;
+            }
+            missingMainIdSet.add(mainId);
+        }
+        if (missingMainIdSet.isEmpty()) {
+            return;
+        }
+
+        // 鍏煎鍘嗗彶鏁版嵁锛氭棫鎶ュ伐璁板綍娌℃湁鎸夋姤宸D钀藉弬鏁板揩鐓ф椂锛屽洖閫�灞曠ず宸ュ簭妯℃澘鍙傛暟銆�
+        List<ProductionProductMain> mainList = productionProductMainMapper.selectBatchIds(missingMainIdSet);
+        Map<Long, Long> mainIdToTaskIdMap = mainList.stream()
+                .filter(Objects::nonNull)
+                .filter(item -> item.getId() != null)
+                .collect(Collectors.toMap(ProductionProductMain::getId,
+                        ProductionProductMain::getProductionOperationTaskId, (left, right) -> left));
+        Set<Long> taskIdSet = mainIdToTaskIdMap.values().stream()
+                .filter(Objects::nonNull)
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (taskIdSet.isEmpty()) {
+            for (ProductionProductMainDto item : recordList) {
+                if (item.getId() != null && missingMainIdSet.contains(item.getId())) {
+                    item.setProductionOperationParamList(Collections.emptyList());
+                }
+            }
+            return;
+        }
+
+        List<ProductionOperationTask> taskList = productionOperationTaskMapper.selectList(
+                Wrappers.<ProductionOperationTask>lambdaQuery()
+                        .in(ProductionOperationTask::getId, taskIdSet));
+        Map<Long, Long> taskIdToRoutingOperationIdMap = taskList.stream()
+                .filter(Objects::nonNull)
+                .filter(item -> item.getId() != null)
+                .collect(Collectors.toMap(ProductionOperationTask::getId,
+                        ProductionOperationTask::getProductionOrderRoutingOperationId, (left, right) -> left));
+        Set<Long> routingOperationIdSet = taskIdToRoutingOperationIdMap.values().stream()
+                .filter(Objects::nonNull)
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (routingOperationIdSet.isEmpty()) {
+            for (ProductionProductMainDto item : recordList) {
+                if (item.getId() != null && missingMainIdSet.contains(item.getId())) {
+                    item.setProductionOperationParamList(Collections.emptyList());
+                }
+            }
+            return;
+        }
+
+        List<ProductionOrderRoutingOperationParam> fallbackParamList = productionOrderRoutingOperationParamMapper.selectList(
+                Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                        .in(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, routingOperationIdSet)
+                        .isNull(ProductionOrderRoutingOperationParam::getProductionProductMainId)
+                        .orderByAsc(ProductionOrderRoutingOperationParam::getId));
+        Map<Long, List<ProductionOrderRoutingOperationParam>> fallbackGroupMap = new HashMap<>();
+        for (ProductionOrderRoutingOperationParam param : fallbackParamList) {
+            if (param == null || param.getProductionOrderRoutingOperationId() == null) {
+                continue;
+            }
+            fallbackGroupMap.computeIfAbsent(param.getProductionOrderRoutingOperationId(), key -> new ArrayList<>()).add(param);
+        }
+
+        for (ProductionProductMainDto item : recordList) {
+            Long mainId = item.getId();
+            if (mainId == null || !missingMainIdSet.contains(mainId)) {
+                continue;
+            }
+            Long taskId = mainIdToTaskIdMap.get(mainId);
+            Long routingOperationId = taskId == null ? null : taskIdToRoutingOperationIdMap.get(taskId);
+            if (routingOperationId == null) {
+                item.setProductionOperationParamList(Collections.emptyList());
+                continue;
+            }
+            item.setProductionOperationParamList(fallbackGroupMap.getOrDefault(routingOperationId, Collections.emptyList()));
+        }
     }
 
     @Override
     public Boolean addProductMain(ProductionProductMainDto dto) {
+        Long taskId = resolveTaskId(dto);
+        if (taskId == null) {
+            throw new ServiceException("璇蜂紶鍏ョ敓浜у伐鍗旾D");
+        }
+        return addProductMainByProductionTask(dto);
+    }
+
+    @Override
+    public Boolean saveProductionProductMain(ProductionProductMainDto productionProductMainDto) {
+        return addProductMain(productionProductMainDto);
+    }
+
+    @Override
+    public Boolean removeProductMain(Long id) {
+        ProductionProductMain currentMain = productionProductMainMapper.selectById(id);
+        if (currentMain == null) {
+            return true;
+        }
+        return removeProductMainByProductionTask(currentMain);
+    }
+
+    private Boolean addProductMainByProductionTask(ProductionProductMainDto dto) {
+        // 鎶ュ伐浠ヨ鍗曞伐搴忓揩鐓т负鍑嗭紝閬垮厤宸ヨ壓涓绘暟鎹彉鏇村悗褰卞搷鍘嗗彶宸ュ崟鎵ц銆�
+        Long taskId = resolveTaskId(dto);
+        if (taskId == null) {
+            throw new ServiceException("productionOperationTaskId can not be null");
+        }
         SysUser user = userMapper.selectUserById(dto.getUserId());
+        ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(taskId);
+        if (productionOperationTask == null) {
+            throw new ServiceException("鐢熶骇宸ュ崟涓嶅瓨鍦�");
+        }
+        ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId());
+        if (routingOperation == null) {
+            throw new ServiceException("璁㈠崟宸ヨ壓璺嚎宸ュ簭涓嶅瓨鍦�");
+        }
+        ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId());
+        if (productionOrder == null) {
+            throw new ServiceException("鐢熶骇璁㈠崟涓嶅瓨鍦�");
+        }
+        TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId());
+        TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null
+                : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId());
+        ProductModel productModel = productModelMapper.selectById(
+                routingOperation.getProductModelId() != null ? routingOperation.getProductModelId() : productionOrder.getProductModelId());
+        if (productModel == null) {
+            throw new ServiceException("浜у搧瑙勬牸涓嶅瓨鍦�");
+        }
+
         ProductionProductMain productionProductMain = new ProductionProductMain();
-        //褰撳墠宸ヨ壓璺嚎瀵瑰簲鐨勫伐搴忚鎯�
-        ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(dto.getProductProcessRouteItemId());
-        if (productProcessRouteItem == null) {
-            throw new RuntimeException("宸ヨ壓璺嚎椤逛笉瀛樺湪");
-        }
-        //褰撳墠鍏蜂綋宸ュ簭
-        ProductProcess productProcess = productProcessMapper.selectById(productProcessRouteItem.getProcessId());
-        //宸ヨ壓璺嚎涓綋鍓嶅伐搴忓搴旂殑浜у嚭瑙勬牸鍨嬪彿
-        ProductModel productModel = productModelMapper.selectById(productProcessRouteItem.getProductModelId());
-        //鏌ヨ璇ョ敓浜ц鍗曞搴旂殑bom
-        ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectById(productProcessRouteItem.getProductRouteId());
-        /*鏂板鎶ュ伐涓昏〃*/
-        //鏌ヨ鏈�澶ф姤宸ョ紪鍙�
-        String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
-        QueryWrapper<ProductionProductMain> queryWrapper = new QueryWrapper<>();
-        queryWrapper.select("MAX(product_no) as maxNo")
-                .likeRight("product_no", datePrefix);
-        List<Map<String, Object>> resultList = productionProductMainMapper.selectMaps(queryWrapper);
-        int sequenceNumber = 1;
-        if (resultList != null && !resultList.isEmpty()) {
-            Map<String, Object> result = resultList.get(0);
-            if (result != null) {
-                Object maxNoObj = result.get("maxNo");
-                if (maxNoObj != null) {
-                    String lastNo = maxNoObj.toString();
-                    System.out.println("lastNo: " + lastNo);
-                    if (lastNo.startsWith(datePrefix)) {
-                        try {
-                            String seqStr = lastNo.substring(datePrefix.length());
-                            sequenceNumber = Integer.parseInt(seqStr) + 1;
-                        } catch (NumberFormatException e) {
-                            sequenceNumber = 1;
-                        }
-                    }
-                }
-            }
-        }
-        String productNo = String.format("%s%03d", datePrefix, sequenceNumber);
-        productionProductMain.setProductNo(productNo);
-        productionProductMain.setUserId(dto.getUserId());
-        productionProductMain.setUserName(dto.getUserName());
-        productionProductMain.setProductProcessRouteItemId(dto.getProductProcessRouteItemId());
-        productionProductMain.setWorkOrderId(dto.getWorkOrderId());
+        productionProductMain.setProductNo(generateProductNo());
+        productionProductMain.setUserId(user == null ? dto.getUserId() : user.getUserId());
+        productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName());
+        productionProductMain.setProductionOperationTaskId(taskId);
         productionProductMain.setStatus(0);
         productionProductMainMapper.insert(productionProductMain);
-        /*鏂板鎶ュ伐鎶曞叆琛�*/
-        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId());
-        if (productStructureDtos.size() == 0) {
-            //濡傛灉璇ュ伐搴忔病鏈変骇鍝佺粨鏋勭殑鎶曞叆鍝�,閭h繖涓姇鍏ュ搧鍜屼骇鍑哄搧鏄悓涓�涓�
-            ProductStructureDto productStructureDto = new ProductStructureDto();
-            productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId());
-            productStructureDto.setUnitQuantity(BigDecimal.ONE);
-            productStructureDtos.add(productStructureDto);
-        }
-        for (ProductStructureDto productStructureDto : productStructureDtos) {
+        syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId());
 
+        List<ProductStructureDto> productStructureDtos = resolveInputStructures(
+                productionOrder.getId(), routingOperation, productModel.getId());
+       // 濡傛灉娌℃湁bom瀛愯妭鐐逛簡锛岄偅涔堟姇鍏ュ氨鏄粬鏈韩
+        if (productStructureDtos.isEmpty()) {
+            ProductStructureDto fallbackInput = new ProductStructureDto();
+            fallbackInput.setProductModelId(productModel.getId());
+            fallbackInput.setUnitQuantity(BigDecimal.ONE);
+            productStructureDtos.add(fallbackInput);
+        }
+        for (ProductStructureDto item : productStructureDtos) {
+            // 褰撳墠瀹炵幇鎸夊伐搴忔垚鍝佺洿鎺ヤ綔涓烘姇鍏ワ紝鍚庣画鑻ユ帴鍏ラ鏂欒褰曞彲鍦ㄨ繖閲屾浛鎹㈡潵婧愩��
             ProductionProductInput productionProductInput = new ProductionProductInput();
-            productionProductInput.setProductModelId(productStructureDto.getProductModelId());
-            productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
+            productionProductInput.setProductionProductMainId(productionProductMain.getId());
             productionProductInput.setProductMainId(productionProductMain.getId());
+            productionProductInput.setProductModelId(item.getProductModelId());
+            productionProductInput.setInputQuantity(item.getUnitQuantity().multiply(defaultDecimal(dto.getQuantity())));
+            productionProductInput.setQuantity(productionProductInput.getInputQuantity());
             productionProductInputMapper.insert(productionProductInput);
-            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
-
         }
-        /*鏂板鎶ュ伐浜у嚭琛�*/
+
         ProductionProductOutput productionProductOutput = new ProductionProductOutput();
+        productionProductOutput.setProductionProductMainId(productionProductMain.getId());
         productionProductOutput.setProductMainId(productionProductMain.getId());
-        productionProductOutput.setProductModelId(productProcessRouteItem.getProductModelId());
-        productionProductOutput.setQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO);
-        productionProductOutput.setScrapQty(dto.getScrapQty() != null ? dto.getScrapQty() : BigDecimal.ZERO);
+        productionProductOutput.setProductModelId(productModel.getId());
+        productionProductOutput.setQuantity(defaultDecimal(dto.getQuantity()));
+        productionProductOutput.setScrapQty(defaultDecimal(dto.getScrapQty()));
         productionProductOutputMapper.insert(productionProductOutput);
-        //鍚堟牸鏁伴噺=鎶ュ伐鏁伴噺-鎶ュ簾鏁伴噺
-        BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty());
-        //鍙湁鍚堟牸鏁伴噺>0鎵嶈兘澧炲姞鐩稿簲鏁版嵁
+        BigDecimal reportQty = defaultDecimal(productionProductOutput.getQuantity());
+        BigDecimal productQty = reportQty;
+
+        List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList(
+                Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
+                        .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId())
+                        .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId()));
+        boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size());
         if (productQty.compareTo(BigDecimal.ZERO) > 0) {
-            /*鏂板璐ㄦ*/
-            List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
-            if (productProcessRouteItem.getIsQuality()) {
-                //瀵瑰簲鐨勮繃绋嬫鎴栬�呭嚭鍘傛
-                int inspectType = 1;
-                String process = productProcess.getName();//宸ュ簭
-                if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
-                    //鏈�鍚庝竴閬撳伐搴忕敓鎴愬嚭鍘傛
-                    inspectType = 2;
-                    process = null;
-                }
+            if (Boolean.TRUE.equals(routingOperation.getIsQuality())) {
+                // 璐ㄦ宸ュ簭鍏堢敓鎴愭楠屽崟锛岄潪璐ㄦ宸ュ簭鐩存帴鍏ュ悎鏍煎搧搴撳瓨銆�
+                int inspectType = isLastOperation ? 2 : 1;
+                String process = isLastOperation ? null : technologyOperation == null ? null : technologyOperation.getName();
                 Product product = productMapper.selectById(productModel.getProductId());
                 QualityInspect qualityInspect = new QualityInspect();
                 qualityInspect.setProductId(product.getId());
@@ -194,11 +323,11 @@
                 qualityInspect.setProductModelId(productModel.getId());
                 qualityInspectMapper.insert(qualityInspect);
                 List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
-                if (qualityTestStandard.size() > 0) {
+                if (!qualityTestStandard.isEmpty()) {
                     qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
                     qualityInspectMapper.updateById(qualityInspect);
                     qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
-                                    .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))//榛樿鑾峰彇鏈�鏂扮殑
+                                    .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))
                             .forEach(qualityTestStandardParam -> {
                                 QualityInspectParam param = new QualityInspectParam();
                                 BeanUtils.copyProperties(qualityTestStandardParam, param);
@@ -207,140 +336,302 @@
                                 qualityInspectParamMapper.insert(param);
                             });
                 }
-            }else {
-                //鐩存帴鍏ュ簱
-                stockUtils.addStock(productProcessRouteItem.getProductModelId(), productQty, StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
+            } else {
+                StockInventoryDto stockInventoryDto = new StockInventoryDto();
+                stockInventoryDto.setRecordId(productionProductMain.getId());
+                stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode()));
+                stockInventoryDto.setQualitity(productQty);
+                stockInventoryDto.setProductModelId(productModel.getId());
+                stockInventoryService.addStockInRecordOnly(stockInventoryDto);
             }
-            /*鏇存柊宸ュ崟鍜岀敓浜ц鍗�*/
-            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
-            productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty));
-            if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) {
-                productWorkOrder.setActualStartTime(LocalDate.now());//瀹為檯寮�濮嬫椂闂�
+
+            productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).add(productQty));
+            if (ObjectUtils.isNull(productionOperationTask.getActualStartTime())) {
+                productionOperationTask.setActualStartTime(LocalDate.now());
             }
-            if (productWorkOrder.getCompleteQuantity().compareTo(productWorkOrder.getPlanQuantity()) == 0) {
-                productWorkOrder.setActualEndTime(LocalDate.now());//瀹為檯缁撴潫鏃堕棿
+            // 鎶ュ伐椹卞姩宸ュ崟鐘舵�佹祦杞細鏈変骇鍑哄嵆杩涜涓紝杈惧埌璁″垝閲忓嵆瀹屽伐銆�
+            productionOperationTask.setStatus(3);
+            if (productionOperationTask.getPlanQuantity() != null
+                    && productionOperationTask.getCompleteQuantity().compareTo(productionOperationTask.getPlanQuantity()) >= 0) {
+                productionOperationTask.setActualEndTime(LocalDate.now());
+                productionOperationTask.setStatus(4);
             }
-            productWorkOrderMapper.updateById(productWorkOrder);
-            //鐢熶骇璁㈠崟
-            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
-            if (ObjectUtils.isNull(productOrder.getStartTime())) {
-                productOrder.setStartTime(LocalDateTime.now());//寮�濮嬫椂闂�
+            productionOperationTaskMapper.updateById(productionOperationTask);
+
+            if (ObjectUtils.isNull(productionOrder.getStartTime())) {
+                productionOrder.setStartTime(LocalDateTime.now());
             }
-            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
-                //濡傛灉鏄渶鍚庝竴閬撳伐搴忔姤宸ヤ箣鍚庣敓浜ц鍗曞畬鎴愭暟閲�+
-                productOrder.setCompleteQuantity(productOrder.getCompleteQuantity().add(productQty));
-                if (productOrder.getCompleteQuantity().compareTo(productOrder.getQuantity()) == 0) {
-                    productOrder.setEndTime(LocalDateTime.now());//缁撴潫鏃堕棿
+            // 璁㈠崟鐘舵�佺敱鏈�鍚庝竴閬撳伐搴忕殑鍚堟牸浜у嚭鎺ㄥ姩锛岄伩鍏嶄腑闂村伐搴忔彁鍓嶅畬宸ャ��
+            productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode());
+            if (isLastOperation) {
+                productionOrder.setCompleteQuantity(defaultDecimal(productionOrder.getCompleteQuantity()).add(productQty));
+                if (productionOrder.getQuantity() != null
+                        && productionOrder.getCompleteQuantity().compareTo(productionOrder.getQuantity()) >= 0) {
+                    productionOrder.setEndTime(LocalDateTime.now());
+                    productionOrder.setStatus(ProductOrderStatusEnum.FINISHED.getCode());
                 }
             }
-            productOrderMapper.updateById(productOrder);
-            /*娣诲姞鐢熶骇鏍哥畻        鍖哄垎宸ュ簭鏄浠惰繕鏄鏃�*/
-            BigDecimal workHours = (productProcess.getType() == 1)
-                    ? productProcess.getSalaryQuota().multiply(productQty)
-                    : productProcess.getSalaryQuota();
+            productionOrderMapper.updateById(productionOrder);
 
-            SalesLedgerProductionAccounting salesLedgerProductionAccounting = SalesLedgerProductionAccounting.builder()
-                    .productMainId(productionProductMain.getId())
-                    .schedulingUserId(user.getUserId())
-                    .schedulingUserName(user.getNickName())
-                    .finishedNum(productQty)
-                    .workHours(workHours)
-                    .process(productProcess.getName())
-                    .schedulingDate(LocalDate.now())
-                    .tenantId(dto.getTenantId())
-                    .build();
-            salesLedgerProductionAccountingMapper.insert(salesLedgerProductionAccounting);
-        }
-        //濡傛灉鎶ュ簾鏁伴噺>0,闇�瑕佽繘鍏ユ姤搴熺殑搴撳瓨
-        if (ObjectUtils.isNotEmpty(dto.getScrapQty())) {
-            if (dto.getScrapQty().compareTo(BigDecimal.ZERO) > 0) {
-                stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId());
+            BigDecimal workHours = BigDecimal.ZERO;
+            if (technologyOperation != null && technologyOperation.getSalaryQuota() != null) {
+                workHours = Integer.valueOf(1).equals(technologyOperation.getType())
+                        ? technologyOperation.getSalaryQuota().multiply(productQty)
+                        : technologyOperation.getSalaryQuota();
             }
+            ProductionAccount productionAccount = new ProductionAccount();
+            productionAccount.setProductionProductMainId(productionProductMain.getId());
+//            productionAccount.setSalesLedgerId(productionOrder.getSalesLedgerId());
+//            productionAccount.setSalesLedgerProductId(productionOrder.getSalesLedgerProductId() == null ? null : productionOrder.getSalesLedgerProductId().longValue());
+            productionAccount.setSchedulingUserId(user == null ? null : user.getUserId());
+            productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName());
+            productionAccount.setFinishedNum(productQty);
+            productionAccount.setWorkHours(workHours);
+            productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName());
+            productionAccount.setSchedulingDate(LocalDateTime.now());
+            productionAccountMapper.insert(productionAccount);
         }
+//        if (defaultDecimal(dto.getScrapQty()).compareTo(BigDecimal.ZERO) > 0) {
+//            stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(),
+//                    StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId());
+//        }
         return true;
     }
 
-    @Override
-    public Boolean removeProductMain(Long id) {
-        //鍒ゆ柇璇ユ潯鎶ュ伐鏄惁涓嶅悎鏍煎鐞�,濡傛灉涓嶅悎鏍煎鐞嗕簡锛屽垯涓嶅厑璁稿垹闄�
-        List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(Wrappers.<QualityInspect>lambdaQuery().eq(QualityInspect::getProductMainId, id));
-        if (qualityInspects.size() > 0){
-            List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.selectList(Wrappers.<QualityUnqualified>lambdaQuery()
-                    .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList())));
-            if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState()==1) {
+    private void syncOperationParamInputValue(ProductionProductMainDto dto,
+                                              Long productionOrderRoutingOperationId,
+                                              Long productionProductMainId) {
+        if (dto == null || productionOrderRoutingOperationId == null || productionProductMainId == null) {
+            return;
+        }
+        List<ProductionOrderRoutingOperationParam> paramList = dto.getProductionOperationParamList();
+        if (paramList == null || paramList.isEmpty()) {
+            return;
+        }
+        Set<Long> sourceParamIdSet = paramList.stream()
+                .filter(Objects::nonNull)
+                .map(ProductionOrderRoutingOperationParam::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (sourceParamIdSet.isEmpty()) {
+            return;
+        }
+
+        List<ProductionOrderRoutingOperationParam> dbParamList = productionOrderRoutingOperationParamMapper.selectList(
+                Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                        .in(ProductionOrderRoutingOperationParam::getId, sourceParamIdSet)
+                        .eq(ProductionOrderRoutingOperationParam::getProductionOrderRoutingOperationId, productionOrderRoutingOperationId));
+        if (dbParamList == null || dbParamList.isEmpty()) {
+            return;
+        }
+
+        Map<Long, ProductionOrderRoutingOperationParam> dbParamMap = dbParamList.stream()
+                .filter(item -> item != null && item.getId() != null)
+                .collect(Collectors.toMap(ProductionOrderRoutingOperationParam::getId, item -> item, (left, right) -> left));
+        for (ProductionOrderRoutingOperationParam param : paramList) {
+            if (param == null || param.getId() == null) {
+                continue;
+            }
+            ProductionOrderRoutingOperationParam dbParam = dbParamMap.get(param.getId());
+            if (dbParam == null) {
+                throw new ServiceException("宸ュ簭鍙傛暟涓嶅瓨鍦ㄦ垨涓嶅睘浜庡綋鍓嶅伐鍗曞伐搴忥紝ID=" + param.getId());
+            }
+            productionOrderRoutingOperationParamMapper.insert(buildReportParamSnapshot(dbParam, param.getInputValue(), productionProductMainId));
+        }
+    }
+
+    private ProductionOrderRoutingOperationParam buildReportParamSnapshot(ProductionOrderRoutingOperationParam source,
+                                                                          String inputValue,
+                                                                          Long productionProductMainId) {
+        ProductionOrderRoutingOperationParam target = new ProductionOrderRoutingOperationParam();
+        target.setProductionOrderId(source.getProductionOrderId());
+        target.setTechnologyRoutingOperationParamId(source.getTechnologyRoutingOperationParamId());
+        target.setParamCode(source.getParamCode());
+        target.setParamName(source.getParamName());
+        target.setParamType(source.getParamType());
+        target.setParamFormat(source.getParamFormat());
+        target.setUnit(source.getUnit());
+        target.setIsRequired(source.getIsRequired());
+        target.setRemark(source.getRemark());
+        target.setParamId(source.getParamId());
+        target.setTechnologyOperationId(source.getTechnologyOperationId());
+        target.setTechnologyOperationParamId(source.getTechnologyOperationParamId());
+        target.setStandardValue(source.getStandardValue());
+        target.setInputValue(inputValue);
+        target.setProductionOrderRoutingOperationId(source.getProductionOrderRoutingOperationId());
+        target.setProductionProductMainId(productionProductMainId);
+        return target;
+    }
+
+    private List<ProductStructureDto> resolveInputStructures(Long productionOrderId,
+                                                             ProductionOrderRoutingOperation routingOperation,
+                                                             Long outputProductModelId) {
+        if (productionOrderId == null || routingOperation == null || routingOperation.getTechnologyOperationId() == null) {
+            return new ArrayList<>();
+        }
+        ProductionOrderBom orderBom = productionOrderBomMapper.selectOne(
+                Wrappers.<ProductionOrderBom>lambdaQuery()
+                        .eq(ProductionOrderBom::getProductionOrderId, productionOrderId)
+                        .orderByDesc(ProductionOrderBom::getId)
+                        .last("limit 1"));
+        if (orderBom == null || orderBom.getId() == null) {
+            return new ArrayList<>();
+        }
+
+        List<ProductionBomStructure> bomNodeList = productionBomStructureMapper.selectList(
+                Wrappers.<ProductionBomStructure>lambdaQuery()
+                        .eq(ProductionBomStructure::getProductionOrderBomId, orderBom.getId())
+                        .orderByAsc(ProductionBomStructure::getId));
+        if (bomNodeList.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        Map<Long, ProductionBomStructure> nodeMap = bomNodeList.stream()
+                .filter(item -> item != null && item.getId() != null)
+                .collect(Collectors.toMap(ProductionBomStructure::getId, item -> item, (left, right) -> left));
+        Long currentOutputModelId = routingOperation.getProductModelId() != null
+                ? routingOperation.getProductModelId()
+                : outputProductModelId;
+
+        Map<Long, BigDecimal> unitQtyByProductModel = new LinkedHashMap<>();
+        for (ProductionBomStructure node : bomNodeList) {
+            if (node == null || node.getParentId() == null || node.getProductModelId() == null) {
+                continue;
+            }
+            if (!Objects.equals(node.getTechnologyOperationId(), routingOperation.getTechnologyOperationId())) {
+                continue;
+            }
+            ProductionBomStructure parent = nodeMap.get(node.getParentId());
+            if (parent == null || !Objects.equals(parent.getProductModelId(), currentOutputModelId)) {
+                continue;
+            }
+            unitQtyByProductModel.merge(node.getProductModelId(), defaultDecimal(node.getUnitQuantity()), BigDecimal::add);
+        }
+
+        List<ProductStructureDto> result = new ArrayList<>();
+        for (Map.Entry<Long, BigDecimal> entry : unitQtyByProductModel.entrySet()) {
+            if (entry.getValue().compareTo(BigDecimal.ZERO) <= 0) {
+                continue;
+            }
+            ProductStructureDto item = new ProductStructureDto();
+            item.setProductModelId(entry.getKey());
+            item.setUnitQuantity(entry.getValue());
+            result.add(item);
+        }
+        return result;
+    }
+
+    private Boolean removeProductMainByProductionTask(ProductionProductMain productionProductMain) {
+        // 鍒犻櫎鎶ュ伐闇�瑕佸悓姝ュ洖婊氳川妫�銆佸簱瀛樸�佸伐鏃舵牳绠楀拰璁㈠崟/宸ュ崟杩涘害銆�
+        List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(
+                Wrappers.<QualityInspect>lambdaQuery().eq(QualityInspect::getProductMainId, productionProductMain.getId()));
+        if (qualityInspects.size() > 0) {
+            List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.selectList(
+                    Wrappers.<QualityUnqualified>lambdaQuery()
+                            .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList())));
+            if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState() == 1) {
                 throw new ServiceException("璇ユ潯鎶ュ伐宸茬粡涓嶅悎鏍煎鐞嗕簡锛屼笉鍏佽鍒犻櫎");
             }
         }
-        ProductionProductMain productionProductMain = productionProductMainMapper.selectById(id);
-        //璇ユ姤宸ュ搴旂殑宸ヨ壓璺嚎璇︽儏
-        ProductProcessRouteItem productProcessRouteItem = productProcessRouteItemMapper.selectById(productionProductMain.getProductProcessRouteItemId());
-        ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectList(Wrappers.<ProductionProductOutput>lambdaQuery().eq(ProductionProductOutput::getProductMainId, productionProductMain.getId())).get(0);
-        /*鍒犻櫎鏍哥畻*/
-        salesLedgerProductionAccountingMapper.delete(
-                new LambdaQueryWrapper<SalesLedgerProductionAccounting>()
-                        .eq(SalesLedgerProductionAccounting::getProductMainId, productionProductMain.getId())
-        );
-        /*鏇存柊宸ュ崟鍜岀敓浜ц鍗�*/
-        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(productionProductMain.getWorkOrderId());
-        if (productWorkOrder != null && productionProductOutput != null) {
-            BigDecimal outputQty = productionProductOutput.getQuantity() == null ? BigDecimal.ZERO : productionProductOutput.getQuantity();
-            BigDecimal scrapQty = productionProductOutput.getScrapQty() == null ? BigDecimal.ZERO : productionProductOutput.getScrapQty();
-            BigDecimal completeQty = productWorkOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productWorkOrder.getCompleteQuantity();
+        ProductionProductOutput productionProductOutput = productionProductOutputMapper.selectList(
+                Wrappers.<ProductionProductOutput>lambdaQuery()
+                        .eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId()))
+                .stream().findFirst().orElse(null);
+        productionAccountMapper.delete(new LambdaQueryWrapper<ProductionAccount>()
+                .eq(ProductionAccount::getProductionProductMainId, productionProductMain.getId()));
 
-            BigDecimal validQuantity = outputQty.subtract(scrapQty);
-
-            productWorkOrder.setCompleteQuantity(completeQty.subtract(validQuantity));
-            productWorkOrder.setActualEndTime(null);
-            productWorkOrderMapper.updateById(productWorkOrder);
-        } else {
-            throw new ServiceException("鎿嶄綔澶辫触锛氬伐鍗曚俊鎭垨浜у嚭璁板綍涓嶅瓨鍦�");
-        }
-        //鍒ゆ柇鏄惁鏄渶鍚庝竴閬撳伐搴�
-        List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
-        if (productProcessRouteItem.getDragSort() != null && productProcessRouteItems != null && productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
-            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
-            if (productOrder != null) {
-                BigDecimal orderCompleteQty = productOrder.getCompleteQuantity() == null ? BigDecimal.ZERO : productOrder.getCompleteQuantity();
-                BigDecimal totalQty = productionProductOutput.getQuantity() != null ? productionProductOutput.getQuantity() : BigDecimal.ZERO;
-                BigDecimal scrapQty = productionProductOutput.getScrapQty() != null ? productionProductOutput.getScrapQty() : BigDecimal.ZERO;
-                BigDecimal actualQualifiedQty = totalQty.subtract(scrapQty);
-                BigDecimal newCompleteQty = orderCompleteQty.subtract(actualQualifiedQty);
-                productOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty);
-                productOrder.setEndTime(null);
-                productOrderMapper.updateById(productOrder);
+        ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(productionProductMain.getProductionOperationTaskId());
+        if (productionOperationTask != null && productionProductOutput != null) {
+            BigDecimal reportQuantity = defaultDecimal(productionProductOutput.getQuantity());
+            productionOperationTask.setCompleteQuantity(defaultDecimal(productionOperationTask.getCompleteQuantity()).subtract(reportQuantity));
+            productionOperationTask.setActualEndTime(null);
+            if (defaultDecimal(productionOperationTask.getCompleteQuantity()).compareTo(BigDecimal.ZERO) <= 0) {
+                productionOperationTask.setCompleteQuantity(BigDecimal.ZERO);
+                productionOperationTask.setActualStartTime(null);
+                productionOperationTask.setStatus(2);
             } else {
-                throw new ServiceException("鍏宠仈鐨勭敓浜ц鍗曚笉瀛樺湪");
+                productionOperationTask.setStatus(3);
+            }
+            productionOperationTaskMapper.updateById(productionOperationTask);
+
+            ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId());
+            ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId());
+            if (productionOrder != null && routingOperation != null) {
+                // 鍙湁鏈�鍚庝竴閬撳伐搴忕殑鎶ュ伐鎵嶄細褰卞搷鐢熶骇璁㈠崟瀹屽伐鏁伴噺銆�
+                List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList(
+                        Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
+                                .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId())
+                                .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId()));
+                boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size());
+                if (isLastOperation) {
+                    BigDecimal newCompleteQty = defaultDecimal(productionOrder.getCompleteQuantity()).subtract(reportQuantity);
+                    productionOrder.setCompleteQuantity(newCompleteQty.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newCompleteQty);
+                    productionOrder.setEndTime(null);
+                }
+                if (defaultDecimal(productionOrder.getCompleteQuantity()).compareTo(BigDecimal.ZERO) <= 0) {
+                    productionOrder.setStartTime(null);
+                    productionOrder.setStatus(ProductOrderStatusEnum.WAIT.getCode());
+                } else {
+                    productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode());
+                }
+                productionOrderMapper.updateById(productionOrder);
             }
         }
-        //鍒犻櫎璐ㄦ
-        qualityInspectMapper.selectList(
-                new LambdaQueryWrapper<QualityInspect>()
-                        .eq(QualityInspect::getProductMainId, productionProductMain.getId())
-        ).forEach(q -> {
-            qualityInspectParamMapper.delete(
-                    new LambdaQueryWrapper<QualityInspectParam>()
-                            .eq(QualityInspectParam::getInspectId, q.getId()));
-            qualityInspectMapper.deleteById(q.getId());
-                stockUtils.deleteStockInRecord(q.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode());
-        });
 
-        // 鍒犻櫎浜у嚭璁板綍
+        qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                .eq(QualityInspect::getProductMainId, productionProductMain.getId())).forEach(q -> {
+            qualityInspectParamMapper.delete(new LambdaQueryWrapper<QualityInspectParam>()
+                    .eq(QualityInspectParam::getInspectId, q.getId()));
+            qualityInspectMapper.deleteById(q.getId());
+            stockUtils.deleteStockInRecord(q.getId(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode());
+        });
         productionProductOutputMapper.delete(new LambdaQueryWrapper<ProductionProductOutput>()
-                .eq(ProductionProductOutput::getProductMainId, productionProductMain.getId()));
-        //鍒犻櫎鎶曞叆璁板綍
+                .eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId()));
         productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
-                .eq(ProductionProductInput::getProductMainId, productionProductMain.getId()));
-        //鍒犻櫎鎶ュ簾鐨勫叆搴撹褰�
+                .eq(ProductionProductInput::getProductionProductMainId, productionProductMain.getId()));
+        productionOrderRoutingOperationParamMapper.delete(
+                Wrappers.<ProductionOrderRoutingOperationParam>lambdaQuery()
+                        .eq(ProductionOrderRoutingOperationParam::getProductionProductMainId, productionProductMain.getId()));
         stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
-        //鍒犻櫎涓嶉渶瑕佽川妫�鐨勫悎鏍煎叆搴�
         stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode());
-        //鍒犻櫎鎶曞叆瀵瑰簲鐨勫嚭搴撹褰�
         stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
-        // 鍒犻櫎涓昏〃
         productionProductMainMapper.deleteById(productionProductMain.getId());
         return true;
     }
 
+    private String generateProductNo() {
+        String datePrefix = "BG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
+        QueryWrapper<ProductionProductMain> queryWrapper = new QueryWrapper<>();
+        queryWrapper.select("MAX(product_no) as maxNo").likeRight("product_no", datePrefix);
+        List<Map<String, Object>> resultList = productionProductMainMapper.selectMaps(queryWrapper);
+        int sequenceNumber = 1;
+        if (resultList != null && !resultList.isEmpty()) {
+            Map<String, Object> result = resultList.get(0);
+            if (result != null && result.get("maxNo") != null) {
+                String lastNo = result.get("maxNo").toString();
+                if (lastNo.startsWith(datePrefix)) {
+                    try {
+                        sequenceNumber = Integer.parseInt(lastNo.substring(datePrefix.length())) + 1;
+                    } catch (NumberFormatException e) {
+                        sequenceNumber = 1;
+                    }
+                }
+            }
+        }
+        return String.format("%s%03d", datePrefix, sequenceNumber);
+    }
+
+    private BigDecimal defaultDecimal(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value;
+    }
+
+    private Long resolveTaskId(ProductionProductMainDto dto) {
+        if (dto == null) {
+            return null;
+        }
+        return dto.getProductionOperationTaskId();
+    }
+
     @Override
     public ArrayList<Long> listMain(List<Long> idList) {
         return productionProductMainMapper.listMain(idList);
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductOutputServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductOutputServiceImpl.java
index 654b9af..fb2aa26 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductOutputServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductOutputServiceImpl.java
@@ -3,19 +3,17 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.production.dto.ProductionProductOutputDto;
+import com.ruoyi.production.bean.dto.ProductionProductOutputDto;
 import com.ruoyi.production.mapper.ProductionProductOutputMapper;
 import com.ruoyi.production.pojo.ProductionProductOutput;
 import com.ruoyi.production.service.ProductionProductOutputService;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 public class ProductionProductOutputServiceImpl extends ServiceImpl<ProductionProductOutputMapper, ProductionProductOutput> implements ProductionProductOutputService {
-    @Autowired
-    private ProductionProductOutputMapper productionProductOutputMapper;
+    private final ProductionProductOutputMapper productionProductOutputMapper;
 
     @Override
     public IPage<ProductionProductOutputDto> listPageProductionProductOutputDto(Page page, ProductionProductOutputDto productionProductOutputDto) {
diff --git a/src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java
index 7e5f58b..f06284d 100644
--- a/src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java
@@ -1,90 +1,24 @@
 package com.ruoyi.production.service.impl;
 
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.production.dto.ProductionProductMainDto;
-import com.ruoyi.production.dto.SalesLedgerProductionAccountingDto;
-import com.ruoyi.production.dto.UserAccountDto;
-import com.ruoyi.production.dto.UserProductionAccountingDto;
-import com.ruoyi.production.mapper.ProductionProductMainMapper;
-import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper;
-import com.ruoyi.production.pojo.SalesLedgerProductionAccounting;
+import com.ruoyi.production.bean.dto.UserAccountDto;
+import com.ruoyi.production.bean.dto.UserProductionAccountingDto;
+import com.ruoyi.production.mapper.ProductionAccountMapper;
 import com.ruoyi.production.service.SalesLedgerProductionAccountingService;
 import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:41
- */
 @Service
 @RequiredArgsConstructor
-@Slf4j
-public class SalesLedgerProductionAccountingServiceImpl extends ServiceImpl<SalesLedgerProductionAccountingMapper, SalesLedgerProductionAccounting> implements SalesLedgerProductionAccountingService {
-  
-    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-    private final ProductionProductMainMapper productionProductMainMapper;
+public class SalesLedgerProductionAccountingServiceImpl implements SalesLedgerProductionAccountingService {
+
+    private final ProductionAccountMapper productionAccountMapper;
 
     @Override
-    public IPage<SalesLedgerProductionAccountingDto> listPage(Page page, SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto) {
-        IPage<SalesLedgerProductionAccountingDto> list = salesLedgerProductionAccountingMapper.listPage(page, salesLedgerProductionAccountingDto);
-        list.getRecords().forEach(item -> {
-            String[] split = item.getSpecificationModel().split("\\*");
-            if(split.length == 2 && isNumeric(split[1])){
-                // 璁$畻宸ヨ祫 = 宸ユ椂瀹氶 * 鏁伴噺 * 瑙勬牸
-                item.setWages(item.getWages().multiply(new BigDecimal(split[1])));
-            }
-        });
-        return list;
-    }
-
-    @Override
-    public IPage<SalesLedgerProductionAccountingDto> pageProductionAccounting(SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page) {
-        // TODO 绠$悊鍛樻煡璇㈡墍鏈夛紝鍏朵粬浜哄彧鑳芥煡鑷繁
-        boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
-        if (!admin) {
-            salesLedgerProductionAccountingDto.setSchedulingUserName(SecurityUtils.getUsername());
+    public UserAccountDto getByUserId(UserProductionAccountingDto dto) {
+        if (dto == null || dto.getUserId() == null || dto.getDate() == null || dto.getDate().trim().isEmpty()) {
+            return new UserAccountDto();
         }
-        if (salesLedgerProductionAccountingDto.getDateType().equals("month"))  {
-            salesLedgerProductionAccountingDto.setEntryDate(null);
-        }else {
-            salesLedgerProductionAccountingDto.setEntryDateStart(null);
-            salesLedgerProductionAccountingDto.setEntryDateEnd(null);
-        }
-        return salesLedgerProductionAccountingMapper.pageProductionAccounting(page, salesLedgerProductionAccountingDto);
-    }
-
-    @Override
-    public IPage<ProductionProductMainDto> listProductionDetails(SalesLedgerProductionAccountingDto salesLedgerProductionAccountingDto, Page page) {
-        if (salesLedgerProductionAccountingDto.getDateType().equals("month"))  {
-            salesLedgerProductionAccountingDto.setEntryDate(null);
-        }else {
-            salesLedgerProductionAccountingDto.setEntryDateStart(null);
-            salesLedgerProductionAccountingDto.setEntryDateEnd(null);
-        }
-        return productionProductMainMapper.listProductionDetails(salesLedgerProductionAccountingDto, page);
-    }
-
-    @Override
-    public UserAccountDto getByUserId(UserProductionAccountingDto userProductionAccountingDto) {
-        return salesLedgerProductionAccountingMapper.getByUserId( userProductionAccountingDto);
-    }
-
-    public static boolean isNumeric(String str) {
-        if (str == null || str.isEmpty()) {
-            return false;
-        }
-        // 閬嶅巻瀛楃涓茬殑姣忎釜瀛楃锛屾鏌ユ槸鍚︿负鏁板瓧
-        for (int i = 0; i < str.length(); i++) {
-            if (!Character.isDigit(str.charAt(i))) {
-                return false;
-            }
-        }
-        return true;
+        UserAccountDto result = productionAccountMapper.selectUserAccount(dto.getUserId(), dto.getDate());
+        return result == null ? new UserAccountDto() : result;
     }
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java
deleted file mode 100644
index 81fd76f..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java
+++ /dev/null
@@ -1,390 +0,0 @@
-package com.ruoyi.production.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.security.LoginUser;
-import com.ruoyi.production.dto.*;
-import com.ruoyi.production.mapper.SalesLedgerSchedulingMapper;
-import com.ruoyi.production.mapper.SalesLedgerWorkMapper;
-import com.ruoyi.production.mapper.SpeculativeTradingInfoMapper;
-import com.ruoyi.production.pojo.SalesLedgerScheduling;
-import com.ruoyi.production.pojo.SalesLedgerWork;
-import com.ruoyi.production.pojo.SpeculativeTradingInfo;
-import com.ruoyi.production.service.SalesLedgerSchedulingService;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.mapper.SysUserMapper;
-import com.ruoyi.sales.mapper.LossMapper;
-import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.Loss;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
-
-import javax.servlet.http.HttpServletResponse;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
-/**
- * @author :yys
- * @date : 2025/7/21 14:41
- */
-@Service
-@RequiredArgsConstructor
-@Slf4j
-public class SalesLedgerSchedulingServiceImpl extends ServiceImpl<SalesLedgerSchedulingMapper, SalesLedgerScheduling> implements SalesLedgerSchedulingService {
-
-    private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper;
-
-    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
-
-    @Override
-    public IPage<SalesLedgerSchedulingDto> listPage(Page page, SalesLedgerSchedulingDto salesLedgerSchedulingDto) {
-        IPage<SalesLedgerSchedulingDto> list = salesLedgerSchedulingMapper.listPage(page, salesLedgerSchedulingDto);
-        if(CollectionUtils.isEmpty(list.getRecords())){
-            return list;
-        }
-        Set<Long> collect = list.getRecords().stream().map(SalesLedgerSchedulingDto::getSalesLedgerProductId).collect(Collectors.toSet());
-        LambdaQueryWrapper<SalesLedgerWork> salesLedgerWorkLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        salesLedgerWorkLambdaQueryWrapper.in(SalesLedgerWork::getSalesLedgerProductId, collect)
-                .ne(SalesLedgerWork::getStatus, 1);
-        List<SalesLedgerWork> salesLedgerWorks = salesLedgerWorkMapper.selectList(salesLedgerWorkLambdaQueryWrapper);
-        list.getRecords().forEach(i -> {
-            // 鑾峰彇瀹屾垚鏁伴噺
-            i.setSuccessNum(salesLedgerWorks
-                    .stream()
-                    .filter(j -> j.getSalesLedgerProductId().equals(i.getSalesLedgerProductId()))
-                    .map(SalesLedgerWork::getFinishedNum)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add));
-
-            // 璁$畻鐢熶骇鎬婚噺 = 瑙勬牸 * 鏁伴噺 / 1000
-            String[] split = i.getSpecificationModel().split("\\*");
-            if(split.length == 2 && isNumeric(split[0]) && isNumeric(split[1])){
-                BigDecimal multiply = new BigDecimal(split[0])
-                        .multiply(new BigDecimal(split[1])
-                                .multiply(i.getQuantity()).divide(new BigDecimal(1000),2, RoundingMode.CEILING));
-                i.setTotalProduction(multiply);
-            }
-
-            // 鐘舵�� = 鏁伴噺鍜屽畬宸ユ暟閲忔瘮杈�
-            if(i.getSchedulingNum().compareTo(new BigDecimal(0)) == 0){
-                i.setStatus("鏈紑濮�");
-            } else if(i.getQuantity().compareTo(i.getSchedulingNum()) <= 0){
-                i.setStatus("宸插畬鎴�");
-            }else{
-                i.setStatus("鐢熶骇涓�");
-            }
-            // 杩涘害淇濈暀涓や綅灏忔暟
-            i.setProgress(i.getSchedulingNum().divide(i.getQuantity(),4,RoundingMode.CEILING).multiply(new BigDecimal(100)));
-
-        });
-        return list;
-    }
-
-    public static boolean isNumeric(String str) {
-        if (str == null || str.isEmpty()) {
-            return false;
-        }
-        // 閬嶅巻瀛楃涓茬殑姣忎釜瀛楃锛屾鏌ユ槸鍚︿负鏁板瓧
-        for (int i = 0; i < str.length(); i++) {
-            if (!Character.isDigit(str.charAt(i))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public void export(HttpServletResponse response) {
-        List<SalesLedgerSchedulingDto> list = salesLedgerSchedulingMapper.list();
-        if(CollectionUtils.isEmpty(list)){
-            throw new RuntimeException("鏃犲鍑烘暟鎹�");
-        }
-        Set<Long> collect = list.stream().map(SalesLedgerSchedulingDto::getSalesLedgerProductId).collect(Collectors.toSet());
-        LambdaQueryWrapper<SalesLedgerWork> salesLedgerWorkLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        salesLedgerWorkLambdaQueryWrapper.in(SalesLedgerWork::getSalesLedgerProductId, collect)
-                .ne(SalesLedgerWork::getStatus, 1);
-        List<SalesLedgerWork> salesLedgerWorks = salesLedgerWorkMapper.selectList(salesLedgerWorkLambdaQueryWrapper);
-        list.forEach(i -> {
-            // 鑾峰彇瀹屾垚鏁伴噺
-            i.setSuccessNum(salesLedgerWorks
-                    .stream()
-                    .filter(j -> j.getSalesLedgerProductId().equals(i.getSalesLedgerProductId()))
-                    .map(SalesLedgerWork::getFinishedNum)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add));
-        });
-        ExcelUtil<SalesLedgerSchedulingDto> util = new ExcelUtil<>(SalesLedgerSchedulingDto.class);
-        util.exportExcel(response, list, "鐢熶骇璁㈠崟");
-    }
-
-    private final SysUserMapper sysUserMapper;
-
-    private final SpeculativeTradingInfoMapper speculativeTradingInfoMapper;
-
-    @Override
-    public String productionDispatch(List<ProductionDispatchAddDto> productionDispatchAddDtoList) {
-        int i = 0;
-        int successNum = 0;
-        LoginUser loginUser = SecurityUtils.getLoginUser();
-        for (ProductionDispatchAddDto productionDispatchAddDto : productionDispatchAddDtoList) {
-            SysUser sysUser = sysUserMapper.selectUserById(productionDispatchAddDto.getSchedulingUserId() == null ? loginUser.getUser().getUserId() : productionDispatchAddDto.getSchedulingUserId());
-            if(sysUser == null){
-                i++;
-                continue;
-            }
-            // 鑾峰彇绌轰綑鐐掓満
-            String[] split = productionDispatchAddDto.getSpeculativeTradingName().split(",");
-            if(split != null && split.length == 0){
-                i++;
-                continue;
-            }
-            List<SpeculativeTradingInfo> speculativeTradingInfos = speculativeTradingInfoMapper.selectList(new LambdaQueryWrapper<SpeculativeTradingInfo>()
-                    .in(SpeculativeTradingInfo::getName, Arrays.asList(split))
-                    .orderByAsc(SpeculativeTradingInfo::getSort));
-            if(CollectionUtils.isEmpty(speculativeTradingInfos)){
-                i++;
-                continue;
-            }
-            AtomicReference<String> name = new AtomicReference<>("");  //闇�瑕佺粦瀹氱殑鐐掓満
-            //閫氳繃瑙勬牸鍨嬪彿鍜屾帓浜ф暟閲忚绠楁湰娆$敓浜т骇閲�
-            String[] split1 = productionDispatchAddDto.getSpecificationModel().split("\\*");
-            if(split1.length != 2){
-                i++;
-                continue;
-            }
-            // 鏈鐢熶骇浜ч噺
-            BigDecimal productionNum = new BigDecimal(split1[0])
-                    .multiply(new BigDecimal(split1[1]).multiply(productionDispatchAddDto.getSchedulingNum()));
-            // 澶氫釜鐐掓満鎯呭喌
-            if(speculativeTradingInfos.size() > 1){
-                for (SpeculativeTradingInfo speculativeTradingInfo : speculativeTradingInfos) {
-                    // 鑾峰彇璇ョ倰鏈烘鍦ㄦ帓浜ч噺
-                    BigDecimal schedulingNumBySpeculativeTradingName = getSchedulingNumBySpeculativeTradingName(speculativeTradingInfo.getName());
-                    // 濡傛灉璇ョ倰鏈烘�婚噺(鍗曚綅kg闇�瑕佷箻1000) - 姝e湪鎺掍骇閲� >=鏈鐢熶骇浜ч噺灏卞垎閰嶆鐐掓満
-                    if(speculativeTradingInfo.getWorkLoad().multiply(new BigDecimal(1000)).subtract(schedulingNumBySpeculativeTradingName).compareTo(productionNum) >= 0){
-                        name.set(speculativeTradingInfo.getName());
-                        break;
-                    }
-                }
-            }else{
-                // 鍗曚釜鐐掓満鎯呭喌
-                name.set(speculativeTradingInfos.get(0).getName());
-            }
-            if(name.get().isEmpty()){
-                i++;
-                continue;
-            }
-            String productionLine = "";
-            switch (name.get()){
-                    case "鐐掓満1":
-                    productionLine = "浜х嚎1";
-                    break;
-                    case "鐐掓満2":
-                    productionLine = "浜х嚎2";
-                    break;
-                    case "鐐掓満3":
-                    productionLine = "浜х嚎3";
-                    break;
-                    case "鐐掓満4":
-                    productionLine = "浜х嚎4";
-                    break;
-            }
-            SalesLedgerScheduling salesLedgerScheduling = SalesLedgerScheduling.builder()
-                    .salesLedgerId(productionDispatchAddDto.getSalesLedgerId())
-                    .salesLedgerProductId(productionDispatchAddDto.getSalesLedgerProductId())
-                    .speculativeTradingName(name.get())
-                    .productionLine(productionLine)
-                    .schedulingUserId(sysUser.getUserId())
-                    .schedulingUserName(sysUser.getNickName())
-                    .schedulingNum(productionDispatchAddDto.getSchedulingNum())
-                    .schedulingDate(productionDispatchAddDto.getSchedulingDate() == null ? LocalDate.now() : LocalDate.parse(productionDispatchAddDto.getSchedulingDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd")))
-                    .status(1)
-                    .build();
-            salesLedgerSchedulingMapper.insert(salesLedgerScheduling);
-            successNum++;
-        }
-
-        return "娲惧伐鎴愬姛鏁伴噺" + successNum + "锛屽け璐ユ暟閲�" + i;
-    }
-
-    private final SalesLedgerProductMapper salesLedgerProductMapper;
-
-    /**
-     *閫氳繃鐐掓満鍚嶇О鑾峰彇褰撳ぉ姝e湪鎺掍骇閲�
-     * @return
-     */
-    public BigDecimal getSchedulingNumBySpeculativeTradingName(String speculativeTradingName){
-        LambdaQueryWrapper<SalesLedgerScheduling> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(SalesLedgerScheduling::getSpeculativeTradingName, speculativeTradingName)
-                .eq(SalesLedgerScheduling::getSchedulingDate, LocalDate.now());
-        List<SalesLedgerScheduling> salesLedgerSchedulings = salesLedgerSchedulingMapper.selectList(queryWrapper);
-        if(CollectionUtils.isEmpty(salesLedgerSchedulings)){
-            return BigDecimal.ZERO;
-        }
-        List<Long> collect = salesLedgerSchedulings.stream().map(SalesLedgerScheduling::getSalesLedgerProductId).collect(Collectors.toList());
-        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
-                .in(SalesLedgerProduct::getId, collect));
-        if(CollectionUtils.isEmpty(salesLedgerProducts)) return BigDecimal.ZERO;
-        AtomicInteger totalNum = new AtomicInteger(0); //鎬绘暟
-        salesLedgerSchedulings.forEach(item ->{
-            List<SalesLedgerProduct> collect1 = salesLedgerProducts.stream()
-                    .filter(j -> j.getId().equals(item.getSalesLedgerProductId()))
-                    .collect(Collectors.toList());
-            if(!CollectionUtils.isEmpty(collect1)){
-                SalesLedgerProduct salesLedgerProduct = collect1.get(0);
-                // 鏍规嵁浜у搧瑙勬牸 * 鎺掍骇鏁伴噺 鑾峰彇鏈鐢熶骇浜ч噺骞剁疮璁�
-                String[] split = salesLedgerProduct.getSpecificationModel().split("\\*");
-                BigDecimal productionNum = new BigDecimal(split[0])
-                        .multiply(new BigDecimal(split[1]).multiply(item.getSchedulingNum()));
-                totalNum.addAndGet(productionNum.intValue());
-            }
-        });
-        // 闇�瑕� / 鎹熻�楃巼
-        Loss loss = lossMapper.selectOne(new LambdaQueryWrapper<Loss>().last("limit 1"));
-        BigDecimal lossNum = loss == null ? new BigDecimal(6) : loss.getRate(); //娌℃湁鎹熻�楃巼鍒欓粯璁や负6
-
-        return new BigDecimal(totalNum.get()).multiply(new BigDecimal(100)).divide(lossNum, 2,RoundingMode.HALF_UP);
-    }
-
-    private final LossMapper lossMapper;
-
-
-    /**
-     *閫氳繃鎵归噺鐐掓満鍚嶇О鑾峰彇褰撳ぉ姝e湪鎺掍骇閲�
-     * @return
-     */
-    public BigDecimal getSchedulingNumBySpeculativeTradingNameList(List<String> speculativeTradingName){
-        LambdaQueryWrapper<SalesLedgerScheduling> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.in(SalesLedgerScheduling::getSpeculativeTradingName, speculativeTradingName)
-                .eq(SalesLedgerScheduling::getSchedulingDate, LocalDate.now());
-        List<SalesLedgerScheduling> salesLedgerSchedulings = salesLedgerSchedulingMapper.selectList(queryWrapper);
-        if(CollectionUtils.isEmpty(salesLedgerSchedulings)){
-            return BigDecimal.ZERO;
-        }
-        List<Long> collect = salesLedgerSchedulings.stream().map(SalesLedgerScheduling::getSalesLedgerProductId).collect(Collectors.toList());
-        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
-                .in(SalesLedgerProduct::getId, collect));
-        if(CollectionUtils.isEmpty(salesLedgerProducts)) return BigDecimal.ZERO;
-        AtomicInteger totalNum = new AtomicInteger(0); //鎬绘暟
-        salesLedgerSchedulings.forEach(item ->{
-            List<SalesLedgerProduct> collect1 = salesLedgerProducts.stream()
-                    .filter(j -> j.getId().equals(item.getSalesLedgerProductId()))
-                    .collect(Collectors.toList());
-            if(!CollectionUtils.isEmpty(collect1)){
-                SalesLedgerProduct salesLedgerProduct = collect1.get(0);
-                // 鏍规嵁浜у搧瑙勬牸 * 鎺掍骇鏁伴噺 鑾峰彇鏈鐢熶骇浜ч噺骞剁疮璁�
-                String[] split = salesLedgerProduct.getSpecificationModel().split("\\*");
-                BigDecimal productionNum = new BigDecimal(split[0])
-                        .multiply(new BigDecimal(split[1]).multiply(item.getSchedulingNum()));
-                totalNum.addAndGet(productionNum.intValue());
-            }
-        });
-        return new BigDecimal(totalNum.get());
-    }
-
-    @Override
-    public IPage<SalesLedgerSchedulingProcessDto> listPageProcess(Page page, SalesLedgerSchedulingProcessDto salesLedgerSchedulingDto) {
-        IPage<SalesLedgerSchedulingProcessDto> list = salesLedgerSchedulingMapper.listPageProcess(page, salesLedgerSchedulingDto);
-        list.getRecords().forEach(i -> {
-            // 璁$畻鐢熶骇鎬婚噺 = 瑙勬牸 * 鏁伴噺 / 1000
-            String[] split = i.getSpecificationModel().split("\\*");
-            if(split.length == 2 && isNumeric(split[0]) && isNumeric(split[1])){
-                BigDecimal multiply = new BigDecimal(split[0])
-                        .multiply(new BigDecimal(split[1])
-                                .multiply(i.getSuccessNum()).divide(new BigDecimal(1000),2, RoundingMode.CEILING));
-                i.setTotalProduction(multiply);
-            }
-        });
-        return list;
-    }
-
-    @Override
-    public int productionDispatchDelete(List<Long> ids) {
-        LambdaQueryWrapper<SalesLedgerScheduling> salesLedgerSchedulingLambdaQueryWrapper = new LambdaQueryWrapper<SalesLedgerScheduling>();
-        salesLedgerSchedulingLambdaQueryWrapper.in(SalesLedgerScheduling::getId, ids);
-        List<SalesLedgerScheduling> salesLedgerSchedulings = salesLedgerSchedulingMapper.selectList(salesLedgerSchedulingLambdaQueryWrapper);
-        if(CollectionUtils.isEmpty(salesLedgerSchedulings)) throw new RuntimeException("鎺掍骇涓嶅瓨鍦�");
-        List<SalesLedgerScheduling> collect = salesLedgerSchedulings.stream().filter(i -> !i.getStatus().equals(1)).collect(Collectors.toList());
-        if(!CollectionUtils.isEmpty(collect)) throw new RuntimeException("鎺掍骇宸插紑濮嬶紝璇峰嬁鍒犻櫎");
-        salesLedgerSchedulingMapper.deleteBatchIds(ids);
-        return 0;
-    }
-
-    @Override
-    public int processScheduling(List<ProcessSchedulingDto> processSchedulingDtos) {
-        for (ProcessSchedulingDto processSchedulingDto : processSchedulingDtos) {
-            SalesLedgerScheduling salesLedgerScheduling = salesLedgerSchedulingMapper.selectById(processSchedulingDto.getId());
-            if(salesLedgerScheduling == null) throw new RuntimeException("鎺掍骇涓嶅瓨鍦�");
-            if(salesLedgerScheduling.getStatus().equals(3)) throw new RuntimeException("鎺掍骇宸插畬鎴愶紝璇峰嬁閲嶅鎺掍骇");
-            SysUser sysUser = sysUserMapper.selectUserById(processSchedulingDto.getSchedulingUserId());
-            if(sysUser == null) throw new RuntimeException("鎺掍骇浜轰笉瀛樺湪");
-            salesLedgerScheduling.setFinishedNum(salesLedgerScheduling.getFinishedNum().add(processSchedulingDto.getSchedulingNum()));
-//            LambdaQueryWrapper<SalesLedgerWork> salesLedgerWorkLambdaQueryWrapper = new LambdaQueryWrapper<>();
-//            salesLedgerWorkLambdaQueryWrapper.eq(SalesLedgerWork::getSalesLedgerSchedulingId, salesLedgerScheduling.getId())
-//                    .ne(SalesLedgerWork::getStatus, 1);
-//            List<SalesLedgerWork> salesLedgerWorks = salesLedgerWorkMapper.selectList(salesLedgerWorkLambdaQueryWrapper);
-            if(salesLedgerScheduling.getSchedulingNum().compareTo(salesLedgerScheduling.getFinishedNum()) < 0){
-                throw new RuntimeException("褰撳墠鎺掍骇鏁伴噺澶т簬寰呮帓浜ф暟閲忥紝璇蜂粩缁嗘牳瀵癸紒");
-            }
-            if(salesLedgerScheduling.getSchedulingNum().compareTo(salesLedgerScheduling.getFinishedNum()) == 0){
-                salesLedgerScheduling.setStatus(3);
-            }else{
-                salesLedgerScheduling.setStatus(2);
-            }
-            salesLedgerSchedulingMapper.updateById(salesLedgerScheduling);
-            SalesLedgerWork.SalesLedgerWorkBuilder salesLedgerWorkBuilder = SalesLedgerWork.builder()
-                    .salesLedgerSchedulingId(salesLedgerScheduling.getId())
-                    .salesLedgerId(salesLedgerScheduling.getSalesLedgerId())
-                    .remark(processSchedulingDto.getRemark())
-                    .productionLine(processSchedulingDto.getProductionLine())
-                    .type(processSchedulingDto.getType())
-                    .loss(processSchedulingDto.getLoss())
-                    .receive(processSchedulingDto.getReceive())
-                    .salesLedgerProductId(salesLedgerScheduling.getSalesLedgerProductId())
-                    .schedulingUserId(salesLedgerScheduling.getSchedulingUserId())
-                    .schedulingUserName(sysUser.getNickName())
-                    .schedulingNum(processSchedulingDto.getSchedulingNum())
-                    .workHours(processSchedulingDto.getWorkHours())
-                    .process(processSchedulingDto.getProcess())
-                    .status(1)
-                    .schedulingDate(LocalDate.parse(processSchedulingDto.getSchedulingDate(), DateTimeFormatter.ISO_LOCAL_DATE));
-            salesLedgerWorkMapper.insert(salesLedgerWorkBuilder.build());
-        }
-        return 0;
-    }
-
-    @Override
-    public void exportOne(HttpServletResponse response) {
-        List<SalesLedgerSchedulingDto> list = salesLedgerSchedulingMapper.list();
-        if(CollectionUtils.isEmpty(list)){
-            throw new RuntimeException("鏃犲鍑烘暟鎹�");
-        }
-        List<DaiDto> dais = new ArrayList<>();
-        list.forEach(i -> {
-            DaiDto daiDto = new DaiDto();
-            BeanUtils.copyProperties(i, daiDto);
-            // 鑾峰彇寰呮帓浜ф暟閲�
-            daiDto.setDaiNum(daiDto.getQuantity().subtract(i.getSchedulingNum()));
-            dais.add(daiDto);
-        });
-        ExcelUtil<DaiDto> util = new ExcelUtil<>(DaiDto.class);
-        util.exportExcel(response, dais, "鐢熶骇娲惧伐");
-    }
-}
diff --git a/src/main/java/com/ruoyi/production/service/impl/SalesLedgerWorkServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/SalesLedgerWorkServiceImpl.java
deleted file mode 100644
index 6573b73..0000000
--- a/src/main/java/com/ruoyi/production/service/impl/SalesLedgerWorkServiceImpl.java
+++ /dev/null
@@ -1,182 +0,0 @@
-//package com.ruoyi.production.service.impl;
-//
-//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-//import com.baomidou.mybatisplus.core.metadata.IPage;
-//import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-//import com.ruoyi.common.utils.SecurityUtils;
-//import com.ruoyi.framework.security.LoginUser;
-//import com.ruoyi.framework.web.domain.AjaxResult;
-//import com.ruoyi.procurementrecord.dto.Details;
-//import com.ruoyi.procurementrecord.dto.ProcurementAddDto;
-//import com.ruoyi.procurementrecord.dto.ProcurementRecordOutAdd;
-//import com.ruoyi.procurementrecord.service.impl.ProcurementRecordOutServiceImpl;
-//import com.ruoyi.procurementrecord.service.impl.ProcurementRecordServiceImpl;
-//import com.ruoyi.production.dto.ProductionReportDto;
-//import com.ruoyi.production.dto.SalesLedgerWorkDto;
-//import com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper;
-//import com.ruoyi.production.mapper.SalesLedgerWorkMapper;
-//import com.ruoyi.production.pojo.SalesLedgerProductionAccounting;
-//import com.ruoyi.production.pojo.SalesLedgerWork;
-//import com.ruoyi.production.service.SalesLedgerProductionAccountingService;
-//import com.ruoyi.production.service.SalesLedgerWorkService;
-//import com.ruoyi.project.system.domain.SysUser;
-//import com.ruoyi.project.system.mapper.SysUserMapper;
-//import com.ruoyi.sales.mapper.LossMapper;
-//import com.ruoyi.sales.pojo.Loss;
-//import lombok.RequiredArgsConstructor;
-//import lombok.extern.slf4j.Slf4j;
-//import org.springframework.beans.BeanUtils;
-//import org.springframework.stereotype.Service;
-//import org.springframework.util.CollectionUtils;
-//
-//import java.math.BigDecimal;
-//import java.math.RoundingMode;
-//import java.time.LocalDate;
-//import java.time.format.DateTimeFormatter;
-//import java.util.ArrayList;
-//import java.util.List;
-//import java.util.stream.Collectors;
-//
-///**
-// * @author :yys
-// * @date : 2025/7/21 14:40
-// */
-//@Service
-//@RequiredArgsConstructor
-//@Slf4j
-//public class SalesLedgerWorkServiceImpl extends ServiceImpl<SalesLedgerWorkMapper, SalesLedgerWork> implements SalesLedgerWorkService {
-//
-//    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
-//
-//    private final SysUserMapper sysUserMapper;
-//
-//    private final LossMapper lossMapper;
-//
-//    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-//
-//    @Override
-//    public IPage<SalesLedgerWorkDto> listPage(Page page, SalesLedgerWorkDto salesLedgerWorkDto) {
-//        IPage<SalesLedgerWorkDto> iPage = salesLedgerWorkMapper.listPage(page, salesLedgerWorkDto);
-//        List<Loss> losses = lossMapper.selectList(null);
-//        if(!CollectionUtils.isEmpty(losses)){
-//            iPage.getRecords().forEach(item -> {
-//                String[] split = item.getSpecificationModel().split("\\*");
-//                if(split.length == 2 && isNumeric(split[1]) && isNumeric(split[0])){
-//                    // 璁$畻鎹熻�楋紙100000浠h〃 鎹熻�楃殑 100 鍜� 鍗曚綅杞崲鐨�1000锛�
-//                    BigDecimal divide = new BigDecimal(split[0])
-//                            .multiply(new BigDecimal(split[1]))
-//                            .multiply(item.getFinishedNum())
-//                            .multiply(losses.get(0).getRate())
-//                            .divide(new BigDecimal(100000), 2, RoundingMode.HALF_UP);
-//                    item.setLoss(divide.toString());
-//                }
-//
-//            });
-//        }
-//        return iPage;
-//    }
-//
-//    public static boolean isNumeric(String str) {
-//        if (str == null || str.isEmpty()) {
-//            return false;
-//        }
-//        // 閬嶅巻瀛楃涓茬殑姣忎釜瀛楃锛屾鏌ユ槸鍚︿负鏁板瓧
-//        for (int i = 0; i < str.length(); i++) {
-//            if (!Character.isDigit(str.charAt(i))) {
-//                return false;
-//            }
-//        }
-//        return true;
-//    }
-//
-//    private final ProcurementRecordServiceImpl procurementRecordService;
-//
-//    @Override
-//    public int productionReport(ProductionReportDto productionReportDto) {
-//        SalesLedgerWork salesLedgerWork = salesLedgerWorkMapper.selectById(productionReportDto.getId());
-//        SysUser sysUser = sysUserMapper.selectUserById(productionReportDto.getSchedulingUserId());
-//        if (salesLedgerWork == null) throw new RuntimeException("鎶ュ伐鏁版嵁涓嶅瓨鍦�");
-//        if (salesLedgerWork.getStatus() == 3) throw new RuntimeException("鎶ュ伐宸插畬鎴�");
-//        if (sysUser == null) throw new RuntimeException("鐢熶骇浜轰笉瀛樺湪");
-//        salesLedgerWork.setFinishedNum(salesLedgerWork.getFinishedNum().add(productionReportDto.getFinishedNum()));
-//        if(salesLedgerWork.getSchedulingNum().compareTo(salesLedgerWork.getFinishedNum()) <= 0){
-//            salesLedgerWork.setStatus(3);
-//        }else{
-//            salesLedgerWork.setStatus(2);
-//        }
-//        salesLedgerWorkMapper.updateById(salesLedgerWork);
-//        // 鏂板鎶ュ伐鏁版嵁
-//        SalesLedgerProductionAccounting.SalesLedgerProductionAccountingBuilder builder = SalesLedgerProductionAccounting.builder()
-//                .productMainId(null)
-//                .schedulingUserId(sysUser.getUserId())
-//                .schedulingUserName(sysUser.getNickName())
-//                .finishedNum(productionReportDto.getFinishedNum())
-//                .workHours(salesLedgerWork.getWorkHours())
-//                .process(salesLedgerWork.getProcess())
-//                .schedulingDate(LocalDate.parse(productionReportDto.getSchedulingDate(), DateTimeFormatter.ISO_LOCAL_DATE));
-//        salesLedgerProductionAccountingMapper.insert(builder.build());
-//        // 鐢熶骇鎶ュ伐鎴愬姛 -> 鍏ュ簱
-//        LoginUser loginUser = SecurityUtils.getLoginUser();
-//        ProcurementAddDto procurementRecordOutAdd = new ProcurementAddDto();
-//        procurementRecordOutAdd.setType(2);
-//        procurementRecordOutAdd.setTypeName("鐢熶骇鍏ュ簱");
-//        procurementRecordOutAdd.setNickName(loginUser.getNickName());
-//        List<Details> details = new ArrayList<>();
-//        Details details1 = new Details();
-//        details1.setInboundQuantity(productionReportDto.getFinishedNum());
-//        details1.setId(Integer.parseInt(salesLedgerWork.getSalesLedgerProductId().toString()));
-//        details1.setUnitPrice(productionReportDto.getUnitPrice());
-//        details1.setTotalPrice(productionReportDto.getTotalPrice());
-//        details.add(details1);
-//        procurementRecordOutAdd.setDetails(details);
-//        procurementRecordService.add(procurementRecordOutAdd);
-//
-//        return 0;
-//    }
-//
-//    @Override
-//    public int productionReportUpdate(ProductionReportDto productionReportDto) {
-//        SalesLedgerProductionAccounting salesLedgerProductionAccounting = salesLedgerProductionAccountingMapper.selectById(productionReportDto.getId());
-//        if(salesLedgerProductionAccounting == null) throw new RuntimeException("鎶ュ伐鏁版嵁涓嶅瓨鍦�");
-//        SysUser sysUser = sysUserMapper.selectUserById(productionReportDto.getSchedulingUserId());
-//        if(sysUser == null) throw new RuntimeException("鐢熶骇浜轰笉瀛樺湪");
-//        salesLedgerProductionAccounting.setFinishedNum(productionReportDto.getFinishedNum());
-//        salesLedgerProductionAccounting.setSchedulingUserId(sysUser.getUserId());
-//        salesLedgerProductionAccounting.setSchedulingUserName(sysUser.getNickName());
-//        salesLedgerProductionAccounting.setSchedulingDate(LocalDate.parse(productionReportDto.getSchedulingDate(), DateTimeFormatter.ISO_LOCAL_DATE));
-//        salesLedgerProductionAccountingMapper.updateById(salesLedgerProductionAccounting);
-//
-//        // 鏇存柊鎶ュ伐鏁版嵁
-//        SalesLedgerWork salesLedgerWork = salesLedgerWorkMapper.selectById(salesLedgerProductionAccounting.getSalesLedgerWorkId());
-//        if(salesLedgerWork == null) throw new RuntimeException("鎶ュ伐鏁版嵁涓嶅瓨鍦�");
-//        salesLedgerWork.setFinishedNum(productionReportDto.getFinishedNum());
-//        if(salesLedgerWork.getSchedulingNum().compareTo(salesLedgerWork.getFinishedNum()) <= 0){
-//            salesLedgerWork.setStatus(3);
-//        }else{
-//            salesLedgerWork.setStatus(2);
-//        }
-//        salesLedgerWork.setSchedulingUserId(sysUser.getUserId());
-//        salesLedgerWork.setSchedulingUserName(sysUser.getNickName());
-//        salesLedgerWork.setSchedulingDate(LocalDate.parse(productionReportDto.getSchedulingDate(), DateTimeFormatter.ISO_LOCAL_DATE));
-//        salesLedgerWorkMapper.updateById(salesLedgerWork);
-//        return 0;
-//    }
-//
-//    @Override
-//    public List<ProductionReportDto> getList(Long id) {
-//        SalesLedgerWork salesLedgerWork = salesLedgerWorkMapper.selectById(id);
-//        if(salesLedgerWork == null) throw new RuntimeException("鎶ュ伐鏁版嵁涓嶅瓨鍦�");
-//        LambdaQueryWrapper<SalesLedgerProductionAccounting> salesLedgerProductionAccountingLambdaQueryWrapper = new LambdaQueryWrapper<>();
-//        salesLedgerProductionAccountingLambdaQueryWrapper.eq(SalesLedgerProductionAccounting::getSalesLedgerWorkId, id);
-//        List<SalesLedgerProductionAccounting> salesLedgerProductionAccountingList = salesLedgerProductionAccountingMapper.selectList(salesLedgerProductionAccountingLambdaQueryWrapper);
-//        if(CollectionUtils.isEmpty(salesLedgerProductionAccountingList)) throw new RuntimeException("娌℃湁鐢熶骇璁板綍鏁版嵁");
-//        return salesLedgerProductionAccountingList.stream().map(salesLedgerProductionAccounting -> {
-//            ProductionReportDto productionReportDto = new ProductionReportDto();
-//            BeanUtils.copyProperties(salesLedgerProductionAccounting, productionReportDto);
-//            productionReportDto.setSchedulingDate(salesLedgerProductionAccounting.getSchedulingDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
-//            productionReportDto.setSchedulingNum(salesLedgerWork.getSchedulingNum());
-//            return productionReportDto;
-//        }).collect(Collectors.toList());
-//    }
-//}
diff --git a/src/main/java/com/ruoyi/project/common/CaptchaController.java b/src/main/java/com/ruoyi/project/common/CaptchaController.java
index 13dd70f..40255cb 100644
--- a/src/main/java/com/ruoyi/project/common/CaptchaController.java
+++ b/src/main/java/com/ruoyi/project/common/CaptchaController.java
@@ -1,16 +1,5 @@
 package com.ruoyi.project.common;
 
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-import javax.annotation.Resource;
-import javax.imageio.ImageIO;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.util.FastByteArrayOutputStream;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.google.code.kaptcha.Producer;
 import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.constant.Constants;
@@ -19,6 +8,18 @@
 import com.ruoyi.framework.redis.RedisCache;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.service.ISysConfigService;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.FastByteArrayOutputStream;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 楠岃瘉鐮佹搷浣滃鐞�
@@ -26,6 +27,7 @@
  * @author ruoyi
  */
 @RestController
+@RequiredArgsConstructor
 public class CaptchaController
 {
     @Resource(name = "captchaProducer")
@@ -34,15 +36,13 @@
     @Resource(name = "captchaProducerMath")
     private Producer captchaProducerMath;
 
-    @Autowired
-    private RedisCache redisCache;
+    private final RedisCache redisCache;
     
     // 楠岃瘉鐮佺被鍨�
     @Value("${ruoyi.captchaType}")
     private String captchaType;
     
-    @Autowired
-    private ISysConfigService configService;
+    private final ISysConfigService configService;
 
     /**
      * 鐢熸垚楠岃瘉鐮�
diff --git a/src/main/java/com/ruoyi/project/common/CommonController.java b/src/main/java/com/ruoyi/project/common/CommonController.java
index 21fa5ec..093e132 100644
--- a/src/main/java/com/ruoyi/project/common/CommonController.java
+++ b/src/main/java/com/ruoyi/project/common/CommonController.java
@@ -1,183 +1,97 @@
 package com.ruoyi.project.common;
 
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import com.ruoyi.basic.service.StorageBlobService;
+import com.ruoyi.basic.utils.FileUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
 import com.ruoyi.framework.web.domain.R;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.ContentDisposition;
 import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.file.FileUploadUtils;
-import com.ruoyi.common.utils.file.FileUtils;
-import com.ruoyi.framework.config.RuoYiConfig;
-import com.ruoyi.framework.config.ServerConfig;
-import com.ruoyi.framework.web.domain.AjaxResult;
+
+import java.io.File;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.List;
 
 /**
  * 閫氱敤璇锋眰澶勭悊
- * 
+ *
  * @author ruoyi
  */
-@Api(tags = "閫氱敤鎺ュ彛")
+@Tag(name = "閫氱敤鎺ュ彛")
+@AllArgsConstructor
 @RestController
 @RequestMapping("/common")
-public class CommonController
-{
-    private static final Logger log = LoggerFactory.getLogger(CommonController.class);
-
-    @Autowired
-    private ServerConfig serverConfig;
-
-    private static final String FILE_DELIMETER = ",";
-
-    /**
-     * 閫氱敤涓嬭浇璇锋眰
-     * 
-     * @param fileName 鏂囦欢鍚嶇О
-     * @param delete 鏄惁鍒犻櫎
-     */
-    @GetMapping("/download")
-    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(fileName))
-            {
-                throw new Exception(StringUtils.format("鏂囦欢鍚嶇О({})闈炴硶锛屼笉鍏佽涓嬭浇銆� ", fileName));
-            }
-            String realFileName =  fileName.substring(fileName.indexOf("_") + 1);
-
-            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
-            FileUtils.setAttachmentResponseHeader(response, realFileName);
-            FileUtils.writeBytes(fileName, response.getOutputStream());
-//            if (delete)
-//            {
-//                FileUtils.deleteFile(fileName);
-//            }
-        }
-        catch (Exception e)
-        {
-            log.error("涓嬭浇鏂囦欢澶辫触", e);
-        }
-    }
-
-    @Autowired
-    private StorageBlobService storageBlobService;
+public class CommonController {
 
 
-    /**
-     * minio閫氱敤涓婁紶璇锋眰锛堝涓級
-     */
-    @PostMapping("/minioUploads")
-    @ApiOperation(value = "minio閫氱敤涓婁紶璇锋眰")
-    public AjaxResult minioUploadFiles(List<MultipartFile> files, String bucketName, Long type) throws Exception
-    {
-        return AjaxResult.success(storageBlobService.updateStorageBlobs(files, bucketName,type));
+    private final StorageBlobService storageBlobService;
+    private final FileUtil fileUtil;
+
+    @PostMapping({"/upload"})
+    @Operation(summary = "鏂囦欢涓婁紶")
+    public R upload(@RequestParam("files") List<MultipartFile> files) {
+        return R.ok(storageBlobService.upload(files, false));
     }
 
     /**
-     * 閫氱敤涓婁紶璇锋眰锛堝崟涓級
+     * 鍏叡鏂囦欢涓婁紶
+     * 姝ゆ帴鍙d笂浼犵殑鏂囦欢姘镐箙鏈夋晥锛屾厧鐢�
      */
-    @PostMapping("/upload")
-    public AjaxResult uploadFile(MultipartFile file) throws Exception
-    {
-        try
-        {
-            // 涓婁紶鏂囦欢璺緞
-            String filePath = RuoYiConfig.getUploadPath();
-            // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
-            String fileName = FileUploadUtils.upload(filePath, file);
-            String url = serverConfig.getUrl() + fileName;
-            AjaxResult ajax = AjaxResult.success();
-            ajax.put("url", url);
-            ajax.put("fileName", fileName);
-            ajax.put("newFileName", FileUtils.getName(fileName));
-            ajax.put("originalFilename", file.getOriginalFilename());
-            return ajax;
-        }
-        catch (Exception e)
-        {
-            return AjaxResult.error(e.getMessage());
-        }
+    @PostMapping({"/public/upload"})
+    @Operation(summary = "鏂囦欢涓婁紶")
+    public R publicUpload(@RequestParam("files") List<MultipartFile> files) {
+        return R.ok(storageBlobService.upload(files, true));
     }
 
-    /**
-     * 閫氱敤涓婁紶璇锋眰锛堝涓級
-     */
-    @PostMapping("/uploads")
-    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
-    {
-        try
-        {
-            // 涓婁紶鏂囦欢璺緞
-            String filePath = RuoYiConfig.getUploadPath();
-            List<String> urls = new ArrayList<String>();
-            List<String> fileNames = new ArrayList<String>();
-            List<String> newFileNames = new ArrayList<String>();
-            List<String> originalFilenames = new ArrayList<String>();
-            for (MultipartFile file : files)
-            {
-                // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
-                String fileName = FileUploadUtils.upload(filePath, file);
-                String url = serverConfig.getUrl() + fileName;
-                urls.add(url);
-                fileNames.add(fileName);
-                newFileNames.add(FileUtils.getName(fileName));
-                originalFilenames.add(file.getOriginalFilename());
-            }
-            AjaxResult ajax = AjaxResult.success();
-            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
-            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
-            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
-            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
-            return ajax;
+    @GetMapping("/download/{fileName}")
+    @Anonymous
+    public void download(@PathVariable String fileName,
+                         @RequestParam(value = "token", required = false) String token,
+                         @RequestParam(value = "publicKey", required = false) String publicKey,
+                         HttpServletResponse response) throws Exception {
+        File file;
+        if (publicKey != null) {
+            file = fileUtil.compressFile(storageBlobService.getPublicFile(fileName, publicKey));
+        } else {
+            file = fileUtil.compressFile(storageBlobService.getFileByToken(fileName, token));
         }
-        catch (Exception e)
-        {
-            return AjaxResult.error(e.getMessage());
-        }
+        String originalFileName = storageBlobService.getDownloadFileName(fileName);
+        String encodedFileName = URLEncoder.encode(originalFileName, StandardCharsets.UTF_8.name()).replace("+", "%20");
+        response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName);
+        response.setContentLengthLong(file.length());
+        Files.copy(file.toPath(), response.getOutputStream());
     }
 
-    /**
-     * 鏈湴璧勬簮閫氱敤涓嬭浇
-     */
-    @GetMapping("/download/resource")
-    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
-            throws Exception
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(resource))
-            {
-                throw new Exception(StringUtils.format("璧勬簮鏂囦欢({})闈炴硶锛屼笉鍏佽涓嬭浇銆� ", resource));
-            }
-            // 鏈湴璧勬簮璺緞
-            String localPath = RuoYiConfig.getProfile();
-            // 鏁版嵁搴撹祫婧愬湴鍧�
-            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
-            // 涓嬭浇鍚嶇О
-            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
-            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
-            FileUtils.setAttachmentResponseHeader(response, downloadName);
-            FileUtils.writeBytes(downloadPath, response.getOutputStream());
+    @GetMapping("/preview/{fileName}")
+    @Anonymous
+    public ResponseEntity<FileSystemResource> preview(@PathVariable String fileName,
+                                                      @RequestParam(value = "token", required = false) String token,
+                                                      @RequestParam(value = "publicKey", required = false) String publicKey) throws Exception {
+        File file;
+        if (publicKey != null) {
+            file = fileUtil.compressFile(storageBlobService.getPublicFile(fileName, publicKey));
+        } else {
+            file = fileUtil.compressFile(storageBlobService.getFileByToken(fileName, token));
         }
-        catch (Exception e)
-        {
-            log.error("涓嬭浇鏂囦欢澶辫触", e);
-        }
+        String contentType = Files.probeContentType(file.toPath());
+
+        ContentDisposition contentDisposition = ContentDisposition.inline()
+                .filename(fileName, StandardCharsets.UTF_8)
+                .build();
+
+        return ResponseEntity.ok()
+                .contentType(MediaType.parseMediaType(contentType != null ? contentType : "application/octet-stream"))
+                .contentLength(file.length())
+                .header("Content-Disposition", contentDisposition.toString())
+                .body(new FileSystemResource(file));
     }
 }
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java b/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java
index 748f1b8..63fe76b 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/CacheController.java
@@ -1,26 +1,16 @@
 package com.ruoyi.project.monitor.controller;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.RedisCallback;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.monitor.domain.SysCache;
+import lombok.AllArgsConstructor;
+import org.springframework.data.redis.core.RedisCallback;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
 
 /**
  * 缂撳瓨鐩戞帶
@@ -29,9 +19,9 @@
  */
 @RestController
 @RequestMapping("/monitor/cache")
+@AllArgsConstructor
 public class CacheController
 {
-    @Autowired
     private RedisTemplate<String, String> redisTemplate;
 
     private final static List<SysCache> caches = new ArrayList<SysCache>();
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java
index fd1b258..ee2c058 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java
@@ -1,7 +1,8 @@
 package com.ruoyi.project.monitor.controller;
 
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.quartz.SchedulerException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -34,9 +35,9 @@
  */
 @RestController
 @RequestMapping("/monitor/job")
+@AllArgsConstructor
 public class SysJobController extends BaseController
 {
-    @Autowired
     private ISysJobService jobService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java
index 0a716ab..0c29d22 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java
@@ -1,7 +1,8 @@
 package com.ruoyi.project.monitor.controller;
 
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -26,9 +27,9 @@
  */
 @RestController
 @RequestMapping("/monitor/jobLog")
+@AllArgsConstructor
 public class SysJobLogController extends BaseController
 {
-    @Autowired
     private ISysJobLogService jobLogService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java
index d49efa2..7f5085d 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java
@@ -1,15 +1,5 @@
 package com.ruoyi.project.monitor.controller;
 
-import java.util.List;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -19,26 +9,28 @@
 import com.ruoyi.framework.web.page.TableDataInfo;
 import com.ruoyi.project.monitor.domain.SysLogininfor;
 import com.ruoyi.project.monitor.service.ISysLogininforService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
 
 /**
  * 绯荤粺璁块棶璁板綍
- * 
+ *
  * @author ruoyi
  */
 @RestController
 @RequestMapping("/monitor/logininfor")
-public class SysLogininforController extends BaseController
-{
-    @Autowired
+@AllArgsConstructor
+public class SysLogininforController extends BaseController {
     private ISysLogininforService logininforService;
-
-    @Autowired
     private SysPasswordService passwordService;
 
     @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
     @GetMapping("/list")
-    public TableDataInfo list(SysLogininfor logininfor)
-    {
+    public TableDataInfo list(SysLogininfor logininfor) {
         startPage();
         List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
         return getDataTable(list);
@@ -47,8 +39,7 @@
     @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
     @PostMapping("/export")
-    public void export(HttpServletResponse response, SysLogininfor logininfor)
-    {
+    public void export(HttpServletResponse response, SysLogininfor logininfor) {
         List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
         ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
         util.exportExcel(response, list, "鐧诲綍鏃ュ織");
@@ -57,16 +48,14 @@
     @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
     @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.DELETE)
     @DeleteMapping("/{infoIds}")
-    public AjaxResult remove(@PathVariable Long[] infoIds)
-    {
+    public AjaxResult remove(@PathVariable Long[] infoIds) {
         return toAjax(logininforService.deleteLogininforByIds(infoIds));
     }
 
     @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
     @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.CLEAN)
     @DeleteMapping("/clean")
-    public AjaxResult clean()
-    {
+    public AjaxResult clean() {
         logininforService.cleanLogininfor();
         return success();
     }
@@ -74,8 +63,7 @@
     @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
     @Log(title = "璐︽埛瑙i攣", businessType = BusinessType.OTHER)
     @GetMapping("/unlock/{userName}")
-    public AjaxResult unlock(@PathVariable("userName") String userName)
-    {
+    public AjaxResult unlock(@PathVariable("userName") String userName) {
         passwordService.clearLoginRecordCache(userName);
         return success();
     }
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java
index 43cc698..81bab02 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java
@@ -1,7 +1,8 @@
 package com.ruoyi.project.monitor.controller;
 
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -26,9 +27,9 @@
  */
 @RestController
 @RequestMapping("/monitor/operlog")
+@AllArgsConstructor
 public class SysOperlogController extends BaseController
 {
-    @Autowired
     private ISysOperLogService operLogService;
 
     @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
diff --git a/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java b/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java
index 763c141..aa8c824 100644
--- a/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java
+++ b/src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java
@@ -4,6 +4,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -30,12 +32,10 @@
  */
 @RestController
 @RequestMapping("/monitor/online")
+@AllArgsConstructor
 public class SysUserOnlineController extends BaseController
 {
-    @Autowired
     private ISysUserOnlineService userOnlineService;
-
-    @Autowired
     private RedisCache redisCache;
 
     @PreAuthorize("@ss.hasPermi('monitor:online:list')")
diff --git a/src/main/java/com/ruoyi/project/monitor/domain/SysJob.java b/src/main/java/com/ruoyi/project/monitor/domain/SysJob.java
index e45f42e..56f30b8 100644
--- a/src/main/java/com/ruoyi/project/monitor/domain/SysJob.java
+++ b/src/main/java/com/ruoyi/project/monitor/domain/SysJob.java
@@ -1,8 +1,8 @@
 package com.ruoyi.project.monitor.domain;
 
 import java.util.Date;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.fasterxml.jackson.annotation.JsonFormat;
diff --git a/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java
index 14c88d5..5457fce 100644
--- a/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java
@@ -1,11 +1,12 @@
 package com.ruoyi.project.monitor.service.impl;
 
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.project.monitor.domain.SysJobLog;
 import com.ruoyi.project.monitor.mapper.SysJobLogMapper;
 import com.ruoyi.project.monitor.service.ISysJobLogService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 瀹氭椂浠诲姟璋冨害鏃ュ織淇℃伅 鏈嶅姟灞�
@@ -13,10 +14,10 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysJobLogServiceImpl implements ISysJobLogService
 {
-    @Autowired
-    private SysJobLogMapper jobLogMapper;
+    private final SysJobLogMapper jobLogMapper;
 
     /**
      * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
diff --git a/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java
index 2db6b22..6780e8b 100644
--- a/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java
@@ -1,14 +1,5 @@
 package com.ruoyi.project.monitor.service.impl;
 
-import java.util.List;
-import javax.annotation.PostConstruct;
-import org.quartz.JobDataMap;
-import org.quartz.JobKey;
-import org.quartz.Scheduler;
-import org.quartz.SchedulerException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import com.ruoyi.common.constant.ScheduleConstants;
 import com.ruoyi.common.exception.job.TaskException;
 import com.ruoyi.common.utils.job.CronUtils;
@@ -16,6 +7,16 @@
 import com.ruoyi.project.monitor.domain.SysJob;
 import com.ruoyi.project.monitor.mapper.SysJobMapper;
 import com.ruoyi.project.monitor.service.ISysJobService;
+import jakarta.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
+import org.quartz.JobDataMap;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
 
 /**
  * 瀹氭椂浠诲姟璋冨害淇℃伅 鏈嶅姟灞�
@@ -23,13 +24,12 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysJobServiceImpl implements ISysJobService
 {
-    @Autowired
-    private Scheduler scheduler;
+    private final Scheduler scheduler;
 
-    @Autowired
-    private SysJobMapper jobMapper;
+    private final SysJobMapper jobMapper;
 
     /**
      * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧畾鏃跺櫒 涓昏鏄槻姝㈡墜鍔ㄤ慨鏀规暟鎹簱瀵艰嚧鏈悓姝ュ埌瀹氭椂浠诲姟澶勭悊锛堟敞锛氫笉鑳芥墜鍔ㄤ慨鏀规暟鎹簱ID鍜屼换鍔$粍鍚嶏紝鍚﹀垯浼氬鑷磋剰鏁版嵁锛�
diff --git a/src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java
index 4a50410..50b841c 100644
--- a/src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java
@@ -1,11 +1,12 @@
 package com.ruoyi.project.monitor.service.impl;
 
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.project.monitor.domain.SysLogininfor;
 import com.ruoyi.project.monitor.mapper.SysLogininforMapper;
 import com.ruoyi.project.monitor.service.ISysLogininforService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞傚鐞�
@@ -13,11 +14,11 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysLogininforServiceImpl implements ISysLogininforService
 {
 
-    @Autowired
-    private SysLogininforMapper logininforMapper;
+    private final SysLogininforMapper logininforMapper;
 
     /**
      * 鏂板绯荤粺鐧诲綍鏃ュ織
diff --git a/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java b/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java
index 954bc08..487bf4f 100644
--- a/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java
@@ -1,11 +1,12 @@
 package com.ruoyi.project.monitor.service.impl;
 
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.project.monitor.domain.SysOperLog;
 import com.ruoyi.project.monitor.mapper.SysOperLogMapper;
 import com.ruoyi.project.monitor.service.ISysOperLogService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 鎿嶄綔鏃ュ織 鏈嶅姟灞傚鐞�
@@ -13,10 +14,10 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysOperLogServiceImpl implements ISysOperLogService
 {
-    @Autowired
-    private SysOperLogMapper operLogMapper;
+    private final SysOperLogMapper operLogMapper;
 
     /**
      * 鏂板鎿嶄綔鏃ュ織
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java b/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
index 6a7cd7e..a10687b 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysConfigController.java
@@ -1,18 +1,5 @@
 package com.ruoyi.project.system.controller;
 
-import java.util.List;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -21,6 +8,13 @@
 import com.ruoyi.framework.web.page.TableDataInfo;
 import com.ruoyi.project.system.domain.SysConfig;
 import com.ruoyi.project.system.service.ISysConfigService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
 
 /**
  * 鍙傛暟閰嶇疆 淇℃伅鎿嶄綔澶勭悊
@@ -29,9 +23,9 @@
  */
 @RestController
 @RequestMapping("/system/config")
+@AllArgsConstructor
 public class SysConfigController extends BaseController
 {
-    @Autowired
     private ISysConfigService configService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java b/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
index 0a48efe..f61e42f 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
@@ -1,6 +1,8 @@
 package com.ruoyi.project.system.controller;
 
 import java.util.List;
+
+import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -29,9 +31,9 @@
  */
 @RestController
 @RequestMapping("/system/dept")
+@AllArgsConstructor
 public class SysDeptController extends BaseController
 {
-    @Autowired
     private ISysDeptService deptService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java b/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
index 0dc5768..58cb4c1 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java
@@ -2,7 +2,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -32,12 +33,10 @@
  */
 @RestController
 @RequestMapping("/system/dict/data")
+@AllArgsConstructor
 public class SysDictDataController extends BaseController
 {
-    @Autowired
     private ISysDictDataService dictDataService;
-
-    @Autowired
     private ISysDictTypeService dictTypeService;
 
     @PreAuthorize("@ss.hasPermi('system:dict:list')")
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java b/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
index 5fb602e..f1a026f 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java
@@ -1,7 +1,8 @@
 package com.ruoyi.project.system.controller;
 
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -29,9 +30,9 @@
  */
 @RestController
 @RequestMapping("/system/dict/type")
+@AllArgsConstructor
 public class SysDictTypeController extends BaseController
 {
-    @Autowired
     private ISysDictTypeService dictTypeService;
 
     @PreAuthorize("@ss.hasPermi('system:dict:list')")
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysIndexController.java b/src/main/java/com/ruoyi/project/system/controller/SysIndexController.java
index 0837663..9a98588 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysIndexController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysIndexController.java
@@ -1,5 +1,6 @@
 package com.ruoyi.project.system.controller;
 
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -12,10 +13,10 @@
  * @author ruoyi
  */
 @RestController
+@AllArgsConstructor
 public class SysIndexController
 {
     /** 绯荤粺鍩虹閰嶇疆 */
-    @Autowired
     private RuoYiConfig ruoyiConfig;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java b/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
index b165f3e..e08c368 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
@@ -1,18 +1,5 @@
 package com.ruoyi.project.system.controller;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.ruoyi.project.system.domain.SysDept;
-import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
-import com.ruoyi.project.system.mapper.SysDeptMapper;
-import com.ruoyi.project.system.service.ISysUserDeptService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.ObjectUtils;
-import org.springframework.web.bind.annotation.*;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.framework.security.LoginBody;
@@ -21,9 +8,27 @@
 import com.ruoyi.framework.security.service.SysPermissionService;
 import com.ruoyi.framework.security.service.TokenService;
 import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.domain.SysMenu;
 import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.service.ISysMenuService;
+import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.service.ISysMenuService;
+import com.ruoyi.project.system.service.ISysUserDeptService;
+import com.ruoyi.project.system.service.ISysUserService;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * 鐧诲綍楠岃瘉
@@ -31,25 +36,16 @@
  * @author ruoyi
  */
 @RestController
+@AllArgsConstructor
 public class SysLoginController
 {
-    @Autowired
     private SysLoginService loginService;
-
-    @Autowired
     private ISysMenuService menuService;
-
-    @Autowired
-    private SysPermissionService permissionService;
-
-    @Autowired
-    private TokenService tokenService;
-
-    @Autowired
-    private ISysUserDeptService userDeptService;
-
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
+    private SysPermissionService permissionService;
+    private TokenService tokenService;
+    private ISysUserDeptService userDeptService;
+    private ISysUserService userService;
+    private SysDeptMapper sysDeptMapper;
 
     /**
      * 鐧诲綍鏂规硶
@@ -77,7 +73,17 @@
     public AjaxResult getInfo()
     {
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        SysUser user = loginUser.getUser();
+        SysUser user = userService.selectUserById(loginUser.getUserId());
+        if (user == null)
+        {
+            user = loginUser.getUser();
+        }
+        else
+        {
+            loginUser.setUser(user);
+            loginUser.setAiEnabled(user.getAiEnabled());
+            tokenService.setLoginUser(loginUser);
+        }
         // 鑾峰彇褰撳墠鐧诲綍鍏徃
         Long tenantId = loginUser.getTenantId();
         if(null != tenantId){
@@ -96,11 +102,12 @@
             loginUser.setPermissions(permissions);
             tokenService.refreshToken(loginUser);
         }
-        AjaxResult ajax = AjaxResult.success();
-        ajax.put("user", user);
-        ajax.put("roles", roles);
-        ajax.put("permissions", permissions);
-        return ajax;
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("user", user);
+        ajax.put("aiEnabled", loginUser.getAiEnabled());
+        ajax.put("roles", roles);
+        ajax.put("permissions", permissions);
+        return ajax;
     }
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java b/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java
index 4f3af2e..865e8a4 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysMenuController.java
@@ -1,17 +1,5 @@
 package com.ruoyi.project.system.controller;
 
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
@@ -20,6 +8,12 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.domain.SysMenu;
 import com.ruoyi.project.system.service.ISysMenuService;
+import lombok.AllArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
 
 /**
  * 鑿滃崟淇℃伅
@@ -28,9 +22,9 @@
  */
 @RestController
 @RequestMapping("/system/menu")
+@AllArgsConstructor
 public class SysMenuController extends BaseController
 {
-    @Autowired
     private ISysMenuService menuService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java b/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java
index 5f856f1..5aa3413 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java
@@ -5,7 +5,8 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -25,17 +26,15 @@
  */
 @RestController
 @RequestMapping("/system/notice")
-public class SysNoticeController extends BaseController
-{
-    @Autowired
+@AllArgsConstructor
+public class SysNoticeController extends BaseController {
     private ISysNoticeService noticeService;
 
     /**
      * 鑾峰彇閫氱煡鍏憡鍒楄〃
      */
     @GetMapping("/list")
-    public R<IPage<SysNotice>> list(SysNotice notice, Page page)
-    {
+    public R<IPage<SysNotice>> list(SysNotice notice, Page page) {
         IPage<SysNotice> list = noticeService.selectNoticeList(notice, page);
         return R.ok(list);
     }
@@ -44,8 +43,7 @@
      * 鑾峰彇鏈鏁伴噺
      */
     @GetMapping("/getCount")
-    public R getCount(Long consigneeId)
-    {
+    public R getCount(Long consigneeId) {
         return R.ok(noticeService.getCount(consigneeId));
     }
 
@@ -53,8 +51,7 @@
      * 鏍规嵁閫氱煡鍏憡缂栧彿鑾峰彇璇︾粏淇℃伅
      */
     @GetMapping(value = "/{noticeId}")
-    public AjaxResult getInfo(@PathVariable Long noticeId)
-    {
+    public AjaxResult getInfo(@PathVariable Long noticeId) {
         return success(noticeService.selectNoticeById(noticeId));
     }
 
@@ -62,8 +59,7 @@
      * 鏂板閫氱煡鍏憡
      */
     @PostMapping
-    public AjaxResult add(@Validated @RequestBody SysNotice notice)
-    {
+    public AjaxResult add(@Validated @RequestBody SysNotice notice) {
         return toAjax(noticeService.insertNotice(notice));
     }
 
@@ -71,8 +67,7 @@
      * 淇敼閫氱煡鍏憡
      */
     @PutMapping
-    public AjaxResult edit(@Validated @RequestBody SysNotice notice)
-    {
+    public AjaxResult edit(@Validated @RequestBody SysNotice notice) {
         return toAjax(noticeService.updateNotice(notice));
     }
 
@@ -80,8 +75,7 @@
      * 鍒犻櫎閫氱煡鍏憡
      */
     @DeleteMapping("/{noticeIds}")
-    public AjaxResult remove(@PathVariable Long[] noticeIds)
-    {
+    public AjaxResult remove(@PathVariable Long[] noticeIds) {
         return toAjax(noticeService.deleteNoticeByIds(noticeIds));
     }
 
@@ -89,13 +83,12 @@
      * 涓�閿凡璇�
      */
     @PostMapping("/readAll")
-    public AjaxResult readAll()
-    {
+    public AjaxResult readAll() {
         return toAjax(noticeService.readAll());
     }
 
     @PostMapping("appReadNotice")
-    @ApiOperation("绉诲姩绔牴鎹秷鎭疘D杩涜宸茶")
+    @Operation(summary = "绉诲姩绔牴鎹秷鎭疘D杩涜宸茶")
     public AjaxResult appReadNotice(@RequestParam("noticeId") Long noticeId) {
         boolean result = noticeService.appReadNotice(noticeId);
         return toAjax(result);
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysPostController.java b/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
index a49692c..a4776c4 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysPostController.java
@@ -1,7 +1,8 @@
 package com.ruoyi.project.system.controller;
 
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -29,9 +30,9 @@
  */
 @RestController
 @RequestMapping("/system/post")
+@AllArgsConstructor
 public class SysPostController extends BaseController
 {
-    @Autowired
     private ISysPostService postService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java b/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java
index 7a6908a..62f6db5 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysProfileController.java
@@ -1,15 +1,5 @@
 package com.ruoyi.project.system.controller;
 
-import java.util.Map;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUploadUtils;
@@ -23,6 +13,11 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.service.ISysUserService;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Map;
 
 /**
  * 涓汉淇℃伅 涓氬姟澶勭悊
@@ -31,12 +26,10 @@
  */
 @RestController
 @RequestMapping("/system/user/profile")
+@AllArgsConstructor
 public class SysProfileController extends BaseController
 {
-    @Autowired
     private ISysUserService userService;
-
-    @Autowired
     private TokenService tokenService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java b/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java
index a3e23ae..ca7baf5 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java
@@ -1,35 +1,30 @@
 package com.ruoyi.project.system.controller;
 
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.security.RegisterBody;
 import com.ruoyi.framework.security.service.SysRegisterService;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.project.system.service.ISysConfigService;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  * 娉ㄥ唽楠岃瘉
- * 
+ *
  * @author ruoyi
  */
 @RestController
-public class SysRegisterController extends BaseController
-{
-    @Autowired
+@AllArgsConstructor
+public class SysRegisterController extends BaseController {
     private SysRegisterService registerService;
-
-    @Autowired
     private ISysConfigService configService;
 
     @PostMapping("/register")
-    public AjaxResult register(@RequestBody RegisterBody user)
-    {
-        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
-        {
+    public AjaxResult register(@RequestBody RegisterBody user) {
+        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) {
             return error("褰撳墠绯荤粺娌℃湁寮�鍚敞鍐屽姛鑳斤紒");
         }
         String msg = registerService.register(user);
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java b/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
index c3766bf..3b05811 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
@@ -1,7 +1,8 @@
 package com.ruoyi.project.system.controller;
 
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -38,21 +39,13 @@
  */
 @RestController
 @RequestMapping("/system/role")
+@AllArgsConstructor
 public class SysRoleController extends BaseController
 {
-    @Autowired
     private ISysRoleService roleService;
-
-    @Autowired
     private TokenService tokenService;
-
-    @Autowired
     private SysPermissionService permissionService;
-
-    @Autowired
     private ISysUserService userService;
-
-    @Autowired
     private ISysDeptService deptService;
 
     @PreAuthorize("@ss.hasPermi('system:role:list')")
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysUserClientController.java b/src/main/java/com/ruoyi/project/system/controller/SysUserClientController.java
index c05fa73..cb921a0 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysUserClientController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysUserClientController.java
@@ -7,8 +7,9 @@
 import com.ruoyi.project.system.domain.SysUserClient;
 import com.ruoyi.project.system.service.SysUserClientService;
 import com.ruoyi.common.utils.SecurityUtils;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -22,19 +23,19 @@
  * @version 1.0
  * @since 2026/2/9
  */
-@Api(tags = "鐢ㄦ埛璁惧缁戝畾")
+@Tag(name = "鐢ㄦ埛璁惧缁戝畾")
 @RestController
 @RequestMapping("/system/client")
+@AllArgsConstructor
 public class SysUserClientController extends BaseController {
 
-    @Autowired
     private SysUserClientService sysUserClientService;
 
     /**
      * 娣诲姞/鏇存柊鐢ㄦ埛cid
      */
     @PostMapping("/addOrUpdateClientId")
-    @ApiOperation("娣诲姞/鏇存柊鐢ㄦ埛cid")
+    @Operation(summary = "娣诲姞/鏇存柊鐢ㄦ埛cid")
     public AjaxResult addOrUpdateClientId(@RequestBody SysUserClient sysUserClient) {
         Long userId = SecurityUtils.getUserId();
         sysUserClient.setUserId(userId);
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java b/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
index 8b01634..332d6b5 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
@@ -2,11 +2,12 @@
 
 import java.util.List;
 import java.util.stream.Collectors;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.system.service.*;
+import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -39,21 +40,13 @@
  */
 @RestController
 @RequestMapping("/system/user")
+@AllArgsConstructor
 public class SysUserController extends BaseController
 {
-    @Autowired
     private ISysUserService userService;
-
-    @Autowired
     private ISysRoleService roleService;
-
-    @Autowired
     private ISysDeptService deptService;
-
-    @Autowired
     private ISysPostService postService;
-
-    @Autowired
     private ISysUserDeptService userDeptService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysConfig.java b/src/main/java/com/ruoyi/project/system/domain/SysConfig.java
index ba1c022..f7f69b3 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysConfig.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysConfig.java
@@ -1,7 +1,7 @@
 package com.ruoyi.project.system.domain;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysDept.java b/src/main/java/com/ruoyi/project/system/domain/SysDept.java
index 355618d..2c3056a 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysDept.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysDept.java
@@ -1,16 +1,16 @@
 package com.ruoyi.project.system.domain;
 
-import java.util.ArrayList;
-import java.util.List;
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.ruoyi.framework.web.domain.BaseEntity;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
-import com.ruoyi.framework.web.domain.BaseEntity;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * 閮ㄩ棬琛� sys_dept
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysDictData.java b/src/main/java/com/ruoyi/project/system/domain/SysDictData.java
index 7d72f89..8ae4cdb 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysDictData.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysDictData.java
@@ -1,7 +1,7 @@
 package com.ruoyi.project.system.domain;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.common.constant.UserConstants;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysDictType.java b/src/main/java/com/ruoyi/project/system/domain/SysDictType.java
index d81dfc9..9a523d6 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysDictType.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysDictType.java
@@ -1,8 +1,8 @@
 package com.ruoyi.project.system.domain;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Pattern;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysMenu.java b/src/main/java/com/ruoyi/project/system/domain/SysMenu.java
index 683bdab..d039ec8 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysMenu.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysMenu.java
@@ -2,9 +2,9 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.framework.web.domain.BaseEntity;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysNotice.java b/src/main/java/com/ruoyi/project/system/domain/SysNotice.java
index b88a57c..5e85478 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysNotice.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysNotice.java
@@ -1,7 +1,7 @@
 package com.ruoyi.project.system.domain;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysPost.java b/src/main/java/com/ruoyi/project/system/domain/SysPost.java
index e9b7ecd..fb0dde2 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysPost.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysPost.java
@@ -1,8 +1,8 @@
 package com.ruoyi.project.system.domain;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysRole.java b/src/main/java/com/ruoyi/project/system/domain/SysRole.java
index 67941af..cb8762a 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysRole.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysRole.java
@@ -1,9 +1,9 @@
 package com.ruoyi.project.system.domain;
 
 import java.util.Set;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysUser.java b/src/main/java/com/ruoyi/project/system/domain/SysUser.java
index ac7f535..515210e 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysUser.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysUser.java
@@ -1,18 +1,21 @@
 package com.ruoyi.project.system.domain;
 
-import java.util.Date;
-import java.util.List;
-import javax.validation.constraints.*;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-import com.ruoyi.common.xss.Xss;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.ruoyi.common.xss.Xss;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel.Type;
 import com.ruoyi.framework.aspectj.lang.annotation.Excels;
 import com.ruoyi.framework.web.domain.BaseEntity;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import jakarta.validation.constraints.Size;
+import java.util.Date;
+import java.util.List;
 
 /**
  * 鐢ㄦ埛瀵硅薄 sys_user
@@ -57,9 +60,13 @@
     @Excel(name = "璐﹀彿鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
     private String status;
 
-    /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
-    private String delFlag;
-
+    /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+    private String delFlag;
+
+    /** 鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級 */
+    @JsonIgnore
+    private Integer aiEnabled;
+
     /** 鏈�鍚庣櫥褰旾P */
     @Excel(name = "鏈�鍚庣櫥褰旾P", type = Type.EXPORT)
     private String loginIp;
@@ -248,15 +255,25 @@
         this.status = status;
     }
 
-    public String getDelFlag()
-    {
-        return delFlag;
-    }
+    public String getDelFlag()
+    {
+        return delFlag;
+    }
 
-    public void setDelFlag(String delFlag)
-    {
-        this.delFlag = delFlag;
-    }
+    public void setDelFlag(String delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Integer getAiEnabled()
+    {
+        return aiEnabled;
+    }
+
+    public void setAiEnabled(Integer aiEnabled)
+    {
+        this.aiEnabled = aiEnabled;
+    }
 
     public String getLoginIp()
     {
@@ -371,9 +388,10 @@
             .append("sex", getSex())
             .append("avatar", getAvatar())
             .append("password", getPassword())
-            .append("status", getStatus())
-            .append("delFlag", getDelFlag())
-            .append("loginIp", getLoginIp())
+            .append("status", getStatus())
+            .append("delFlag", getDelFlag())
+            .append("aiEnabled", getAiEnabled())
+            .append("loginIp", getLoginIp())
             .append("loginDate", getLoginDate())
             .append("createBy", getCreateBy())
             .append("createTime", getCreateTime())
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysUserDept.java b/src/main/java/com/ruoyi/project/system/domain/SysUserDept.java
index 8ca1d40..a254ca8 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysUserDept.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysUserDept.java
@@ -2,7 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -16,19 +16,19 @@
 
     private Long deptId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 }
diff --git a/src/main/java/com/ruoyi/project/system/domain/vo/SysUserDeptVo.java b/src/main/java/com/ruoyi/project/system/domain/vo/SysUserDeptVo.java
index 0bf2406..f416d39 100644
--- a/src/main/java/com/ruoyi/project/system/domain/vo/SysUserDeptVo.java
+++ b/src/main/java/com/ruoyi/project/system/domain/vo/SysUserDeptVo.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.ruoyi.project.system.domain.SysUserDept;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java
index 507159b..f61cf5a 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java
@@ -1,6 +1,8 @@
 package com.ruoyi.project.system.mapper;
 
 import java.util.List;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.project.system.domain.SysRole;
 
 /**
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java
index 0396057..cf198ce 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java
@@ -1,10 +1,5 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.Collection;
-import java.util.List;
-import javax.annotation.PostConstruct;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.common.constant.CacheConstants;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.text.Convert;
@@ -14,6 +9,12 @@
 import com.ruoyi.project.system.domain.SysConfig;
 import com.ruoyi.project.system.mapper.SysConfigMapper;
 import com.ruoyi.project.system.service.ISysConfigService;
+import jakarta.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
 
 /**
  * 鍙傛暟閰嶇疆 鏈嶅姟灞傚疄鐜�
@@ -21,13 +22,11 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysConfigServiceImpl implements ISysConfigService
 {
-    @Autowired
-    private SysConfigMapper configMapper;
-
-    @Autowired
-    private RedisCache redisCache;
+    private final SysConfigMapper configMapper;
+    private final RedisCache redisCache;
 
     /**
      * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧弬鏁板埌缂撳瓨
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java
index eae688f..65f4705 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java
@@ -1,11 +1,5 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.stream.Collectors;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.exception.ServiceException;
@@ -20,6 +14,13 @@
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.mapper.SysRoleMapper;
 import com.ruoyi.project.system.service.ISysDeptService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 閮ㄩ棬绠$悊 鏈嶅姟瀹炵幇
@@ -27,13 +28,11 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysDeptServiceImpl implements ISysDeptService
 {
-    @Autowired
-    private SysDeptMapper deptMapper;
-    
-    @Autowired
-    private SysRoleMapper roleMapper;
+    private final SysDeptMapper deptMapper;
+    private final SysRoleMapper roleMapper;
 
     /**
      * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java
index 8a33773..d82dd46 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java
@@ -1,12 +1,13 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.common.utils.DictUtils;
 import com.ruoyi.project.system.domain.SysDictData;
 import com.ruoyi.project.system.mapper.SysDictDataMapper;
 import com.ruoyi.project.system.service.ISysDictDataService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 瀛楀吀 涓氬姟灞傚鐞�
@@ -14,10 +15,10 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysDictDataServiceImpl implements ISysDictDataService
 {
-    @Autowired
-    private SysDictDataMapper dictDataMapper;
+    private final SysDictDataMapper dictDataMapper;
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java
index 8dce677..883e225 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java
@@ -1,13 +1,5 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import javax.annotation.PostConstruct;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DictUtils;
@@ -17,6 +9,15 @@
 import com.ruoyi.project.system.mapper.SysDictDataMapper;
 import com.ruoyi.project.system.mapper.SysDictTypeMapper;
 import com.ruoyi.project.system.service.ISysDictTypeService;
+import jakarta.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 瀛楀吀 涓氬姟灞傚鐞�
@@ -24,13 +25,11 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysDictTypeServiceImpl implements ISysDictTypeService
 {
-    @Autowired
-    private SysDictTypeMapper dictTypeMapper;
-
-    @Autowired
-    private SysDictDataMapper dictDataMapper;
+    private final SysDictTypeMapper dictTypeMapper;
+    private final SysDictDataMapper dictDataMapper;
 
     /**
      * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧瓧鍏稿埌缂撳瓨
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
index db14845..f729ddc 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
@@ -1,15 +1,5 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.utils.SecurityUtils;
@@ -24,6 +14,11 @@
 import com.ruoyi.project.system.mapper.SysRoleMapper;
 import com.ruoyi.project.system.mapper.SysRoleMenuMapper;
 import com.ruoyi.project.system.service.ISysMenuService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 鑿滃崟 涓氬姟灞傚鐞�
@@ -31,18 +26,14 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysMenuServiceImpl implements ISysMenuService
 {
     public static final String PREMISSION_STRING = "perms[\"{0}\"]";
 
-    @Autowired
-    private SysMenuMapper menuMapper;
-
-    @Autowired
-    private SysRoleMapper roleMapper;
-
-    @Autowired
-    private SysRoleMenuMapper roleMenuMapper;
+    private final SysMenuMapper menuMapper;
+    private final SysRoleMapper roleMapper;
+    private final SysRoleMenuMapper roleMenuMapper;
 
     /**
      * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
index 28ec77c..dcbcded 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
@@ -1,34 +1,25 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.github.xiaoymin.knife4j.core.util.StrUtil;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysNotice;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.domain.SysUserDept;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.mapper.SysNoticeMapper;
 import com.ruoyi.project.system.mapper.SysUserDeptMapper;
 import com.ruoyi.project.system.mapper.SysUserMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Service;
-import com.ruoyi.project.system.domain.SysNotice;
-import com.ruoyi.project.system.mapper.SysNoticeMapper;
 import com.ruoyi.project.system.service.ISysNoticeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 鍏憡 鏈嶅姟灞傚疄鐜�
@@ -36,26 +27,14 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysNoticeServiceImpl  extends ServiceImpl<SysNoticeMapper, SysNotice> implements ISysNoticeService {
 
-    @Autowired
-    private SysNoticeMapper noticeMapper;
-
-    @Autowired
-    private SysUserMapper userMapper;
-
-    @Autowired
-    private SysDeptMapper deptMapper;
-
-    @Autowired
-    private SysUserDeptMapper userDeptMapper;
-
-    @Autowired
-    @Lazy
-    private ISysNoticeService sysNoticeService;
-
-    @Autowired
-    private UnipushService unipushService;
+    private final SysNoticeMapper noticeMapper;
+    private final SysUserMapper userMapper;
+    private final SysDeptMapper deptMapper;
+    private final SysUserDeptMapper userDeptMapper;
+    private final UnipushService unipushService;
 
     /**
      * 鏌ヨ鍏憡淇℃伅
@@ -151,7 +130,7 @@
         List<SysNotice> sysNotices = consigneeId.stream()
                 .map(it -> convertSysNotice(title, message, it, tenantId, jumpPath, unipushService.convertWebPathToAppPath(jumpPath), userId))
                 .collect(Collectors.toList());
-        sysNoticeService.saveBatch(sysNotices);
+        noticeMapper.insert(sysNotices);
         try {
             unipushService.sendClientMessage(sysNotices);
         } catch (Exception e) {
@@ -207,8 +186,7 @@
                         userId
                 ))
                 .collect(Collectors.toList());
-
-        sysNoticeService.saveBatch(collect);
+        noticeMapper.insert(collect);
         try {
             unipushService.sendClientMessage(collect);
         } catch (Exception e) {
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java
index 5501e27..2282c3f 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java
@@ -1,8 +1,5 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.StringUtils;
@@ -10,6 +7,10 @@
 import com.ruoyi.project.system.mapper.SysPostMapper;
 import com.ruoyi.project.system.mapper.SysUserPostMapper;
 import com.ruoyi.project.system.service.ISysPostService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 宀椾綅淇℃伅 鏈嶅姟灞傚鐞�
@@ -17,13 +18,11 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysPostServiceImpl implements ISysPostService
 {
-    @Autowired
-    private SysPostMapper postMapper;
-
-    @Autowired
-    private SysUserPostMapper userPostMapper;
+    private final SysPostMapper postMapper;
+    private final SysUserPostMapper userPostMapper;
 
     /**
      * 鏌ヨ宀椾綅淇℃伅闆嗗悎
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java
index 1fe2055..76fe605 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java
@@ -1,29 +1,22 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
-import com.ruoyi.project.system.domain.SysRole;
-import com.ruoyi.project.system.domain.SysRoleDept;
-import com.ruoyi.project.system.domain.SysRoleMenu;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.domain.SysUserRole;
+import com.ruoyi.project.system.domain.*;
 import com.ruoyi.project.system.mapper.SysRoleDeptMapper;
 import com.ruoyi.project.system.mapper.SysRoleMapper;
 import com.ruoyi.project.system.mapper.SysRoleMenuMapper;
 import com.ruoyi.project.system.mapper.SysUserRoleMapper;
 import com.ruoyi.project.system.service.ISysRoleService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
 
 /**
  * 瑙掕壊 涓氬姟灞傚鐞�
@@ -31,19 +24,13 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysRoleServiceImpl implements ISysRoleService
 {
-    @Autowired
-    private SysRoleMapper roleMapper;
-
-    @Autowired
-    private SysRoleMenuMapper roleMenuMapper;
-
-    @Autowired
-    private SysUserRoleMapper userRoleMapper;
-
-    @Autowired
-    private SysRoleDeptMapper roleDeptMapper;
+    private final SysRoleMapper roleMapper;
+    private final SysRoleMenuMapper roleMenuMapper;
+    private final SysUserRoleMapper userRoleMapper;
+    private final SysRoleDeptMapper roleDeptMapper;
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysUserDeptServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysUserDeptServiceImpl.java
index 97be11b..71ea511 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysUserDeptServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysUserDeptServiceImpl.java
@@ -3,16 +3,16 @@
 import com.ruoyi.project.system.domain.vo.SysUserDeptVo;
 import com.ruoyi.project.system.mapper.SysUserDeptMapper;
 import com.ruoyi.project.system.service.ISysUserDeptService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
 
 @Service
+@RequiredArgsConstructor
 public class SysUserDeptServiceImpl implements ISysUserDeptService {
 
-    @Autowired
-    private SysUserDeptMapper sysUserDeptMapper;
+    private final SysUserDeptMapper sysUserDeptMapper;
 
     @Override
     public List<SysUserDeptVo> userLoginFacotryList(SysUserDeptVo userDeptVo) {
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
index 7773825..39f7234 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
@@ -1,22 +1,6 @@
 package com.ruoyi.project.system.service.impl;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import javax.validation.Validator;
-
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.ruoyi.project.system.domain.*;
-import com.ruoyi.project.system.mapper.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.SecurityUtils;
@@ -24,9 +8,21 @@
 import com.ruoyi.common.utils.bean.BeanValidators;
 import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
+import com.ruoyi.project.system.domain.*;
+import com.ruoyi.project.system.mapper.*;
 import com.ruoyi.project.system.service.ISysConfigService;
-import com.ruoyi.project.system.service.ISysDeptService;
 import com.ruoyi.project.system.service.ISysUserService;
+import jakarta.validation.Validator;
+import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 鐢ㄦ埛 涓氬姟灞傚鐞�
@@ -34,36 +30,19 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class SysUserServiceImpl implements ISysUserService
 {
-    @Autowired
-    private SysUserDeptMapper sysUserDeptMapper;
-
     private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
 
-    @Autowired
-    private SysUserMapper userMapper;
-
-    @Autowired
-    private SysRoleMapper roleMapper;
-
-    @Autowired
-    private SysPostMapper postMapper;
-
-    @Autowired
-    private SysUserRoleMapper userRoleMapper;
-
-    @Autowired
-    private SysUserPostMapper userPostMapper;
-
-    @Autowired
-    private ISysConfigService configService;
-
-    @Autowired
-    private ISysDeptService deptService;
-
-    @Autowired
-    protected Validator validator;
+    private final SysUserDeptMapper sysUserDeptMapper;
+    private final SysUserMapper userMapper;
+    private final SysRoleMapper roleMapper;
+    private final SysPostMapper postMapper;
+    private final SysUserRoleMapper userRoleMapper;
+    private final SysUserPostMapper userPostMapper;
+    private final ISysConfigService configService;
+    protected final Validator validator;
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/UnipushService.java b/src/main/java/com/ruoyi/project/system/service/impl/UnipushService.java
index a6e97f4..c331756 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/UnipushService.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/UnipushService.java
@@ -19,13 +19,13 @@
 import com.ruoyi.project.system.domain.SysUserClient;
 import com.ruoyi.project.system.mapper.SysMenuMapper;
 import com.ruoyi.project.system.service.SysUserClientService;
+import jakarta.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.PostConstruct;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -39,16 +39,12 @@
  */
 @Slf4j
 @Component
+@RequiredArgsConstructor
 public class UnipushService {
 
-    @Autowired
-    private SysMenuMapper sysMenuMapper;
-
-    @Autowired
-    private GetuiConfig getuiConfig;
-
-    @Autowired
-    private SysUserClientService userClientService;
+    private final SysMenuMapper sysMenuMapper;
+    private final GetuiConfig getuiConfig;
+    private final SysUserClientService userClientService;
 
     private PushApi pushApi;
 
@@ -140,7 +136,7 @@
     /**
      * 鍙戦�佸洖璁挎彁閱�
      */
-    public void sendReturnVisitReminder(Long returnVisitId, String cid, String content, Integer customerId) {
+    public void sendReturnVisitReminder(Long returnVisitId, String cid, String content, Long customerId) {
         String targetPath = "pages/cooperativeOffice/customerManage/detail?customerId=" + customerId;
         sendRoutingPush(returnVisitId, cid, "瀹㈡埛鍥炶鎻愰啋", content, targetPath, false);
     }
diff --git a/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java b/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java
index 93f4956..ec16cea 100644
--- a/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java
+++ b/src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java
@@ -1,23 +1,5 @@
 package com.ruoyi.project.tool.gen.controller;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.io.IOUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.alibaba.druid.DbType;
 import com.alibaba.druid.sql.SQLUtils;
 import com.alibaba.druid.sql.ast.SQLStatement;
@@ -35,6 +17,18 @@
 import com.ruoyi.project.tool.gen.domain.GenTableColumn;
 import com.ruoyi.project.tool.gen.service.IGenTableColumnService;
 import com.ruoyi.project.tool.gen.service.IGenTableService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import org.apache.commons.io.IOUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 浠g爜鐢熸垚 鎿嶄綔澶勭悊
@@ -43,12 +37,10 @@
  */
 @RestController
 @RequestMapping("/tool/gen")
+@AllArgsConstructor
 public class GenController extends BaseController
 {
-    @Autowired
     private IGenTableService genTableService;
-
-    @Autowired
     private IGenTableColumnService genTableColumnService;
 
     /**
diff --git a/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java b/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java
index 5cc81a0..7ed591b 100644
--- a/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java
+++ b/src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java
@@ -1,8 +1,8 @@
 package com.ruoyi.project.tool.gen.domain;
 
 import java.util.List;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
 import org.apache.commons.lang3.ArrayUtils;
 import com.ruoyi.common.constant.GenConstants;
 import com.ruoyi.common.utils.StringUtils;
diff --git a/src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java b/src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java
index e14d6e8..0fc104a 100644
--- a/src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java
+++ b/src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java
@@ -1,6 +1,6 @@
 package com.ruoyi.project.tool.gen.domain;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.web.domain.BaseEntity;
 
diff --git a/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java b/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java
index 61ae55e..c982942 100644
--- a/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java
@@ -1,11 +1,12 @@
 package com.ruoyi.project.tool.gen.service;
 
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.project.tool.gen.domain.GenTableColumn;
 import com.ruoyi.project.tool.gen.mapper.GenTableColumnMapper;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * 涓氬姟瀛楁 鏈嶅姟灞傚疄鐜�
@@ -13,10 +14,10 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class GenTableColumnServiceImpl implements IGenTableColumnService 
 {
-	@Autowired
-	private GenTableColumnMapper genTableColumnMapper;
+	private final GenTableColumnMapper genTableColumnMapper;
 
 	/**
      * 鏌ヨ涓氬姟瀛楁鍒楄〃
diff --git a/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java b/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java
index df90784..0c8a1a1 100644
--- a/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java
@@ -1,26 +1,5 @@
 package com.ruoyi.project.tool.gen.service;
 
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.Velocity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.ruoyi.common.constant.Constants;
@@ -35,6 +14,28 @@
 import com.ruoyi.project.tool.gen.util.GenUtils;
 import com.ruoyi.project.tool.gen.util.VelocityInitializer;
 import com.ruoyi.project.tool.gen.util.VelocityUtils;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 /**
  * 涓氬姟 鏈嶅姟灞傚疄鐜�
@@ -42,15 +43,13 @@
  * @author ruoyi
  */
 @Service
+@RequiredArgsConstructor
 public class GenTableServiceImpl implements IGenTableService
 {
     private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);
 
-    @Autowired
-    private GenTableMapper genTableMapper;
-
-    @Autowired
-    private GenTableColumnMapper genTableColumnMapper;
+    private final GenTableMapper genTableMapper;
+    private final GenTableColumnMapper genTableColumnMapper;
 
     /**
      * 鏌ヨ涓氬姟淇℃伅
diff --git a/src/main/java/com/ruoyi/project/tool/swagger/TestController.java b/src/main/java/com/ruoyi/project/tool/swagger/TestController.java
index 21871ce..0859437 100644
--- a/src/main/java/com/ruoyi/project/tool/swagger/TestController.java
+++ b/src/main/java/com/ruoyi/project/tool/swagger/TestController.java
@@ -12,22 +12,21 @@
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.web.controller.BaseController;
-import com.ruoyi.framework.web.domain.R;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import io.swagger.annotations.ApiOperation;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.R;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
 
 /**
  * swagger 鐢ㄦ埛娴嬭瘯鏂规硶
  * 
  * @author ruoyi
  */
-@Api("鐢ㄦ埛淇℃伅绠$悊")
+@Tag(name = "鐢ㄦ埛淇℃伅绠$悊")
 @RestController
 @RequestMapping("/test/user")
 public class TestController extends BaseController
@@ -38,7 +37,7 @@
         users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
     }
 
-    @ApiOperation("鑾峰彇鐢ㄦ埛鍒楄〃")
+    @Operation(summary = "鑾峰彇鐢ㄦ埛鍒楄〃")
     @GetMapping("/list")
     public R<List<UserEntity>> userList()
     {
@@ -46,10 +45,10 @@
         return R.ok(userList);
     }
 
-    @ApiOperation("鑾峰彇鐢ㄦ埛璇︾粏")
-    @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
-    @GetMapping("/{userId}")
-    public R<UserEntity> getUser(@PathVariable Integer userId)
+    @Operation(summary = "鑾峰彇鐢ㄦ埛璇︾粏")
+    @Parameter(name = "userId", description = "鐢ㄦ埛ID", required = true)
+    @GetMapping("/{userId}")
+    public R<UserEntity> getUser(@PathVariable Integer userId)
     {
         if (!users.isEmpty() && users.containsKey(userId))
         {
@@ -61,15 +60,15 @@
         }
     }
 
-    @ApiOperation("鏂板鐢ㄦ埛")
-    @ApiImplicitParams({
-        @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛id", dataType = "Integer", dataTypeClass = Integer.class),
-        @ApiImplicitParam(name = "username", value = "鐢ㄦ埛鍚嶇О", dataType = "String", dataTypeClass = String.class),
-        @ApiImplicitParam(name = "password", value = "鐢ㄦ埛瀵嗙爜", dataType = "String", dataTypeClass = String.class),
-        @ApiImplicitParam(name = "mobile", value = "鐢ㄦ埛鎵嬫満", dataType = "String", dataTypeClass = String.class)
-    })
-    @PostMapping("/save")
-    public R<String> save(UserEntity user)
+    @Operation(summary = "鏂板鐢ㄦ埛")
+    @Parameters({
+        @Parameter(name = "userId", description = "鐢ㄦ埛id"),
+        @Parameter(name = "username", description = "鐢ㄦ埛鍚嶇О"),
+        @Parameter(name = "password", description = "鐢ㄦ埛瀵嗙爜"),
+        @Parameter(name = "mobile", description = "鐢ㄦ埛鎵嬫満")
+    })
+    @PostMapping("/save")
+    public R<String> save(UserEntity user)
     {
         if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
         {
@@ -79,7 +78,7 @@
         return R.ok();
     }
 
-    @ApiOperation("鏇存柊鐢ㄦ埛")
+    @Operation(summary = "鏇存柊鐢ㄦ埛")
     @PutMapping("/update")
     public R<String> update(@RequestBody UserEntity user)
     {
@@ -96,10 +95,10 @@
         return R.ok();
     }
 
-    @ApiOperation("鍒犻櫎鐢ㄦ埛淇℃伅")
-    @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
-    @DeleteMapping("/{userId}")
-    public R<String> delete(@PathVariable Integer userId)
+    @Operation(summary = "鍒犻櫎鐢ㄦ埛淇℃伅")
+    @Parameter(name = "userId", description = "鐢ㄦ埛ID", required = true)
+    @DeleteMapping("/{userId}")
+    public R<String> delete(@PathVariable Integer userId)
     {
         if (!users.isEmpty() && users.containsKey(userId))
         {
@@ -113,19 +112,19 @@
     }
 }
 
-@ApiModel(value = "UserEntity", description = "鐢ㄦ埛瀹炰綋")
+@Schema(name = "UserEntity", description = "鐢ㄦ埛瀹炰綋")
 class UserEntity
 {
-    @ApiModelProperty("鐢ㄦ埛ID")
+    @Schema(description = "鐢ㄦ埛ID")
     private Integer userId;
 
-    @ApiModelProperty("鐢ㄦ埛鍚嶇О")
+    @Schema(description = "鐢ㄦ埛鍚嶇О")
     private String username;
 
-    @ApiModelProperty("鐢ㄦ埛瀵嗙爜")
+    @Schema(description = "鐢ㄦ埛瀵嗙爜")
     private String password;
 
-    @ApiModelProperty("鐢ㄦ埛鎵嬫満")
+    @Schema(description = "鐢ㄦ埛鎵嬫満")
     private String mobile;
 
     public UserEntity()
diff --git a/src/main/java/com/ruoyi/projectManagement/controller/InfoController.java b/src/main/java/com/ruoyi/projectManagement/controller/InfoController.java
index cb79883..56baf0f 100644
--- a/src/main/java/com/ruoyi/projectManagement/controller/InfoController.java
+++ b/src/main/java/com/ruoyi/projectManagement/controller/InfoController.java
@@ -8,12 +8,12 @@
 import com.ruoyi.projectManagement.vo.SaveInfoStageVo;
 import com.ruoyi.projectManagement.vo.SaveInfoVo;
 import com.ruoyi.projectManagement.vo.SearchInfoVo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.validation.Valid;
+import jakarta.validation.Valid;
 
 /**
  * @author buhuazhen
@@ -22,7 +22,7 @@
  */
 @RestController
 @RequestMapping("/projectManagement/info")
-@Api(value = "InfoController", tags = "椤圭洰绠$悊淇℃伅琛�(椤圭洰绠$悊绫诲瀷)")
+@Tag(name = "椤圭洰绠$悊淇℃伅琛�(椤圭洰绠$悊绫诲瀷)")
 @RequiredArgsConstructor
 public class InfoController {
 
@@ -30,54 +30,54 @@
     private final InfoStageHandleService infoStageHandleService;
 
     @PostMapping("/save")
-    @ApiOperation("淇濆瓨")
+    @Operation(summary = "淇濆瓨")
     public AjaxResult save(@RequestBody @Valid SaveInfoVo saveInfoVo) {
         infoService.save(saveInfoVo);
         return AjaxResult.success();
     }
 
     @PostMapping("/updateStatus")
-    @ApiOperation("淇敼鐘舵��")
+    @Operation(summary = "淇敼鐘舵��")
     public AjaxResult updateStatus(@RequestBody @Valid UpdateStateInfo updateStateInfo){
         infoService.updateStatus(updateStateInfo);
         return AjaxResult.success();
     }
 
     @PostMapping("/delete/{id}")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delete(@PathVariable Long id) {
         infoService.deleteInfo(id);
         return AjaxResult.success();
     }
 
     @PostMapping("/listPage")
-    @ApiOperation("鍒嗛〉鍒楄〃")
+    @Operation(summary = "鍒嗛〉鍒楄〃")
     public AjaxResult listPage(@RequestBody @Valid SearchInfoVo vo) {
         return AjaxResult.success(infoService.searchListInfo(vo));
     }
 
 
     @PostMapping("/{id}")
-    @ApiOperation("璇︽儏")
+    @Operation(summary = "璇︽儏")
     public AjaxResult getInfoById(@PathVariable Long id) {
         return AjaxResult.success(infoService.getInfoById(id));
     }
 
     @PostMapping("/saveStage")
-    @ApiOperation("淇濆瓨闃舵")
+    @Operation(summary = "淇濆瓨闃舵")
     public AjaxResult saveStage(@RequestBody @Valid SaveInfoStageVo dto) {
         infoStageHandleService.save(dto);
         return AjaxResult.success();
     }
 
     @PostMapping("/listStage/{id}")
-    @ApiOperation("鍒楄〃闃舵")
+    @Operation(summary = "鍒楄〃闃舵")
     public AjaxResult listStage(@PathVariable Long id) {
         return AjaxResult.success(infoStageHandleService.getListVoByInfoId(id));
     }
 
     @PostMapping("/deleteStage/{id}")
-    @ApiOperation("鍒犻櫎闃舵")
+    @Operation(summary = "鍒犻櫎闃舵")
     public AjaxResult deleteStage(@PathVariable Long id) {
         infoStageHandleService.deleteById(id);
         return AjaxResult.success();
diff --git a/src/main/java/com/ruoyi/projectManagement/controller/PlanController.java b/src/main/java/com/ruoyi/projectManagement/controller/PlanController.java
index f3a4745..c8b982c 100644
--- a/src/main/java/com/ruoyi/projectManagement/controller/PlanController.java
+++ b/src/main/java/com/ruoyi/projectManagement/controller/PlanController.java
@@ -5,13 +5,13 @@
 import com.ruoyi.projectManagement.vo.SavePlanNodeVo;
 import com.ruoyi.projectManagement.vo.SavePlanVo;
 import com.ruoyi.projectManagement.vo.SearchPlanVo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.validation.Valid;
+import jakarta.validation.Valid;
 
 /**
  * @author buhuazhen
@@ -20,28 +20,28 @@
  */
 @RestController
 @RequestMapping("/projectManagement/plan")
-@Api(value = "PlanController", tags = "椤圭洰绠$悊璁″垝琛�(椤圭洰绠$悊绫诲瀷)")
+@Tag(name = "椤圭洰绠$悊璁″垝琛�(椤圭洰绠$悊绫诲瀷)")
 @RequiredArgsConstructor
 public class PlanController {
 
     private final PlanService planService;
 
     @PostMapping("/save")
-    @ApiOperation("淇濆瓨")
+    @Operation(summary = "淇濆瓨")
     public AjaxResult save(@RequestBody @Valid SavePlanVo savePlanVo) {
         planService.savePlan(savePlanVo);
         return AjaxResult.success();
     }
 
     @PostMapping("/delete/{id}")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delete(@PathVariable Long id) {
         planService.deletePlan(id);
         return AjaxResult.success();
     }
 
     @PostMapping("/listPage")
-    @ApiOperation("鍒嗛〉鍒楄〃")
+    @Operation(summary = "鍒嗛〉鍒楄〃")
     public AjaxResult listPage(@RequestBody SearchPlanVo searchPlanVo) {
         return AjaxResult.success(planService.searchPlan(searchPlanVo));
     }
diff --git a/src/main/java/com/ruoyi/projectManagement/controller/RolesController.java b/src/main/java/com/ruoyi/projectManagement/controller/RolesController.java
index e3ca4a3..8adcf8d 100644
--- a/src/main/java/com/ruoyi/projectManagement/controller/RolesController.java
+++ b/src/main/java/com/ruoyi/projectManagement/controller/RolesController.java
@@ -9,8 +9,8 @@
 import com.ruoyi.projectManagement.mapper.RolesMapper;
 import com.ruoyi.projectManagement.pojo.Roles;
 import com.ruoyi.projectManagement.service.RolesService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
@@ -19,35 +19,35 @@
 @RestController
 @AllArgsConstructor
 @RequestMapping("/projectManagement/roles")
-@Api(value = "Roles", tags = "")
+@Tag(name = "")
 public class RolesController {
 
     private RolesService rolesservice;
     private RolesMapper rolesMapper;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ鎵�鏈�")
+    @Operation(summary = "鍒嗛〉鏌ヨ鎵�鏈�")
     public AjaxResult listPage(Page<Roles> page, Roles roles) {
         return AjaxResult.success(rolesservice.listPage(page, roles));
     }
 
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public AjaxResult add(@RequestBody RoleDto roleDto) {
         if (roleDto.getIsDefaultNo()) {
-            roleDto.setNo(OrderUtils.countTodayByCreateTime(rolesMapper, "XMJS"));
+            roleDto.setNo(OrderUtils.countTodayByCreateTime(rolesMapper, "XMJS","no"));
         }
         return AjaxResult.success(rolesservice.save(roleDto));
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼")
+    @Operation(summary = "淇敼")
     public AjaxResult update(@RequestBody Roles roles) {
         return AjaxResult.success(rolesservice.updateById(roles));
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         return AjaxResult.success(rolesservice.removeBatchByIds(ids));
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java b/src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java
index 13fade5..fcc881a 100644
--- a/src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java
+++ b/src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java
@@ -6,7 +6,7 @@
 import lombok.NoArgsConstructor;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/RoleDto.java b/src/main/java/com/ruoyi/projectManagement/dto/RoleDto.java
index a93b483..f033d2f 100644
--- a/src/main/java/com/ruoyi/projectManagement/dto/RoleDto.java
+++ b/src/main/java/com/ruoyi/projectManagement/dto/RoleDto.java
@@ -1,12 +1,12 @@
 package com.ruoyi.projectManagement.dto;
 
 import com.ruoyi.projectManagement.pojo.Roles;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 @Data
 public class RoleDto extends Roles {
     // 鏄惁浣跨敤绯荤粺缂栧彿
-    @ApiModelProperty("鏄惁浣跨敤绯荤粺缂栧彿")
+    @Schema(description = "鏄惁浣跨敤绯荤粺缂栧彿")
     private Boolean isDefaultNo;
 }
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java b/src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java
index 0b878ef..9fbef30 100644
--- a/src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java
+++ b/src/main/java/com/ruoyi/projectManagement/dto/SaveInfoDto.java
@@ -8,8 +8,8 @@
 import lombok.NoArgsConstructor;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
 import java.io.Serializable;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
diff --git a/src/main/java/com/ruoyi/projectManagement/dto/UpdateStateInfo.java b/src/main/java/com/ruoyi/projectManagement/dto/UpdateStateInfo.java
index 162a1d6..3aaab47 100644
--- a/src/main/java/com/ruoyi/projectManagement/dto/UpdateStateInfo.java
+++ b/src/main/java/com/ruoyi/projectManagement/dto/UpdateStateInfo.java
@@ -6,7 +6,7 @@
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
 import java.io.Serializable;
 
 /**
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java b/src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java
index d568a02..a438a4e 100644
--- a/src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/ContractInfo.java
@@ -135,4 +135,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/Info.java b/src/main/java/com/ruoyi/projectManagement/pojo/Info.java
index 999e787..5f5a0ab 100644
--- a/src/main/java/com/ruoyi/projectManagement/pojo/Info.java
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/Info.java
@@ -213,4 +213,7 @@
 
     @TableField(value = "update_user_name", fill = FieldFill.INSERT_UPDATE)
     private String updateUserName;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java b/src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java
index 052091a..d5c8643 100644
--- a/src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java
@@ -1,5 +1,6 @@
 package com.ruoyi.projectManagement.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -138,4 +139,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/Plan.java b/src/main/java/com/ruoyi/projectManagement/pojo/Plan.java
index fd63a03..a45409b 100644
--- a/src/main/java/com/ruoyi/projectManagement/pojo/Plan.java
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/Plan.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.time.LocalDateTime;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -17,69 +16,69 @@
  */
 @TableName(value ="project_management_plan")
 @Data
-@ApiModel(description="椤圭洰绠$悊璁″垝琛�(椤圭洰绠$悊绫诲瀷)")
+@Schema(description = "椤圭洰绠$悊璁″垝琛�(椤圭洰绠$悊绫诲瀷)")
 public class Plan {
     /**
      * 
      */
     @TableId(value = "id", type = IdType.AUTO)
-    @ApiModelProperty(value="涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     private Long id;
 
     /**
      * 璁″垝鍚嶇О
      */
     @TableField(value = "name")
-    @ApiModelProperty(value="璁″垝鍚嶇О")
+    @Schema(description = "璁″垝鍚嶇О")
     private String name;
 
     /**
      * 璁″垝鎻忚堪
      */
     @TableField(value = "description")
-    @ApiModelProperty(value="璁″垝鎻忚堪")
+    @Schema(description = "璁″垝鎻忚堪")
     private String description;
 
     /**
      * 闄勪欢 ,杩涜鍒嗗壊
      */
     @TableField(value = "attachment")
-    @ApiModelProperty(value="闄勪欢")
+    @Schema(description = "闄勪欢")
     private String attachment;
 
     /**
      * 
      */
     @TableField(value = "is_delete")
-    @ApiModelProperty(value="鏄惁鍒犻櫎")
+    @Schema(description = "鏄惁鍒犻櫎")
     private Integer isDelete;
 
     /**
      * 
      */
     @TableField(value = "create_time",fill = FieldFill.INSERT)
-    @ApiModelProperty(value="鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     private LocalDateTime createTime;
 
     /**
      * 
      */
     @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
-    @ApiModelProperty(value="鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     private LocalDateTime updateTime;
 
     /**
      * 
      */
     @TableField(value = "create_user",fill = FieldFill.INSERT)
-    @ApiModelProperty(value="鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     private Integer createUser;
 
     /**
      * 
      */
     @TableField(value = "update_user",fill = FieldFill.INSERT_UPDATE)
-    @ApiModelProperty(value="鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     private Integer updateUser;
 
     @TableField(value = "create_user_name", fill = FieldFill.INSERT)
@@ -87,4 +86,7 @@
 
     @TableField(value = "update_user_name", fill = FieldFill.INSERT_UPDATE)
     private String updateUserName;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/PlanNode.java b/src/main/java/com/ruoyi/projectManagement/pojo/PlanNode.java
index 3d9d9b1..1aac964 100644
--- a/src/main/java/com/ruoyi/projectManagement/pojo/PlanNode.java
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/PlanNode.java
@@ -107,4 +107,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/Roles.java b/src/main/java/com/ruoyi/projectManagement/pojo/Roles.java
index c284f13..1b65ea4 100644
--- a/src/main/java/com/ruoyi/projectManagement/pojo/Roles.java
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/Roles.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -12,7 +11,7 @@
 
 @Data
 @TableName("project_management_roles")
-@ApiModel(description="")
+@Schema(description = "")
 public class Roles implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -20,37 +19,40 @@
     /**
     * 涓婚敭ID
     */
-    @ApiModelProperty(value="涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     private Long id;
     /**
     * 缂栧彿
     */
-    @ApiModelProperty(value="缂栧彿")
+    @Schema(description = "缂栧彿")
     private String no;
     /**
     * 鍚嶇О
     */
-    @ApiModelProperty(value="鍚嶇О")
+    @Schema(description = "鍚嶇О")
     private String name;
     /**
     * 鐘舵��(1:鍚敤, 0:绂佺敤)
     */
-    @ApiModelProperty(value="鐘舵��(1:鍚敤, 0:绂佺敤)")
+    @Schema(description = "鐘舵��(1:鍚敤, 0:绂佺敤)")
     private Integer status;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java b/src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java
index ffc6940..dd552ce 100644
--- a/src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java
+++ b/src/main/java/com/ruoyi/projectManagement/pojo/ShippingAddress.java
@@ -79,4 +79,7 @@
 
     @TableField(exist = false)
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/projectManagement/service/InfoService.java b/src/main/java/com/ruoyi/projectManagement/service/InfoService.java
index ac3d8e8..22a9250 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/InfoService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/InfoService.java
@@ -7,7 +7,7 @@
 import com.ruoyi.projectManagement.vo.SaveInfoVo;
 import com.ruoyi.projectManagement.vo.SearchInfoVo;
 
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
 
 /**
  * @author buhuazhen
diff --git a/src/main/java/com/ruoyi/projectManagement/service/PlanService.java b/src/main/java/com/ruoyi/projectManagement/service/PlanService.java
index c0a8161..2659b27 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/PlanService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/PlanService.java
@@ -9,9 +9,9 @@
 import com.ruoyi.projectManagement.vo.SavePlanVo;
 import com.ruoyi.projectManagement.vo.SearchPlanVo;
 
-import javax.annotation.Nullable;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Null;
+import jakarta.annotation.Nullable;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Null;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java b/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java
index fd5f028..e05ce2e 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java
@@ -6,7 +6,10 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.basic.service.CustomerFollowUpFileService;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.projectManagement.mapper.PlanMapper;
 import com.ruoyi.projectManagement.mapper.PlanNodeMapper;
@@ -40,6 +43,7 @@
     private final CustomerFollowUpFileService customerFollowUpFileService;
 
     private final PlanNodeMapper planNodeMapper;
+    private final FileUtil fileUtil;
 
     @Lazy
     @Autowired
@@ -49,9 +53,8 @@
     @Transactional(rollbackFor = Exception.class)
     public void savePlan(SavePlanVo savePlanVo) {
         Plan plan = BeanUtil.copyProperties(savePlanVo, Plan.class);
-        // 闄勪欢澶勭悊 , 鎷兼帴
-        String attachments = String.join(",", Optional.ofNullable(savePlanVo.getAttachmentIds()).orElse(Collections.emptyList()));
-        plan.setAttachment(attachments);
+        // 闄勪欢澶勭悊
+        fileUtil.saveStorageAttachmentByRecordTypeAndRecordId("", RecordTypeEnum.PLAN, savePlanVo.getId(), savePlanVo.getStorageBlobDTOs());
         if (savePlanVo.getId() == null) {
             planMapper.insert(plan);
         } else {
@@ -101,6 +104,9 @@
     }
 
     private List<PlanNode> getPlanNodeByPlanIds(List<Long> planIds) {
+        if(CollUtil.isEmpty(planIds)){
+            return Collections.emptyList();
+        }
         return planNodeMapper.selectList(new LambdaQueryWrapper<PlanNode>()
                 .eq(PlanNode::getIsDelete, 0)
                 .in(PlanNode::getProjectManagementPlanId, planIds).orderByAsc(PlanNode::getSort));
@@ -133,12 +139,14 @@
         IPage<Plan> planIPage = planMapper.selectPlanPage(searchPlanVo);
         IPage<PlanVo> resultPage = planIPage.convert(plan -> BeanUtil.copyProperties(plan, PlanVo.class));
         // 鏂囦欢鑾峰彇
-        customerFollowUpFileService.fillAttachment(resultPage.getRecords(), PlanVo::getAttachment, PlanVo::setAttachmentList);
         Map<Long, List<PlanNodeVo>> collect = getPlanNodeByPlanIds(resultPage.getRecords().stream().map(PlanVo::getId).collect(Collectors.toList()))
                 .stream()
                 .map(it -> BeanUtil.copyProperties(it, PlanNodeVo.class))
                 .collect(Collectors.groupingBy(PlanNodeVo::getProjectManagementPlanId, Collectors.toList()));
-        resultPage.getRecords().forEach(planVo -> planVo.setPlanNodeList(collect.getOrDefault(planVo.getId(), Collections.emptyList())));
+        resultPage.getRecords().forEach(planVo -> {
+            planVo.setPlanNodeList(collect.getOrDefault(planVo.getId(), Collections.emptyList()));
+            planVo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.PLAN, planVo.getId()));
+        });
         return resultPage;
     }
 
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java
index 59cbb9f..afe4de3 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ContractInfoHandleService.java
@@ -5,13 +5,11 @@
 import com.ruoyi.projectManagement.dto.ContractInfoDto;
 import com.ruoyi.projectManagement.mapper.ContractInfoMapper;
 import com.ruoyi.projectManagement.pojo.ContractInfo;
+import jakarta.annotation.Nullable;
+import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
-
-import javax.annotation.Nullable;
-import javax.validation.constraints.NotNull;
 
 /**
  * @author buhuazhen
@@ -20,10 +18,10 @@
  */
 @Component
 @Transactional(rollbackFor = Exception.class,readOnly = true)
+@RequiredArgsConstructor
 public class ContractInfoHandleService{
 
-    @Autowired
-    private ContractInfoMapper contractInfoMapper;
+    private final ContractInfoMapper contractInfoMapper;
 
     @Transactional(rollbackFor = Exception.class)
     public void save(@Nullable Long id, @NotNull ContractInfoDto contractInfoDto) {
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java
index 84715f9..a5f2ff4 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java
@@ -20,7 +20,7 @@
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java
index dac839d..2025777 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java
@@ -4,7 +4,10 @@
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.basic.service.CustomerFollowUpFileService;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.enums.IsDeleteEnum;
 import com.ruoyi.common.enums.PlanStageEnum;
 import com.ruoyi.projectManagement.dto.InfoStageDto;
@@ -15,13 +18,13 @@
 import com.ruoyi.projectManagement.pojo.InfoStage;
 import com.ruoyi.projectManagement.vo.InfoStageVo;
 import com.ruoyi.projectManagement.vo.SaveInfoStageVo;
+import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.validation.constraints.NotNull;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -37,9 +40,10 @@
     private final InfoStageMapper infoStageMapper;
     private final InfoHandleService infoHandleService;
     private final CustomerFollowUpFileService customerFollowUpFileService;
-    @Autowired
     @Lazy
+    @Autowired
     private InfoStageHandleService infoStageHandleService;
+    private final FileUtil fileUtil;
 
     @Transactional
     public void save(@NotNull SaveInfoStageVo saveInfoStageVo) {
@@ -47,6 +51,8 @@
         // 闄勪欢澶勭悊
         String attachmentIds = StrUtil.join(",", Optional.ofNullable(saveInfoStageVo.getAttachmentIds()).orElse(Collections.emptyList()));
         infoStage.setAttachment(attachmentIds);
+
+        fileUtil.saveStorageAttachmentByRecordTypeAndRecordId("", RecordTypeEnum.INFO_STAGE, infoStage.getProjectManagementInfoId(), saveInfoStageVo.getStorageBlobDTOs());
 
         if (infoStage.getId() == null) {
             infoStageMapper.insert(infoStage);
@@ -153,7 +159,10 @@
         List<InfoStageDto> listByInfoId = getListDtoByInfoId(infoId);
         List<InfoStageVo> infoStageVos = BeanUtil.copyToList(listByInfoId, InfoStageVo.class);
         // 澶勭悊闄勪欢
-        customerFollowUpFileService.fillAttachment(infoStageVos, InfoStageVo::getAttachment, InfoStageVo::setAttachmentList);
+        for (InfoStageVo infoStageVo : infoStageVos) {
+            List<StorageBlobVO> storageBlobVOs = fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.INFO_STAGE, infoStageVo.getId());
+            infoStageVo.setStorageBlobVOs(storageBlobVOs != null ? storageBlobVOs : new ArrayList<>());
+        }
         return infoStageVos;
     }
 
diff --git a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java
index f5e6cf6..73acb78 100644
--- a/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java
+++ b/src/main/java/com/ruoyi/projectManagement/service/impl/handle/ShippingAddressHandleService.java
@@ -9,8 +9,8 @@
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.annotation.Nullable;
-import javax.validation.constraints.NotNull;
+import jakarta.annotation.Nullable;
+import jakarta.validation.constraints.NotNull;
 
 /**
  * @author buhuazhen
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java b/src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java
index 8be6a2d..71d7ee5 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java
@@ -1,5 +1,6 @@
 package com.ruoyi.projectManagement.vo;
 
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.common.vo.SimpleFileVo;
 import com.ruoyi.projectManagement.dto.InfoStageDto;
 import lombok.AllArgsConstructor;
@@ -21,4 +22,5 @@
 public class InfoStageVo extends InfoStageDto implements java.io.Serializable {
 
     private List<SimpleFileVo> attachmentList; // 闄勪欢鍒楄〃
+    private List<StorageBlobVO> storageBlobVOs;
 }
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/PlanVo.java b/src/main/java/com/ruoyi/projectManagement/vo/PlanVo.java
index 492435e..6cba06b 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/PlanVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/PlanVo.java
@@ -2,6 +2,8 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.common.vo.SimpleFileVo;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -44,5 +46,5 @@
     private LocalDateTime updateTime;
 
     private List<PlanNodeVo> planNodeList;
-
+    private List<StorageBlobVO> storageBlobVOs;
 }
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java b/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java
index d19095b..966b999 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java
@@ -2,6 +2,8 @@
 
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.projectManagement.dto.InfoStageDto;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -24,5 +26,5 @@
 public class SaveInfoStageVo extends InfoStageDto implements java.io.Serializable {
 
     private List<String> attachmentIds;
-
+    private List<StorageBlobDTO> StorageBlobDTOs;
 }
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java b/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java
index 749de19..166cc32 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/SaveInfoVo.java
@@ -8,7 +8,7 @@
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.validation.Valid;
+import jakarta.validation.Valid;
 import java.io.Serializable;
 import java.util.List;
 
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/SavePlanNodeVo.java b/src/main/java/com/ruoyi/projectManagement/vo/SavePlanNodeVo.java
index 7f059da..807f87e 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/SavePlanNodeVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/SavePlanNodeVo.java
@@ -4,8 +4,8 @@
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
 import java.io.Serializable;
 
 /**
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java b/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java
index bd42d84..e1042b2 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java
@@ -1,13 +1,14 @@
 package com.ruoyi.projectManagement.vo;
 
 
+import com.ruoyi.basic.dto.StorageBlobDTO;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.util.List;
 
@@ -32,5 +33,5 @@
     @Valid
     private List<SavePlanNodeVo> savePlanNodeList;
 
-
+    private List<StorageBlobDTO> storageBlobDTOs;
 }
diff --git a/src/main/java/com/ruoyi/projectManagement/vo/SearchPlanVo.java b/src/main/java/com/ruoyi/projectManagement/vo/SearchPlanVo.java
index 3a29444..efe2bc5 100644
--- a/src/main/java/com/ruoyi/projectManagement/vo/SearchPlanVo.java
+++ b/src/main/java/com/ruoyi/projectManagement/vo/SearchPlanVo.java
@@ -1,12 +1,15 @@
 package com.ruoyi.projectManagement.vo;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * @author buhuazhen
diff --git a/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java b/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
index 3df034f..813fb44 100644
--- a/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
@@ -11,8 +11,8 @@
 import com.ruoyi.purchase.pojo.InvoicePurchase;
 import com.ruoyi.purchase.service.IInvoicePurchaseService;
 import com.ruoyi.waterrecord.pojo.WaterRecord;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -20,16 +20,15 @@
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
-@Api(tags = "閲囪喘鎶ヨ〃")
+@Tag(name = "閲囪喘鎶ヨ〃")
 @RequestMapping("/purchase/report")
 @AllArgsConstructor
 public class AccountingReportController {
 
-    @Autowired
     private IInvoicePurchaseService invoicePurchaseService;
 
     @GetMapping("/list")
@@ -41,7 +40,7 @@
 
     @Log(title = "閲囪喘鎶ヨ〃-椤圭洰鍒╂鼎瀵煎嚭", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("閲囪喘鎶ヨ〃-椤圭洰鍒╂鼎瀵煎嚭")
+    @Operation(summary = "閲囪喘鎶ヨ〃-椤圭洰鍒╂鼎瀵煎嚭")
     public void export(HttpServletResponse response) {
         Page page = new Page(-1,-1);
         InvoicePurchaseReportDto waterRecord = new InvoicePurchaseReportDto();
@@ -59,7 +58,7 @@
 
     @Log(title = "閲囪喘鎶ヨ〃-澧炲�肩◣姣斿", businessType = BusinessType.EXPORT)
     @PostMapping("/exportTwo")
-    @ApiOperation("閲囪喘鎶ヨ〃-澧炲�肩◣姣斿")
+    @Operation(summary = "閲囪喘鎶ヨ〃-澧炲�肩◣姣斿")
     public void exportTwo(HttpServletResponse response) {
         Page page = new Page(-1,-1);
         IPage<VatDto> result = invoicePurchaseService.listVat(page, null);
diff --git a/src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java b/src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java
index a69d204..afd9213 100644
--- a/src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java
@@ -10,11 +10,10 @@
 import com.ruoyi.purchase.pojo.InvoicePurchase;
 import com.ruoyi.purchase.service.IInvoicePurchaseService;
 import com.ruoyi.sales.service.ICommonFileService;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.List;
 
@@ -80,12 +79,4 @@
         return toAjax(invoicePurchaseService.delInvoice(ids));
     }
 
-    @PostMapping("/upload")
-    public AjaxResult uploadFile(MultipartFile file, Long id, Integer type) {
-        try {
-            return AjaxResult.success(commonFileService.uploadFile(file, id, type));
-        } catch (Exception e) {
-            return AjaxResult.error(e.getMessage());
-        }
-    }
 }
diff --git a/src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java b/src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java
index e895ea6..289110c 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java
@@ -13,11 +13,12 @@
 import com.ruoyi.purchase.dto.PaymentRegistrationDto;
 import com.ruoyi.purchase.pojo.PaymentRegistration;
 import com.ruoyi.purchase.service.IPaymentRegistrationService;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 
@@ -29,8 +30,8 @@
  */
 @RestController
 @RequestMapping("/purchase/paymentRegistration")
+@AllArgsConstructor
 public class PaymentRegistrationController extends BaseController {
-    @Autowired
     private IPaymentRegistrationService paymentRegistrationService;
 
     /**
diff --git a/src/main/java/com/ruoyi/purchase/controller/ProcurementBusinessSummaryController.java b/src/main/java/com/ruoyi/purchase/controller/ProcurementBusinessSummaryController.java
index 9370ddb..cbdee81 100644
--- a/src/main/java/com/ruoyi/purchase/controller/ProcurementBusinessSummaryController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/ProcurementBusinessSummaryController.java
@@ -8,30 +8,26 @@
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.purchase.dto.ProcurementBusinessSummaryDto;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.purchase.service.impl.ProcurementBusinessSummaryServiceImpl;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
 /**
  * @author :yys
  * @date : 2026/1/15 13:29
  */
-@Api(tags = "閲囪喘涓氬姟姹囨��")
+@Tag(name = "閲囪喘涓氬姟姹囨��")
 @RestController
 @RequestMapping("/procurementBusinessSummary")
+@AllArgsConstructor
 public class ProcurementBusinessSummaryController extends BaseController {
 
 
-    @Autowired
     private ProcurementBusinessSummaryServiceImpl procurementBusinessSummaryService;
 
     @GetMapping("/listPage")
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
index 2358caf..3290499 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
@@ -20,15 +20,15 @@
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.service.ISalesLedgerProductService;
 import com.ruoyi.sales.service.ISalesLedgerService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -48,7 +48,7 @@
 @RestController
 @RequestMapping("/purchase/ledger")
 @AllArgsConstructor
-@Api(tags = "閲囪喘鍙拌处")
+@Tag(name = "閲囪喘鍙拌处")
 @Slf4j
 public class PurchaseLedgerController extends BaseController {
     private IPurchaseLedgerService purchaseLedgerService;
@@ -66,14 +66,14 @@
      */
     @Log(title = "瀵煎叆閲囪喘鍙拌处", businessType = BusinessType.INSERT)
     @PostMapping("/import")
-    @ApiOperation("瀵煎叆閲囪喘鍙拌处")
+    @Operation(summary = "瀵煎叆閲囪喘鍙拌处")
     public AjaxResult importData(@RequestParam("file")
                                  @ApiParam(value = "Excel鏂囦欢", required = true)
                                          MultipartFile file) {
         return purchaseLedgerService.importData(file);
     }
 
-    @ApiOperation("瀵煎嚭閲囪喘鍙拌处妯℃澘")
+    @Operation(summary = "瀵煎嚭閲囪喘鍙拌处妯℃澘")
     @PostMapping("/exportTemplate")
     public void exportTemplate(HttpServletResponse response) {
         // 1. 妯℃澘鏂囦欢鍦╮esources/static涓嬬殑璺緞
@@ -158,7 +158,7 @@
     /**
      * 鏌ヨ閲囪喘妯℃澘
      */
-    @ApiOperation("/鏌ヨ閲囪喘妯℃澘")
+    @Operation(summary = "/鏌ヨ閲囪喘妯℃澘")
     @GetMapping("/getPurchaseTemplateList")
     public AjaxResult getPurchaseTemplateList() {
         List<PurchaseLedgerTemplate>  purchaseLedgers = purchaseLedgerTemplateMapper.selectList(null);
@@ -262,7 +262,7 @@
         return AjaxResult.success(purchaseLedgerService.selectPurchaseLedgerListPage(page, purchaseLedger));
     }
 
-    @ApiOperation("鐢熸垚閲囪喘搴忓垪鍙�")
+    @Operation(summary = "鐢熸垚閲囪喘搴忓垪鍙�")
     @GetMapping("/createPurchaseNo")
     @Log(title = "鐢熸垚閲囪喘搴忓垪鍙�", businessType = BusinessType.OTHER)
     public AjaxResult createPurchaseNo() {
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerTemplateController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerTemplateController.java
index 3f5aca6..3b3c97f 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerTemplateController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerTemplateController.java
@@ -10,15 +10,13 @@
 import com.ruoyi.purchase.mapper.SalesLedgerProductTemplateMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
 import com.ruoyi.purchase.pojo.SalesLedgerProductTemplate;
-import com.ruoyi.purchase.service.PurchaseLedgerTemplateService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -31,18 +29,16 @@
  */
 @RestController
 @RequestMapping("/purchaseLedgerTemplate")
-@Api(tags = "閲囪喘鍙拌处妯℃澘")
+@Tag(name = "閲囪喘鍙拌处妯℃澘")
+@AllArgsConstructor
 public class PurchaseLedgerTemplateController {
 
-    @Autowired
     private PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
-
-    @Autowired
     private SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
 
     @PostMapping("/add")
     @Log(title = "娣诲姞閲囪喘鍙拌处妯℃澘", businessType = BusinessType.INSERT)
-    @ApiOperation(value = "娣诲姞閲囪喘鍙拌处妯℃澘")
+    @Operation(summary = "娣诲姞閲囪喘鍙拌处妯℃澘")
     public AjaxResult add(@RequestBody PurchaseLedgerDto purchaseLedgerDto) {
         // 閲囪喘妯℃澘
         if(StringUtils.isNotEmpty(purchaseLedgerDto.getTemplateName())){
@@ -72,7 +68,7 @@
 
     @DeleteMapping("/delete")
     @Log(title = "閲囪喘鍙拌处妯℃澘", businessType = BusinessType.DELETE)
-    @ApiOperation(value = "鍒犻櫎閲囪喘鍙拌处妯℃澘")
+    @Operation(summary = "鍒犻櫎閲囪喘鍙拌处妯℃澘")
     public AjaxResult delete(@RequestBody List<Long> id) {
         if(CollectionUtils.isEmpty(id)) return AjaxResult.error("璇烽�夋嫨瑕佸垹闄ょ殑閲囪喘鍙拌处妯℃澘");
         int result = purchaseLedgerTemplateMapper.deleteBatchIds(id);
@@ -83,7 +79,7 @@
 
     @PostMapping("/update")
     @Log(title = "淇敼閲囪喘鍙拌处妯℃澘", businessType = BusinessType.UPDATE)
-    @ApiOperation(value = "淇敼閲囪喘鍙拌处妯℃澘")
+    @Operation(summary = "淇敼閲囪喘鍙拌处妯℃澘")
     public AjaxResult update(@RequestBody PurchaseLedgerDto purchaseLedgerDto) {
         // 妯℃澘鍚嶇О涓嶈兘閲嶅锛屾湁閲嶅灏变笉闇�瑕佹柊澧炰簡
         PurchaseLedgerTemplate purchaseLedgerTemplate = purchaseLedgerTemplateMapper
@@ -102,6 +98,7 @@
                 SalesLedgerProductTemplate salesLedgerProductTemplate = new SalesLedgerProductTemplate();
                 BeanUtils.copyProperties(product, salesLedgerProductTemplate);
                 salesLedgerProductTemplate.setSalesLedgerId(purchaseLedgerTemplate.getId());
+                salesLedgerProductTemplate.setType(2);
                 salesLedgerProductTemplateMapper.insert(salesLedgerProductTemplate);
             });
         }
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrderProductsController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrderProductsController.java
index e3b1e8b..896c3c3 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrderProductsController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrderProductsController.java
@@ -1,6 +1,6 @@
 package com.ruoyi.purchase.controller;
 
-import io.swagger.annotations.Api;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -14,7 +14,7 @@
  */
 @RestController
 @RequestMapping("/purchaseReturnOrderProducts")
-@Api(tags = "閲囪喘閫�璐т骇鍝�")
+@Tag(name = "閲囪喘閫�璐т骇鍝�")
 public class PurchaseReturnOrderProductsController {
 
 }
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
index 1e56411..16449e8 100644
--- a/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
@@ -5,17 +5,16 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.projectManagement.mapper.RolesMapper;
 import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
 import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
 import com.ruoyi.purchase.service.PurchaseReturnOrdersService;
-import io.swagger.annotations.Api;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 /**
  * <p>
- *  鍓嶇鎺у埗鍣�
+ * 鍓嶇鎺у埗鍣�
  * </p>
  *
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
@@ -23,12 +22,10 @@
  */
 @RestController
 @RequestMapping("/purchaseReturnOrders")
-@Api(tags = "閲囪喘閫�璐у崟")
+@Tag(name = "閲囪喘閫�璐у崟")
+@AllArgsConstructor
 public class PurchaseReturnOrdersController {
-    @Autowired
     private PurchaseReturnOrdersService purchaseReturnOrdersService;
-
-    @Autowired
     private PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
 
 
@@ -42,8 +39,22 @@
     @PostMapping("/add")
     public AjaxResult add(@RequestBody PurchaseReturnOrderDto purchaseReturnOrderDto) throws Exception {
         if (purchaseReturnOrderDto.getIsDefaultNo()) {
-            purchaseReturnOrderDto.setNo(OrderUtils.countTodayByCreateTime(purchaseReturnOrdersMapper, "CGTL"));
+            purchaseReturnOrderDto.setNo(OrderUtils.countTodayByCreateTime(purchaseReturnOrdersMapper, "CGTL", "no"));
         }
         return AjaxResult.success(purchaseReturnOrdersService.add(purchaseReturnOrderDto));
     }
+
+
+    @GetMapping("/selectById/{id}")
+    public AjaxResult selectById(@PathVariable Long id) {
+        return AjaxResult.success(purchaseReturnOrdersService.getPurchaseReturnOrderDtoById(id));
+    }
+
+    @PostMapping("/deleteById/{id}")
+    public AjaxResult deleteById(@PathVariable Long id) {
+        purchaseReturnOrdersService.deleteById(id);
+        return AjaxResult.success();
+    }
+
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java b/src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java
index baefa12..db628af 100644
--- a/src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java
+++ b/src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java
@@ -19,18 +19,15 @@
 import com.ruoyi.purchase.service.ITicketRegistrationService;
 import com.ruoyi.purchase.service.impl.PaymentRegistrationServiceImpl;
 import com.ruoyi.sales.service.ICommonFileService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiModelProperty;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.parameters.P;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.List;
 
@@ -43,7 +40,7 @@
 @RestController
 @RequestMapping("/purchase/registration")
 @AllArgsConstructor
-@Api(tags = "鏉ョエ鐧昏")
+@Tag(name = "鏉ョエ鐧昏")
 public class TicketRegistrationController extends BaseController {
 
     private final PaymentRegistrationServiceImpl paymentRegistrationServiceImpl;
@@ -53,7 +50,6 @@
 
     private IProductRecordService productRecordService;
 
-    @Autowired
     private IPaymentRegistrationService paymentRegistrationService;
 
     /**
@@ -66,27 +62,27 @@
         return getDataTable(list);
     }
 
-    @ApiOperation("鏍规嵁id鏌ヨ浠樻娴佹按淇℃伅")
+    @Operation(summary = "鏍规嵁id鏌ヨ浠樻娴佹按淇℃伅")
     @GetMapping("/getById")
     public List<PaymentRegistrationDto> getById( Long id ) {
         return ticketRegistrationService.getPaymentRegistrationDtoById(id);
     }
 
-    @ApiOperation("鏍规嵁id鏌ヨ浠樻娴佹按")
+    @Operation(summary = "鏍规嵁id鏌ヨ浠樻娴佹按")
     @GetMapping("/getPaymentRegistrationById")
     public AjaxResult getPaymentRegistrationById(Long id) {
         PaymentRegistration byId = paymentRegistrationService.getById(id);
         return AjaxResult.success(byId);
     }
 
-    @ApiOperation("淇敼浠樻娴佹按")
+    @Operation(summary = "淇敼浠樻娴佹按")
     @PutMapping("/updatePaymentRegistration")
     @Log(title = "淇敼浠樻娴佹按", businessType = BusinessType.UPDATE)
     public AjaxResult updatePaymentRegistration(@RequestBody PaymentRegistration paymentRegistratio) {
         return AjaxResult.success(paymentRegistrationService.updatePaymentRegistration(paymentRegistratio));
     }
 
-    @ApiOperation("鍒犻櫎浠樻娴佹按")
+    @Operation(summary = "鍒犻櫎浠樻娴佹按")
     @DeleteMapping("/delPaymentRegistration")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delPaymentRegistration(@RequestBody List<Long> id) {
@@ -147,7 +143,7 @@
         return AjaxResult.success(productRecordService.getProductRecordById(productRecordDto));
     }
 
-    @ApiModelProperty("淇敼鏉ョエ鐧昏")
+    @Schema(description = "淇敼鏉ョエ鐧昏")
     @PostMapping("/updateRegistration")
     public AjaxResult updateRegistration(@RequestBody ProductRecordDto productRecordDto) {
 
@@ -162,15 +158,6 @@
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delRegistration(@RequestBody Long[] ids) {
         return toAjax(ticketRegistrationService.delRegistration(ids));
-    }
-
-    @PostMapping("/upload")
-    public AjaxResult uploadFile(MultipartFile file, Long id, Integer type) {
-        try {
-            return AjaxResult.success(commonFileService.uploadFile(file, id, type));
-        } catch (Exception e) {
-            return AjaxResult.error(e.getMessage());
-        }
     }
 
     /**
@@ -208,7 +195,7 @@
         return ticketRegistrationService.selectTicketRegistrationListPage(page,ticketRegistration);
     }
 
-    @ApiModelProperty("鏍规嵁id鏌ヨ鏉ユ紓鐧昏")
+    @Schema(description = "鏍规嵁id鏌ヨ鏉ユ紓鐧昏")
     @GetMapping("/getPuargeById")
     public AjaxResult getPuargeById(Long id) {
         return AjaxResult.success(ticketRegistrationService.getPuargeById( id));
diff --git a/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java b/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java
index a154c94..3e48e79 100644
--- a/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/ProcurementBusinessSummaryDto.java
@@ -8,8 +8,7 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -21,7 +20,7 @@
  * @date : 2026/1/15 13:34
  */
 @Data
-@ApiModel
+@Schema
 public class ProcurementBusinessSummaryDto {
 
     @Excel(name = "浜у搧澶х被")
@@ -33,12 +32,12 @@
     @Excel(name = "瑙勬牸鍨嬪彿")
     private String specificationModel;
 
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
+    @Schema(description = "寮�濮嬫椂闂�")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date entryDateStart;
 
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
+    @Schema(description = "缁撴潫鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date entryDateEnd;
@@ -82,4 +81,16 @@
     @Excel(name = "褰曞叆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private Date entryDate;
 
+    /**
+     * 閫�璐ф暟閲�
+     */
+    @Excel(name = "閫�璐ф暟閲�")
+
+    private BigDecimal returnQuantity;
+
+    /**
+     * 閫�璐ч噾棰�
+     */
+    @Excel(name = "閫�璐ч噾棰�")
+    private BigDecimal returnAmount;
 }
diff --git a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
index c8ea3f5..c6b1406 100644
--- a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
@@ -2,10 +2,12 @@
 
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,7 +20,7 @@
     /**
      * 瀹℃壒浜篿d鍒楄〃
      */
-    @ApiModelProperty(value = "瀹℃壒浜篿d鍒楄〃")
+    @Schema(description = "瀹℃壒浜篿d鍒楄〃")
     private String approveUserIds;
 
 
@@ -175,26 +177,29 @@
 
 
     @TableField(exist = false)
-    @ApiModelProperty("鏉ョエ閲戦")
+    @Schema(description = "鏉ョエ閲戦")
     @Excel(name = "宸叉潵绁ㄩ噾棰�(鍏�)")
     private BigDecimal receiptPaymentAmount =  BigDecimal.ZERO;
 
-    @ApiModelProperty("鏈潵绁ㄩ噾棰�")
+    @Schema(description = "鏈潵绁ㄩ噾棰�")
     @TableField(exist = false)
     @Excel(name = "鏈潵绁ㄩ噾棰�(鍏�)")
     private BigDecimal unReceiptPaymentAmount =BigDecimal.ZERO;
 
-    @ApiModelProperty("鏂囦欢绫诲瀷  鍙� 4")
+    @Schema(description = "鏂囦欢绫诲瀷  鍙� 4")
     @TableField(exist = false)
     private Integer type;
 
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     private String paymentMethod;
-    @ApiModelProperty("瀹℃壒鐘舵��")
+    @Schema(description = "瀹℃壒鐘舵��")
     private Integer approvalStatus;
-    @ApiModelProperty(value = "妯℃澘鍚嶇О")
+    @Schema(description = "妯℃澘鍚嶇О")
     private String templateName;
-    @ApiModelProperty(value = "瀹℃壒浜篿d")
+    @Schema(description = "瀹℃壒浜篿d")
     private Integer approverId;
+
+    private List<StorageBlobVO> storageBlobVOS;
+    private List<StorageBlobDTO> storageBlobDTOS;
 }
diff --git a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerImportDto.java b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerImportDto.java
index f915051..bf510b4 100644
--- a/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerImportDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerImportDto.java
@@ -2,7 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.Date;
@@ -35,16 +35,16 @@
     @Excel(name = "澶囨敞")
     private String remarks;
 
-    @ApiModelProperty(value = "绛捐鏃ユ湡")
+    @Schema(description = "绛捐鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "绛捐鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private Date executionDate;
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     @Excel(name = "浠樻鏂瑰紡")
     private String paymentMethod;
 
-    @ApiModelProperty(value = "瀹℃牳浜�(澶氫釜鐢紝闅斿紑)")
+    @Schema(description = "瀹℃牳浜�(澶氫釜鐢紝闅斿紑)")
     @Excel(name = "瀹℃牳浜�(澶氫釜鐢紝闅斿紑)")
     private String approveUserIds;
 
diff --git a/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java b/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java
index f10a853..926221c 100644
--- a/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java
+++ b/src/main/java/com/ruoyi/purchase/dto/PurchaseReturnOrderDto.java
@@ -1,16 +1,20 @@
 package com.ruoyi.purchase.dto;
 
-import com.ruoyi.purchase.pojo.PurchaseReturnOrderProducts;
 import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.util.List;
 
+@EqualsAndHashCode(callSuper = true)
 @Data
 public class PurchaseReturnOrderDto extends PurchaseReturnOrders {
     // 鏄惁浣跨敤绯荤粺鍗曞彿
     private Boolean isDefaultNo;
 
+    private String supplierName;
 
     private List<PurchaseReturnOrderProductsDto> purchaseReturnOrderProductsDtos;
+
+    private Long[] deptIds;
 }
diff --git a/src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java b/src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java
new file mode 100644
index 0000000..dc9220a
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/dto/SimpleReturnOrderGroupDto.java
@@ -0,0 +1,21 @@
+package com.ruoyi.purchase.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/21
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SimpleReturnOrderGroupDto implements Serializable {
+    private Long salesLedgerProductId;
+    private BigDecimal sumReturnQuantity;
+}
diff --git a/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java b/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java
index f4ab57b..fe18e44 100644
--- a/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java
+++ b/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java
@@ -1,8 +1,13 @@
 package com.ruoyi.purchase.mapper;
 
+import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
 import com.ruoyi.purchase.pojo.PurchaseReturnOrderProducts;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import jakarta.validation.constraints.NotNull;
+import java.util.List;
 
 /**
  * <p>
@@ -14,5 +19,5 @@
  */
 @Mapper
 public interface PurchaseReturnOrderProductsMapper extends BaseMapper<PurchaseReturnOrderProducts> {
-
+    List<SimpleReturnOrderGroupDto> getReturnOrderGroupListByProductIds(@NotNull @Param("productIds") List<Long> productIds);
 }
diff --git a/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrdersMapper.java b/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrdersMapper.java
index f0e0227..a680c12 100644
--- a/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrdersMapper.java
+++ b/src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrdersMapper.java
@@ -2,6 +2,7 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
 import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ruoyi.purchase.vo.PurchaseReturnOrderVo;
@@ -18,5 +19,5 @@
  */
 @Mapper
 public interface PurchaseReturnOrdersMapper extends BaseMapper<PurchaseReturnOrders> {
-    IPage<PurchaseReturnOrderVo> listPage(Page page, @Param("params") PurchaseReturnOrders purchaseReturnOrder);
+    IPage<PurchaseReturnOrderVo> listPage(Page page, @Param("params") PurchaseReturnOrderDto purchaseReturnOrder);
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java b/src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java
index bcc868d..0d9eb46 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java
@@ -1,5 +1,6 @@
 package com.ruoyi.purchase.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
@@ -110,4 +111,11 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java b/src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java
index 803d600..a84cf04 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java
@@ -1,5 +1,6 @@
 package com.ruoyi.purchase.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
@@ -102,4 +103,11 @@
      */
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Date updateTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java b/src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java
index f7cae28..fdd7503 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java
@@ -1,5 +1,6 @@
 package com.ruoyi.purchase.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
@@ -127,4 +128,11 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
index e01db26..d937bad 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -137,26 +137,33 @@
     private String phoneNumber;
 
     @TableField(exist = false)
-    @ApiModelProperty("鏉ョエ閲戦")
+    @Schema(description = "鏉ョエ閲戦")
     private String receiptPaymentAmount;
 
-    @ApiModelProperty("鏈潵绁ㄩ噾棰�")
+    @Schema(description = "鏈潵绁ㄩ噾棰�")
     @TableField(exist = false)
     private String unReceiptPaymentAmount;
 
-    @ApiModelProperty("鏂囦欢绫诲瀷  鍙� 4")
+    @Schema(description = "鏂囦欢绫诲瀷  鍙� 4")
     @TableField(exist = false)
     private Integer type;
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     private String paymentMethod;
-    @ApiModelProperty("瀹℃壒鐘舵��  1-寰呭鏍革紝2-瀹℃壒涓紝3-瀹℃壒閫氳繃锛�4-瀹℃壒澶辫触,5琛ㄧず鏄ā鏉�")
+    @Schema(description = "瀹℃壒鐘舵��  1-寰呭鏍革紝2-瀹℃壒涓紝3-瀹℃壒閫氳繃锛�4-瀹℃壒澶辫触,5琛ㄧず鏄ā鏉�")
     @Excel(name = "瀹℃壒鐘舵��", readConverterExp = "1=寰呭鏍�,2=瀹℃壒涓�,3=瀹℃壒閫氳繃,4=瀹℃壒澶辫触")
     private Integer approvalStatus;
 
-    @ApiModelProperty(value = "妯℃澘鍚嶇О")
+    @Schema(description = "妯℃澘鍚嶇О")
     private String templateName;
-    @ApiModelProperty(value = "瀹℃壒浜篿d")
+    @Schema(description = "瀹℃壒浜篿d")
     private String approveUserIds;
 
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerTemplate.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerTemplate.java
index 2bb53a4..018c38e 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerTemplate.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedgerTemplate.java
@@ -1,5 +1,6 @@
 package com.ruoyi.purchase.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -11,8 +12,7 @@
 import java.util.Date;
 import java.util.List;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -27,70 +27,77 @@
 @Getter
 @Setter
 @TableName("purchase_ledger_template")
-@ApiModel(value = "PurchaseLedgerTemplate瀵硅薄", description = "閲囪喘鍙拌处妯℃澘")
+@Schema(name = "PurchaseLedgerTemplate瀵硅薄", description = "閲囪喘鍙拌处妯℃澘")
 public class PurchaseLedgerTemplate implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("鑷涓婚敭ID")
+    @Schema(description = "鑷涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("閲囪喘鍚堝悓鍙�")
+    @Schema(description = "閲囪喘鍚堝悓鍙�")
     private String purchaseContractNumber;
 
-    @ApiModelProperty("渚涘簲鍟嗗悕绉癷d")
+    @Schema(description = "渚涘簲鍟嗗悕绉癷d")
     private Long supplierId;
 
-    @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+    @Schema(description = "渚涘簲鍟嗗悕绉�")
     private String supplierName;
 
-    @ApiModelProperty("褰曞叆浜篿d")
+    @Schema(description = "褰曞叆浜篿d")
     private Integer recorderId;
 
-    @ApiModelProperty("褰曞叆浜哄鍚�")
+    @Schema(description = "褰曞叆浜哄鍚�")
     private String recorderName;
 
-    @ApiModelProperty("閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     private String salesContractNo;
 
-    @ApiModelProperty("椤圭洰鍚嶇О")
+    @Schema(description = "椤圭洰鍚嶇О")
     private String projectName;
 
-    @ApiModelProperty("褰曞叆鏃ユ湡")
+    @Schema(description = "褰曞叆鏃ユ湡")
     private Date entryDate;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remarks;
 
-    @ApiModelProperty("璁板綍鍒涘缓鏃堕棿")
+    @Schema(description = "璁板綍鍒涘缓鏃堕棿")
     private Date createdAt;
 
-    @ApiModelProperty("璁板綍鏈�鍚庢洿鏂版椂闂�")
+    @Schema(description = "璁板綍鏈�鍚庢洿鏂版椂闂�")
     private Date updatedAt;
 
-    @ApiModelProperty("鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�")
+    @Schema(description = "鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�")
     private Integer salesLedgerId;
 
-    @ApiModelProperty("鍚堝悓閲戦")
+    @Schema(description = "鍚堝悓閲戦")
     private BigDecimal contractAmount;
 
-    @ApiModelProperty("涓氬姟鍛�")
+    @Schema(description = "涓氬姟鍛�")
     private String businessPerson;
 
-    @ApiModelProperty("涓氬姟鍛榠d")
+    @Schema(description = "涓氬姟鍛榠d")
     private Integer businessPersonId;
 
-    @ApiModelProperty("褰曞叆浜虹數璇�")
+    @Schema(description = "褰曞叆浜虹數璇�")
     private String phoneNumber;
 
     private String paymentMethod;
 
     private Date executionDate;
 
-    @ApiModelProperty("妯℃澘鍚嶇О")
+    @Schema(description = "妯℃澘鍚嶇О")
     private String templateName;
 
     @TableField(exist = false)
     private List<SalesLedgerProductTemplate> productList;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrderProducts.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrderProducts.java
index da9e769..2a1b172 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrderProducts.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrderProducts.java
@@ -8,8 +8,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -24,7 +23,7 @@
 @Getter
 @Setter
 @TableName("purchase_return_order_products")
-@ApiModel(value = "PurchaseReturnOrderProducts瀵硅薄", description = "")
+@Schema(name = "PurchaseReturnOrderProducts瀵硅薄", description = "")
 public class PurchaseReturnOrderProducts implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -32,20 +31,27 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("閫�璐у崟id")
+    @Schema(description = "閫�璐у崟id")
     private Long purchaseReturnOrderId;
 
-    @ApiModelProperty("閲囪喘浜у搧id")
+    @Schema(description = "閲囪喘浜у搧id")
     private Long salesLedgerProductId;
 
-    @ApiModelProperty("閫�璐ф暟閲�")
+    @Schema(description = "閫�璐ф暟閲�")
     private BigDecimal returnQuantity;
 
-    @ApiModelProperty("褰曞叆鏃堕棿")
+    @Schema(description = "褰曞叆鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java
index 3de6e3d..a89317b 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java
@@ -11,10 +11,10 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -27,7 +27,7 @@
 @Getter
 @Setter
 @TableName("purchase_return_orders")
-@ApiModel(value = "PurchaseReturnOrders瀵硅薄", description = "閲囪喘閫�璐у崟")
+@Schema(name = "PurchaseReturnOrders瀵硅薄", description = "閲囪喘閫�璐у崟")
 public class PurchaseReturnOrders implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -35,51 +35,84 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("閫�璐у崟缂栧彿")
+    @Schema(description = "閫�璐у崟缂栧彿")
     private String no;
 
-    @ApiModelProperty("閫�璐ф柟寮� 0閫�璐ч��娆� 1鎷掓敹")
+    @Schema(description = "閫�璐ф柟寮� 0閫�璐ч��娆� 1鎷掓敹")
     private Integer returnType;
 
-    @ApiModelProperty("渚涘簲鍟唅d")
+    @Schema(description = "渚涘簲鍟唅d")
     private Long supplierId;
 
-    @ApiModelProperty("椤圭洰id")
+    @Schema(description = "椤圭洰id")
     private Long projectId;
 
-    @ApiModelProperty("椤圭洰闃舵")
+    @Schema(description = "椤圭洰闃舵")
     private Integer projectPhase;
 
-    @ApiModelProperty("鍒跺崟鏃ユ湡")
+    @Schema(description = "鍒跺崟鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     private LocalDate preparedAt;
 
-    @ApiModelProperty("鍒跺崟浜篿d")
+    @Schema(description = "鍒跺崟浜篿d")
     private Long preparedUserId;
 
-    @ApiModelProperty("閫�鏂欎汉id")
+    @Schema(description = "鍒跺崟浜哄悕绉�")
+    private String preparedUserName;
+
+    @Schema(description = "閫�鏂欎汉id")
     private Long returnUserId;
 
-    @ApiModelProperty("閲囪喘璁㈠崟id")
+    @Schema(description = "閫�鏂欎汉鍚嶇О")
+    private String returnUserName;
+
+    @Schema(description = "閲囪喘璁㈠崟id")
     private Long purchaseLedgerId;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("'鏁村崟鎶樻墸棰�'")
+    @Schema(description = "'鏁村崟鎶樻墸棰�'")
     private BigDecimal totalDiscountAmount;
 
-    @ApiModelProperty("'鏁村崟鎶樻墸鐜�'")
+    @Schema(description = "'鏁村崟鎶樻墸鐜�'")
     private BigDecimal totalDiscountRate;
 
-    @ApiModelProperty("'鎴愪氦閲戦'")
+    @Schema(description = "'鎴愪氦閲戦'")
     private BigDecimal totalAmount;
 
-    @ApiModelProperty("褰曞叆鏃堕棿")
+    @Schema(description = "褰曞叆鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
+
+    @Schema(description = "鏀跺叆绫诲瀷")
+    @TableField(value = "income_type")
+    private Integer incomeType;
+
+
+    /**
+     *
+     */
+    @TableField(value = "create_user",fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(value = "update_user",fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(value = "create_user_name", fill = FieldFill.INSERT)
+    private String createUserName;
+
+    @TableField(value = "update_user_name", fill = FieldFill.INSERT_UPDATE)
+    private String updateUserName;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/SalesLedgerProductTemplate.java b/src/main/java/com/ruoyi/purchase/pojo/SalesLedgerProductTemplate.java
index 1c47d7b..3f1690c 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/SalesLedgerProductTemplate.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/SalesLedgerProductTemplate.java
@@ -1,13 +1,14 @@
 package com.ruoyi.purchase.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -22,55 +23,55 @@
 @Getter
 @Setter
 @TableName("sales_ledger_product_template")
-@ApiModel(value = "SalesLedgerProductTemplate瀵硅薄", description = "浜у搧淇℃伅妯℃澘")
+@Schema(name = "SalesLedgerProductTemplate瀵硅薄", description = "浜у搧淇℃伅妯℃澘")
 public class SalesLedgerProductTemplate implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("浜у搧淇℃伅涓婚敭")
+    @Schema(description = "浜у搧淇℃伅涓婚敭")
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鍏宠仈鍙拌处涓昏〃涓婚敭")
+    @Schema(description = "鍏宠仈鍙拌处涓昏〃涓婚敭")
     private Integer salesLedgerId;
 
-    @ApiModelProperty("浜у搧澶х被")
+    @Schema(description = "浜у搧澶х被")
     private String productCategory;
 
-    @ApiModelProperty("瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     private String specificationModel;
 
-    @ApiModelProperty("鍗曚綅")
+    @Schema(description = "鍗曚綅")
     private String unit;
 
-    @ApiModelProperty("鏁伴噺")
+    @Schema(description = "鏁伴噺")
     private BigDecimal quantity;
 
-    @ApiModelProperty("鏈�浣庡簱瀛�")
+    @Schema(description = "鏈�浣庡簱瀛�")
     private BigDecimal minStock;
 
-    @ApiModelProperty("绋庣巼")
+    @Schema(description = "绋庣巼")
     private BigDecimal taxRate;
 
-    @ApiModelProperty("鍚◣鍗曚环")
+    @Schema(description = "鍚◣鍗曚环")
     private BigDecimal taxInclusiveUnitPrice;
 
-    @ApiModelProperty("鍚◣鎬讳环")
+    @Schema(description = "鍚◣鎬讳环")
     private BigDecimal taxInclusiveTotalPrice;
 
-    @ApiModelProperty("涓嶅惈绋庢�讳环")
+    @Schema(description = "涓嶅惈绋庢�讳环")
     private BigDecimal taxExclusiveTotalPrice;
 
-    @ApiModelProperty("鍙戠エ绫诲瀷")
+    @Schema(description = "鍙戠エ绫诲瀷")
     private String invoiceType;
 
-    @ApiModelProperty("1.閿�鍞彴璐︼紝2.閲囪喘鍙拌处")
+    @Schema(description = "1.閿�鍞彴璐︼紝2.閲囪喘鍙拌处")
     private Integer type;
 
-    @ApiModelProperty("浜у搧id")
+    @Schema(description = "浜у搧id")
     private Integer productId;
 
-    @ApiModelProperty("鍨嬪彿id")
+    @Schema(description = "鍨嬪彿id")
     private Integer productModelId;
 
     private String register;
@@ -79,6 +80,13 @@
 
     private BigDecimal warnNum;
 
-    @ApiModelProperty("鏄惁鎺ㄩ�佽川妫�")
+    @Schema(description = "鏄惁鎺ㄩ�佽川妫�")
     private Boolean isChecked;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java b/src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java
index e79796a..0dcf7c6 100644
--- a/src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java
+++ b/src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -140,12 +140,12 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty(value = "宸蹭粯娆炬�婚噾棰�")
+    @Schema(description = "宸蹭粯娆炬�婚噾棰�")
     @TableField(exist = false)
     @Excel(name = "宸蹭粯娆炬�婚噾棰�")
     private BigDecimal paymentAmountTotal;
 
-    @ApiModelProperty(value = "鏈粯娆炬�婚噾棰�")
+    @Schema(description = "鏈粯娆炬�婚噾棰�")
     @TableField(exist = false)
     @Excel(name = "鏈粯娆炬�婚噾棰�")
     private BigDecimal unPaymentAmountTotal;
@@ -161,6 +161,13 @@
     @TableField(exist = false)
     private String supplierNameOrContractNo;
 
-    @ApiModelProperty(value = "褰曞叆鏃堕棿")
+    @Schema(description = "褰曞叆鏃堕棿")
     private LocalDate enterDate;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java b/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
index 34d19b3..d09050e 100644
--- a/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
+++ b/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
@@ -7,9 +7,9 @@
 import com.ruoyi.purchase.dto.PurchaseLedgerDto;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.IOException;
 import java.util.List;
 
 /**
@@ -24,6 +24,8 @@
 
     int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws Exception;
 
+    void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct);
+
     int deletePurchaseLedgerByIds(Long[] ids);
 
     PurchaseLedgerDto getPurchaseById(PurchaseLedgerDto purchaseLedgerDto);
diff --git a/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java b/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java
index 6ec7650..dc68108 100644
--- a/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java
+++ b/src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrdersService.java
@@ -5,7 +5,10 @@
 import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
 import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.purchase.vo.PurchaseReturnDetailsVo;
 import com.ruoyi.purchase.vo.PurchaseReturnOrderVo;
+
+import jakarta.validation.constraints.NotNull;
 
 /**
  * <p>
@@ -19,4 +22,9 @@
     IPage<PurchaseReturnOrderVo> listPage(Page page, PurchaseReturnOrderDto purchaseReturnOrderDto);
 
     Boolean add(PurchaseReturnOrderDto purchaseReturnOrderDto);
+
+
+    PurchaseReturnDetailsVo getPurchaseReturnOrderDtoById(@NotNull Long id);
+
+    void deleteById(@NotNull Long id);
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java
index 0187823..8b76b1a 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java
@@ -50,10 +50,7 @@
 
     private final CommonFileMapper commonFileMapper;
 
-    private final TempFileMapper tempFileMapper;
 
-    @Value("${file.upload-dir}")
-    private String uploadDir;
 
     @Override
     public List<InvoicePurchaseDto> selectInvoicePurchaseList(InvoicePurchaseDto invoicePurchaseDto) {
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java
index 55aea8f..d5875e3 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java
@@ -6,7 +6,6 @@
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.mapper.AccountExpenseMapper;
 import com.ruoyi.account.pojo.AccountExpense;
 import com.ruoyi.account.service.AccountExpenseService;
 import com.ruoyi.basic.mapper.SupplierManageMapper;
@@ -17,18 +16,18 @@
 import com.ruoyi.purchase.dto.PaymentHistoryRecordVo;
 import com.ruoyi.purchase.dto.PaymentLedgerDto;
 import com.ruoyi.purchase.dto.PaymentRegistrationDto;
-import com.ruoyi.purchase.mapper.*;
+import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
+import com.ruoyi.purchase.mapper.ProductRecordMapper;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
 import com.ruoyi.purchase.pojo.PaymentRegistration;
 import com.ruoyi.purchase.pojo.ProductRecord;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.purchase.pojo.TicketRegistration;
 import com.ruoyi.purchase.service.IPaymentRegistrationService;
-import com.ruoyi.sales.mapper.SalesLedgerMapper;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.ReceiptPayment;
-import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import lombok.AllArgsConstructor;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
@@ -47,23 +46,16 @@
  * @date 2025-05-15
  */
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 public class PaymentRegistrationServiceImpl extends ServiceImpl<PaymentRegistrationMapper, PaymentRegistration> implements IPaymentRegistrationService {
-    private PaymentRegistrationMapper paymentRegistrationMapper;
 
-    private PurchaseLedgerMapper purchaseLedgerMapper;
-
-    private SalesLedgerMapper salesLedgerMapper;
-
-    private SupplierManageMapper supplierManageMapper;
-
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-
-    private TicketRegistrationMapper ticketRegistrationMapper;
-
-    private ProductRecordMapper productRecordMapper;
-
-    private AccountExpenseService accountExpenseService;
+    private final PaymentRegistrationMapper paymentRegistrationMapper;
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
+    private final SupplierManageMapper supplierManageMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final TicketRegistrationMapper ticketRegistrationMapper;
+    private final ProductRecordMapper productRecordMapper;
+    private final AccountExpenseService accountExpenseService;
 
     /**
      * 鏌ヨ浠樻鐧昏
@@ -131,7 +123,8 @@
             accountExpense.setSupplierName(purchaseLedger.getSupplierName());
             accountExpense.setExpenseMoney(paymentRegistration.getCurrentPaymentAmount());
             accountExpense.setExpenseDescribed("浠樻鏀嚭");
-            accountExpense.setExpenseMethod("0");
+
+            accountExpense.setExpenseMethod(paymentRegistration.getPaymentMethod());
             accountExpense.setBusinessId(paymentRegistration.getId());
             accountExpense.setBusinessType(1);
             accountExpense.setInputTime(new Date());
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/ProcurementBusinessSummaryServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/ProcurementBusinessSummaryServiceImpl.java
index ea0a3f8..b8ec1d4 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/ProcurementBusinessSummaryServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/ProcurementBusinessSummaryServiceImpl.java
@@ -2,12 +2,10 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.purchase.dto.ProcurementBusinessSummaryDto;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -16,10 +14,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class ProcurementBusinessSummaryServiceImpl {
 
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
 
     public IPage<ProcurementBusinessSummaryDto> listPage(Page page, ProcurementBusinessSummaryDto procurementBusinessSummaryDto) {
         return salesLedgerProductMapper.procurementBusinessSummaryListPage(page, procurementBusinessSummaryDto);
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java
index fda5910..961e759 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java
@@ -10,20 +10,16 @@
 import com.ruoyi.purchase.dto.ProductRecordDto;
 import com.ruoyi.purchase.dto.TicketRegistrationDto;
 import com.ruoyi.purchase.mapper.ProductRecordMapper;
-import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
 import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
 import com.ruoyi.purchase.pojo.ProductRecord;
-import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.purchase.pojo.TicketRegistration;
 import com.ruoyi.purchase.service.IProductRecordService;
 import com.ruoyi.sales.mapper.CommonFileMapper;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.AllArgsConstructor;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -37,20 +33,12 @@
  * @date 2025-05-23
  */
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 public class ProductRecordServiceImpl extends ServiceImpl<ProductRecordMapper, ProductRecord> implements IProductRecordService {
 
-    @Autowired
-    private ProductRecordMapper productRecordMapper;
-
-    @Autowired
-    private CommonFileMapper commonFileMapper;
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-    @Autowired
-    private PurchaseLedgerMapper purchaseLedgerMapper;
-
-
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final ProductRecordMapper productRecordMapper;
+    private final CommonFileMapper commonFileMapper;
     /**
      * 鏌ヨ閲囪喘鍙拌处浜у搧寮�绁ㄨ褰�
      *
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index d71b3bb..c4a48cd 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -1,36 +1,31 @@
 package com.ruoyi.purchase.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.pojo.AccountExpense;
-import com.ruoyi.account.pojo.AccountIncome;
-import com.ruoyi.account.service.AccountExpenseService;
-import com.ruoyi.account.service.AccountIncomeService;
+import com.ruoyi.approve.bean.vo.ApproveProcessVO;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
-import com.ruoyi.approve.vo.ApproveProcessVO;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.basic.mapper.ProductMapper;
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.mapper.SupplierManageMapper;
-import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.basic.pojo.SupplierManage;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.exception.base.BaseException;
-import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.other.pojo.TempFile;
 import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
 import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
 import com.ruoyi.project.system.domain.SysUser;
@@ -38,14 +33,27 @@
 import com.ruoyi.purchase.dto.PurchaseLedgerDto;
 import com.ruoyi.purchase.dto.PurchaseLedgerImportDto;
 import com.ruoyi.purchase.dto.PurchaseLedgerProductImportDto;
-import com.ruoyi.purchase.mapper.*;
-import com.ruoyi.purchase.pojo.*;
+import com.ruoyi.purchase.mapper.PaymentRegistrationMapper;
+import com.ruoyi.purchase.mapper.ProductRecordMapper;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.mapper.TicketRegistrationMapper;
+import com.ruoyi.purchase.pojo.PaymentRegistration;
+import com.ruoyi.purchase.pojo.ProductRecord;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.purchase.pojo.TicketRegistration;
 import com.ruoyi.purchase.service.IPurchaseLedgerService;
-import com.ruoyi.quality.mapper.*;
-import com.ruoyi.quality.pojo.*;
-import com.ruoyi.sales.dto.SalesLedgerImportDto;
-import com.ruoyi.sales.dto.SalesLedgerProductImportDto;
-import com.ruoyi.sales.mapper.*;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.mapper.QualityInspectParamMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardParamMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.quality.pojo.QualityTestStandard;
+import com.ruoyi.quality.pojo.QualityTestStandardParam;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
 import com.ruoyi.sales.pojo.SalesLedger;
@@ -53,23 +61,15 @@
 import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
@@ -86,72 +86,32 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class PurchaseLedgerServiceImpl extends ServiceImpl<PurchaseLedgerMapper, PurchaseLedger> implements IPurchaseLedgerService {
-    @Autowired
-    private  AccountExpenseService accountExpenseService;
-    @Autowired
-    private  PurchaseLedgerMapper purchaseLedgerMapper;
 
-    @Autowired
-    private  SalesLedgerMapper salesLedgerMapper;
-    @Autowired
-    private  SalesLedgerProductMapper salesLedgerProductMapper;
-
-    @Autowired
-    private  SysUserMapper userMapper;
-
-    @Autowired
-    private  TempFileMapper tempFileMapper;
-
-    @Autowired
-    private  CommonFileMapper commonFileMapper;
-
-    @Autowired
-    private  SupplierManageMapper supplierManageMapper;
-
-    @Autowired
-    private  ProductMapper productMapper;
-
-    @Autowired
-    private  ProductModelMapper productModelMapper;
-
-    @Autowired
-    private  SysUserMapper sysUserMapper;
-
-    @Autowired
-    private  TicketRegistrationMapper ticketRegistrationMapper;
-
-    @Autowired
-    private  ProductRecordMapper productRecordMapper;
-
-    @Autowired
-    private  PaymentRegistrationMapper paymentRegistrationMapper;
-    @Autowired
-    private  InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-    @Autowired
-    private  StringRedisTemplate redisTemplate;
-    @Autowired
-    private  QualityInspectMapper qualityInspectMapper;
-    @Autowired
-    private  CommonFileServiceImpl commonFileService;
-    @Autowired
-    private  QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
-    @Autowired
-    private  QualityTestStandardParamMapper qualityTestStandardParamMapper;
-    @Autowired
-    private  QualityTestStandardMapper qualityTestStandardMapper;
-    @Autowired
-    private  QualityInspectParamMapper qualityInspectParamMapper;
-    @Autowired
-    private  ApproveProcessServiceImpl approveProcessService;
-    @Autowired
-    private  ProcurementRecordMapper procurementRecordStorageMapper;
-    @Autowired
-    private  PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
-    @Autowired
-    private  SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
-    @Value("${file.upload-dir}")
-    private String uploadDir;
+    private final PurchaseLedgerMapper purchaseLedgerMapper;
+    private final SalesLedgerMapper salesLedgerMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final SysUserMapper userMapper;
+    private final TempFileMapper tempFileMapper;
+    private final CommonFileMapper commonFileMapper;
+    private final SupplierManageMapper supplierManageMapper;
+    private final ProductMapper productMapper;
+    private final ProductModelMapper productModelMapper;
+    private final SysUserMapper sysUserMapper;
+    private final TicketRegistrationMapper ticketRegistrationMapper;
+    private final ProductRecordMapper productRecordMapper;
+    private final PaymentRegistrationMapper paymentRegistrationMapper;
+    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
+    private final StringRedisTemplate redisTemplate;
+    private final QualityInspectMapper qualityInspectMapper;
+    private final CommonFileServiceImpl commonFileService;
+    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
+    private final QualityTestStandardMapper qualityTestStandardMapper;
+    private final QualityInspectParamMapper qualityInspectParamMapper;
+    private final ApproveProcessServiceImpl approveProcessService;
+    private final ProcurementRecordMapper procurementRecordStorageMapper;
+    private final FileUtil fileUtil;
 
     @Override
     public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) {
@@ -159,21 +119,35 @@
         if (StringUtils.isNotBlank(purchaseLedger.getPurchaseContractNumber())) {
             queryWrapper.like(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber());
         }
+        if(purchaseLedger.getSupplierId()!=null){
+            queryWrapper.eq(PurchaseLedger::getSupplierId, purchaseLedger.getSupplierId());
+        }
+        if (purchaseLedger.getApprovalStatus() != null) {
+            queryWrapper.eq(PurchaseLedger::getApprovalStatus, purchaseLedger.getApprovalStatus());
+        }
         return purchaseLedgerMapper.selectList(queryWrapper);
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws Exception {
-
+        PurchaseLedger purchaseLedger = new PurchaseLedger();
         SalesLedger salesLedger = salesLedgerMapper.selectById(purchaseLedgerDto.getSalesLedgerId());
         //褰曞叆浜�
         SysUser sysUser = userMapper.selectUserById(purchaseLedgerDto.getRecorderId());
+        if (ObjectUtils.isNotEmpty(sysUser)) {
+            purchaseLedger.setRecorderName(sysUser.getNickName());
+            purchaseLedger.setPhoneNumber(sysUser.getPhonenumber());
+        }else {
+            purchaseLedger.setRecorderName(SecurityUtils.getLoginUser().getNickName());
+            SysUser sysUser1 = userMapper.selectUserById(SecurityUtils.getUserId());
+            purchaseLedger.setPhoneNumber(sysUser1.getPhonenumber());
+        }
 
         SupplierManage supplierManage = supplierManageMapper.selectById(purchaseLedgerDto.getSupplierId());
 
         // DTO杞珽ntity
-        PurchaseLedger purchaseLedger = new PurchaseLedger();
+
         BeanUtils.copyProperties(purchaseLedgerDto, purchaseLedger);
         LoginUser loginUser = SecurityUtils.getLoginUser();
         if (ObjectUtils.isNotEmpty(loginUser) && null != loginUser.getTenantId()) {
@@ -183,8 +157,7 @@
         purchaseLedger.setSalesLedgerId(ObjectUtils.isNotEmpty(salesLedger) ? salesLedger.getId() : -1);
         purchaseLedger.setSupplierName(supplierManage.getSupplierName());
         purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId());
-        purchaseLedger.setRecorderName(sysUser.getNickName());
-        purchaseLedger.setPhoneNumber(sysUser.getPhonenumber());
+
         purchaseLedger.setApprovalStatus(1);
         // 3. 鏂板鎴栨洿鏂颁富琛�
         if (purchaseLedger.getId() == null) {
@@ -201,7 +174,7 @@
             }
             purchaseLedgerMapper.updateById(purchaseLedger);
         }
-        // 6.閲囪喘瀹℃牳鏂板
+        // 6.閲囪喘瀹℃牳鏂板锛涘鎵圭鐞嗘湭閰嶇疆閲囪喘瀹℃壒浜烘椂锛屽鎵规湇鍔′細鑷姩缃负瀹℃壒閫氳繃銆�
         addApproveByPurchase(loginUser, purchaseLedger);
 
         // 4. 澶勭悊瀛愯〃鏁版嵁
@@ -219,9 +192,7 @@
 //            }
 //        }
         // 5. 杩佺Щ涓存椂鏂囦欢鍒版寮忕洰褰�
-        if (purchaseLedgerDto.getTempFileIds() != null && !purchaseLedgerDto.getTempFileIds().isEmpty()) {
-            migrateTempFilesToFormal(purchaseLedger.getId(), purchaseLedgerDto.getTempFileIds());
-        }
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.PURCHASE_LEDGER, purchaseLedger.getId(), purchaseLedgerDto.getStorageBlobDTOS());
         return 1;
     }
 
@@ -258,6 +229,7 @@
         if (products == null || products.isEmpty()) {
             throw new BaseException("浜у搧淇℃伅涓嶅瓨鍦�");
         }
+        Integer ledgerType = type == null ? 2 : type;
 
         // 鎻愬墠鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑ID
         Set<Long> productIds = products.stream()
@@ -309,14 +281,14 @@
         // 鎵ц鏇存柊鎿嶄綔
         if (!updateList.isEmpty()) {
             for (SalesLedgerProduct product : updateList) {
-                product.setType(type);
+                product.setType(ledgerType);
                 salesLedgerProductMapper.updateById(product);
             }
         }
         // 鎵ц鎻掑叆鎿嶄綔
         if (!insertList.isEmpty()) {
             for (SalesLedgerProduct salesLedgerProduct : insertList) {
-                salesLedgerProduct.setType(type);
+                salesLedgerProduct.setType(ledgerType);
                 Date entryDate = purchaseLedger.getEntryDate();
 
                 LocalDateTime localDateTime = entryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -338,80 +310,6 @@
         if (salesLedgerId != null) {
             // 鐩存帴鏇存柊鎸囧畾ID鐨勮褰曠殑contractAmount瀛楁涓簍otalTaxInclusiveAmount
             purchaseLedgerMapper.updateContractAmountById(salesLedgerId, totalTaxInclusiveAmount);
-        }
-    }
-
-    /**
-     * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
-     *
-     * @param businessId  涓氬姟ID锛堥攢鍞彴璐D锛�
-     * @param tempFileIds 涓存椂鏂囦欢ID鍒楄〃
-     * @throws IOException 鏂囦欢鎿嶄綔寮傚父
-     */
-    private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException {
-        if (CollectionUtils.isEmpty(tempFileIds)) {
-            return;
-        }
-
-        // 鏋勫缓姝e紡鐩綍璺緞锛堟寜涓氬姟绫诲瀷鍜屾棩鏈熷垎缁勶級
-        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
-
-        Path formalDirPath = Paths.get(formalDir);
-
-        // 纭繚姝e紡鐩綍瀛樺湪锛堥�掑綊鍒涘缓锛�
-        if (!Files.exists(formalDirPath)) {
-            Files.createDirectories(formalDirPath);
-        }
-
-        for (String tempFileId : tempFileIds) {
-            // 鏌ヨ涓存椂鏂囦欢璁板綍
-            TempFile tempFile = tempFileMapper.selectById(tempFileId);
-            if (tempFile == null) {
-                log.warn("涓存椂鏂囦欢涓嶅瓨鍦紝璺宠繃澶勭悊: {}", tempFileId);
-                continue;
-            }
-
-            // 鏋勫缓姝e紡鏂囦欢鍚嶏紙鍖呭惈涓氬姟ID鍜屾椂闂存埑锛岄伩鍏嶅啿绐侊級
-            String originalFilename = tempFile.getOriginalName();
-            String fileExtension = FilenameUtils.getExtension(originalFilename);
-            String formalFilename = businessId + "_" +
-                    System.currentTimeMillis() + "_" +
-                    UUID.randomUUID().toString().substring(0, 8) +
-                    (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
-
-            Path formalFilePath = formalDirPath.resolve(formalFilename);
-
-            try {
-                // 鎵ц鏂囦欢杩佺Щ锛堜娇鐢ㄥ師瀛愭搷浣滅‘淇濆畨鍏ㄦ�э級
-//                Files.move(
-//                        Paths.get(tempFile.getTempPath()),
-//                        formalFilePath,
-//                        StandardCopyOption.REPLACE_EXISTING,
-//                        StandardCopyOption.ATOMIC_MOVE
-//                );
-                // 鍘熷瓙绉诲姩澶辫触锛屼娇鐢ㄥ鍒�+鍒犻櫎
-                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
-                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-
-                // 鏇存柊鏂囦欢璁板綍锛堝叧鑱斿埌涓氬姟ID锛�
-                CommonFile fileRecord = new CommonFile();
-                fileRecord.setCommonId(businessId);
-                fileRecord.setName(originalFilename);
-                fileRecord.setUrl(formalFilePath.toString());
-                fileRecord.setCreateTime(LocalDateTime.now());
-                fileRecord.setType(FileNameType.PURCHASE.getValue());
-                commonFileMapper.insert(fileRecord);
-
-                // 鍒犻櫎涓存椂鏂囦欢璁板綍
-                tempFileMapper.deleteById(tempFile);
-
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-            } catch (IOException e) {
-                log.error("鏂囦欢杩佺Щ澶辫触: {}", tempFile.getTempPath(), e);
-                // 鍙�夋嫨鍥炴粴浜嬪姟鎴栬褰曞け璐ユ枃浠�
-                throw new IOException("鏂囦欢杩佺Щ寮傚父", e);
-            }
         }
     }
 
@@ -512,11 +410,6 @@
                 .eq(SalesLedgerProduct::getType, purchaseLedgerDto.getType());
         List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper);
 
-        // 3.鏌ヨ涓婁紶鏂囦欢
-        LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>();
-        salesLedgerFileWrapper.eq(CommonFile::getCommonId, purchaseLedger.getId())
-                .eq(CommonFile::getType,FileNameType.PURCHASE.getValue());
-        List<CommonFile> salesLedgerFiles = commonFileMapper.selectList(salesLedgerFileWrapper);
 
         // 4. 杞崲 DTO
         PurchaseLedgerDto resultDto = new PurchaseLedgerDto();
@@ -524,7 +417,7 @@
         if (!products.isEmpty()) {
             resultDto.setHasChildren(true);
             resultDto.setProductData(products);
-            resultDto.setSalesLedgerFiles(salesLedgerFiles);
+            resultDto.setStorageBlobVOS(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.PURCHASE_LEDGER, purchaseLedger.getId()));
         }
         return resultDto;
     }
@@ -709,20 +602,21 @@
                 if(salesLedger1 != null){
                     salesLedger.setSalesLedgerId(salesLedger1.getId());
                 }
-                // 閲囪喘瀹℃牳
-                // 閫氳繃鏄电О鑾峰彇鐢ㄦ埛ID
-                String[] split = salesLedger.getApproveUserIds().split("锛�");
-                List<Long> ids = new ArrayList<>();
-                for (int i = 0; i < split.length; i++) {
-                    SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getNickName, split[i])
-                            .last("LIMIT 1"));
-                    if (sysUser != null) {
-                        ids.add(sysUser.getUserId());
+                if (StringUtils.hasText(salesLedger.getApproveUserIds())) {
+                    // 閲囪喘瀹℃牳锛氬巻鍙插鍏ユā鏉夸紶瀹℃壒浜哄鍚嶆椂锛岀户缁吋瀹硅浆鎹负鐢ㄦ埛ID銆�
+                    String[] split = salesLedger.getApproveUserIds().split("锛�");
+                    List<Long> ids = new ArrayList<>();
+                    for (int i = 0; i < split.length; i++) {
+                        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getNickName, split[i])
+                                .last("LIMIT 1"));
+                        if (sysUser != null) {
+                            ids.add(sysUser.getUserId());
+                        }
                     }
+                    // 灏嗛泦鍚堣浆涓哄瓧绗︿覆锛岄殧寮�
+                    String collect = ids.stream().map(Object::toString).collect(Collectors.joining(","));
+                    salesLedger.setApproveUserIds(collect);
                 }
-                // 灏嗛泦鍚堣浆涓哄瓧绗︿覆锛岄殧寮�
-                String collect = ids.stream().map(Object::toString).collect(Collectors.joining(","));
-                salesLedger.setApproveUserIds(collect);
                 purchaseLedgerMapper.insert(salesLedger);
 
                 for (PurchaseLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
@@ -790,6 +684,9 @@
     }
 
     public void addApproveByPurchase(LoginUser loginUser,PurchaseLedger purchaseLedger) throws Exception {
+        if (loginUser == null) {
+            return;
+        }
         ApproveProcessVO approveProcessVO = new ApproveProcessVO();
         approveProcessVO.setApproveType(5);
         approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerTemplateServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerTemplateServiceImpl.java
index d64bd4d..446c995 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerTemplateServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerTemplateServiceImpl.java
@@ -1,11 +1,11 @@
 package com.ruoyi.purchase.service.impl;
 
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.purchase.mapper.PurchaseLedgerTemplateMapper;
 import com.ruoyi.purchase.mapper.SalesLedgerProductTemplateMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedgerTemplate;
-import com.ruoyi.purchase.mapper.PurchaseLedgerTemplateMapper;
 import com.ruoyi.purchase.service.PurchaseLedgerTemplateService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 /**
@@ -17,13 +17,7 @@
  * @since 2026-01-26 11:21:44
  */
 @Service
+@RequiredArgsConstructor
 public class PurchaseLedgerTemplateServiceImpl extends ServiceImpl<PurchaseLedgerTemplateMapper, PurchaseLedgerTemplate> implements PurchaseLedgerTemplateService {
-
-    @Autowired
-    private PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
-
-    @Autowired
-    private SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
-
 
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
index 37c2f5b..e75e986 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
@@ -1,33 +1,53 @@
 package com.ruoyi.purchase.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.account.pojo.AccountIncome;
+import com.ruoyi.account.service.AccountIncomeService;
+import com.ruoyi.common.enums.SaleEnum;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
 import com.ruoyi.purchase.dto.PurchaseReturnOrderProductsDto;
 import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
-import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrderProducts;
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
 import com.ruoyi.purchase.service.PurchaseReturnOrdersService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.purchase.vo.PurchaseReturnDetailsVo;
 import com.ruoyi.purchase.vo.PurchaseReturnOrderVo;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.service.ISalesLedgerService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
 /**
  * <p>
- *  鏈嶅姟瀹炵幇绫�
+ * 鏈嶅姟瀹炵幇绫�
  * </p>
  *
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-03-06 11:44:38
  */
 @Service
+@RequiredArgsConstructor
 public class PurchaseReturnOrdersServiceImpl extends ServiceImpl<PurchaseReturnOrdersMapper, PurchaseReturnOrders> implements PurchaseReturnOrdersService {
-    @Autowired
-    private PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
-    @Autowired
-    private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
+
+    private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
+    private final PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
+    private final ISalesLedgerService salesLedgerService;
+    private final AccountIncomeService accountIncomeService;
 
     @Override
     public IPage<PurchaseReturnOrderVo> listPage(Page page, PurchaseReturnOrderDto purchaseReturnOrderDto) {
@@ -38,14 +58,74 @@
     @Transactional(rollbackFor = Exception.class)
     public Boolean add(PurchaseReturnOrderDto purchaseReturnOrderDto) {
         this.save(purchaseReturnOrderDto);
+
         if (!purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos().isEmpty()) {
-            for (PurchaseReturnOrderProductsDto purchaseReturnOrderProductsDto :purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos()) {
+            for (PurchaseReturnOrderProductsDto purchaseReturnOrderProductsDto : purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos()) {
                 purchaseReturnOrderProductsDto.setSalesLedgerProductId(purchaseReturnOrderProductsDto.getSalesLedgerProductId());
                 purchaseReturnOrderProductsDto.setPurchaseReturnOrderId(purchaseReturnOrderDto.getId());
                 purchaseReturnOrderProductsDto.setReturnQuantity(purchaseReturnOrderProductsDto.getReturnQuantity());
+                // 杩欓噷涓烘柊澧炲洜姝d涓簄ull
+                purchaseReturnOrderProductsDto.setId(null);
                 purchaseReturnOrderProductsMapper.insert(purchaseReturnOrderProductsDto);
             }
+        }else {
+            throw new RuntimeException("璇烽�夋嫨閫�璐у晢鍝�");
         }
+
+        // 瀵硅储鍔$鐞嗗彴璐︽坊鍔犱竴绗旇繘璐︽敹鍏�.
+        AccountIncome accountIncome = new AccountIncome();
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        accountIncome.setInputUser(loginUser.getUsername());
+        accountIncome.setIncomeMoney(purchaseReturnOrderDto.getTotalAmount());
+        accountIncome.setIncomeDate(DateUtils.toDate(purchaseReturnOrderDto.getPreparedAt()));
+        accountIncome.setInputTime(DateUtils.toDate(purchaseReturnOrderDto.getPreparedAt()));
+        accountIncome.setBusinessId(purchaseReturnOrderDto.getId());
+        accountIncome.setBusinessType(1);
+        accountIncome.setIncomeType("4");
+        accountIncome.setCustomerName(purchaseReturnOrderDto.getSupplierName());
+        accountIncome.setIncomeDescribed(purchaseReturnOrderDto.getRemark());
+        accountIncome.setIncomeMethod(String.valueOf(purchaseReturnOrderDto.getIncomeType()));
+        accountIncomeService.save(accountIncome);
         return true;
     }
+
+    @Override
+    public PurchaseReturnDetailsVo getPurchaseReturnOrderDtoById(Long id) {
+        PurchaseReturnOrders purchaseReturnOrders = purchaseReturnOrdersMapper.selectById(id);
+        PurchaseReturnDetailsVo purchaseReturnOrderDto = BeanUtil.copyProperties(purchaseReturnOrders, PurchaseReturnDetailsVo.class);
+        // 鏌ヨ鍑轰粬鍏蜂綋瀵瑰簲鐨勯��璐�
+        LambdaQueryWrapper<PurchaseReturnOrderProducts> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(PurchaseReturnOrderProducts::getPurchaseReturnOrderId, purchaseReturnOrders.getId());
+
+        List<PurchaseReturnOrderProducts> purchaseReturnOrderProducts = purchaseReturnOrderProductsMapper.selectList(queryWrapper);
+        List<PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo> purchaseReturnOrderProductsDetailVos = BeanUtil.copyToList(purchaseReturnOrderProducts, PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo.class);
+        // 鏌ヨ鍑哄搴旂殑鍟嗗搧淇℃伅
+        List<Long> productIds = purchaseReturnOrderProductsDetailVos.stream().map(PurchaseReturnDetailsVo.PurchaseReturnOrderProductsDetailVo::getSalesLedgerProductId).distinct().filter(Objects::nonNull).collect(Collectors.toList());
+        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerService.getSalesLedgerProductListByIds(productIds, SaleEnum.PURCHASE);
+        Map<Long, SalesLedgerProduct> productmap = salesLedgerProducts.stream().collect(Collectors.toMap(SalesLedgerProduct::getId, product -> product));
+        purchaseReturnOrderProductsDetailVos.forEach(purchaseReturnOrderProductsDetailVo -> {
+            purchaseReturnOrderProductsDetailVo.setSalesLedgerProduct(productmap.get(purchaseReturnOrderProductsDetailVo.getSalesLedgerProductId()));
+        });
+
+        purchaseReturnOrderDto.setPurchaseReturnOrderProductsDetailVoList(purchaseReturnOrderProductsDetailVos);
+
+
+        return purchaseReturnOrderDto;
+    }
+
+    @Override
+    @Transactional
+    public void deleteById(Long id) {
+        purchaseReturnOrdersMapper.deleteById(id);
+        LambdaUpdateWrapper<PurchaseReturnOrderProducts> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(PurchaseReturnOrderProducts::getPurchaseReturnOrderId, id);
+        purchaseReturnOrderProductsMapper.delete(updateWrapper);
+
+        // 璐㈠姟
+        LambdaUpdateWrapper<AccountIncome> updateWrapperAccountIncome = new LambdaUpdateWrapper<>();
+        updateWrapperAccountIncome.eq(AccountIncome::getBusinessId, id);
+        updateWrapperAccountIncome.eq(AccountIncome::getBusinessType, 1);
+        updateWrapperAccountIncome.eq(AccountIncome::getIncomeType, 4);
+        accountIncomeService.remove(updateWrapperAccountIncome);
+    }
 }
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java
index ec8716f..a98d924 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java
@@ -14,7 +14,6 @@
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.other.pojo.TempFile;
 import com.ruoyi.purchase.dto.PaymentRegistrationDto;
 import com.ruoyi.purchase.dto.PurchaseLedgerDto;
 import com.ruoyi.purchase.dto.TicketRegistrationDto;
@@ -34,22 +33,17 @@
 import com.ruoyi.sales.service.ISalesLedgerProductService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.io.IOException;
 import java.math.BigDecimal;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -75,14 +69,9 @@
 
     private final ProductRecordMapper productRecordMapper;
 
-    @Autowired
-    private ISalesLedgerProductService salesLedgerProductService;
+    private final ISalesLedgerProductService salesLedgerProductService;
 
-    @Autowired
-    private PaymentRegistrationMapper paymentRegistrationMapper;
-
-    @Value("${file.upload-dir}")
-    private String uploadDir;
+    private final PaymentRegistrationMapper paymentRegistrationMapper;
 
 
     @Override
@@ -178,78 +167,7 @@
                 throw new RuntimeException("浜у搧寮�绁ㄦ暟閮戒负0锛岃妫�鏌�");
             }
         }
-        // 杩佺Щ涓存椂鏂囦欢鍒版寮忕洰褰�
-        if (ticketRegistrationDto.getTempFileIds() != null && !ticketRegistrationDto.getTempFileIds().isEmpty()) {
-            migrateTempFilesToFormal(ticketRegistration.getId(), ticketRegistrationDto.getTempFileIds());
-        }
         return rowsAffected;
-    }
-
-
-    /**
-     * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
-     *
-     * @param businessId  涓氬姟ID锛堥攢鍞彴璐D锛�
-     * @param tempFileIds 涓存椂鏂囦欢ID鍒楄〃
-     * @throws IOException 鏂囦欢鎿嶄綔寮傚父
-     */
-    public void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException {
-        if (CollectionUtils.isEmpty(tempFileIds)) {
-            return;
-        }
-
-        // 鏋勫缓姝e紡鐩綍璺緞锛堟寜涓氬姟绫诲瀷鍜屾棩鏈熷垎缁勶級
-        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
-
-        Path formalDirPath = Paths.get(formalDir);
-
-        // 纭繚姝e紡鐩綍瀛樺湪锛堥�掑綊鍒涘缓锛�
-        if (!Files.exists(formalDirPath)) {
-            Files.createDirectories(formalDirPath);
-        }
-
-        for (String tempFileId : tempFileIds) {
-            // 鏌ヨ涓存椂鏂囦欢璁板綍
-            TempFile tempFile = tempFileMapper.selectById(tempFileId);
-            if (tempFile == null) {
-                log.warn("涓存椂鏂囦欢涓嶅瓨鍦紝璺宠繃澶勭悊: {}", tempFileId);
-                continue;
-            }
-
-            // 鏋勫缓姝e紡鏂囦欢鍚嶏紙鍖呭惈涓氬姟ID鍜屾椂闂存埑锛岄伩鍏嶅啿绐侊級
-            String originalFilename = tempFile.getOriginalName();
-            String fileExtension = FilenameUtils.getExtension(originalFilename);
-            String baseName = FilenameUtils.getBaseName(originalFilename);
-            String formalFilename = businessId + "_" +
-                    System.currentTimeMillis() + "_" +
-                    UUID.randomUUID().toString().substring(0, 8) +baseName+
-                    (com.ruoyi.common.utils.StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
-
-            Path formalFilePath = formalDirPath.resolve(formalFilename);
-
-            try {
-
-                // 鍘熷瓙绉诲姩澶辫触锛屼娇鐢ㄥ鍒�+鍒犻櫎
-                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
-                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-
-                // 鏇存柊鏂囦欢璁板綍锛堝叧鑱斿埌涓氬姟ID锛�
-                CommonFile fileRecord = new CommonFile();
-                fileRecord.setCommonId(businessId);
-                fileRecord.setName(originalFilename);
-                fileRecord.setUrl(formalFilePath.toString());
-                fileRecord.setCreateTime(LocalDateTime.now());
-                fileRecord.setType(4);
-                commonFileMapper.insert(fileRecord);
-
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-            } catch (IOException e) {
-                log.error("鏂囦欢杩佺Щ澶辫触: {}", tempFile.getTempPath(), e);
-                // 鍙�夋嫨鍥炴粴浜嬪姟鎴栬褰曞け璐ユ枃浠�
-                throw new IOException("鏂囦欢杩佺Щ寮傚父", e);
-            }
-        }
     }
 
 
diff --git a/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java
new file mode 100644
index 0000000..02317e6
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnDetailsVo.java
@@ -0,0 +1,38 @@
+package com.ruoyi.purchase.vo;
+
+import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/21
+ * @email 3038525872@qq.com
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PurchaseReturnDetailsVo extends PurchaseReturnOrders implements Serializable {
+
+    private List<PurchaseReturnOrderProductsDetailVo> purchaseReturnOrderProductsDetailVoList;
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class PurchaseReturnOrderProductsDetailVo implements Serializable {
+        private Long id;
+        private BigDecimal returnQuantity;
+        private Long salesLedgerProductId;
+        private Long purchaseReturnOrderId;
+
+        private SalesLedgerProduct salesLedgerProduct;
+    }
+}
diff --git a/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java
index 8e19f8c..fb02943 100644
--- a/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java
+++ b/src/main/java/com/ruoyi/purchase/vo/PurchaseReturnOrderVo.java
@@ -1,7 +1,13 @@
 package com.ruoyi.purchase.vo;
 
 import com.ruoyi.purchase.pojo.PurchaseReturnOrders;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
 public class PurchaseReturnOrderVo extends PurchaseReturnOrders {
     //渚涘簲鍟嗗悕绉�
     private String supplierName;
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
index dec3d1c..fcaceb6 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
@@ -2,11 +2,7 @@
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.procurementrecord.service.ProcurementRecordService;
-import com.ruoyi.procurementrecord.utils.StockUtils;
 import com.ruoyi.quality.dto.QualityInspectDto;
 import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.quality.pojo.QualityInspectFile;
@@ -14,12 +10,11 @@
 import com.ruoyi.quality.service.IQualityInspectFileService;
 import com.ruoyi.quality.service.IQualityInspectParamService;
 import com.ruoyi.quality.service.IQualityInspectService;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -27,24 +22,17 @@
  */
 @RestController
 @RequestMapping("/quality/qualityInspect")
+@AllArgsConstructor
 public class QualityInspectController {
 
-    @Resource
     private IQualityInspectService qualityInspectService;
-
-    @Resource
     private IQualityInspectParamService qualityInspectParamService;
-
-    @Resource
     private IQualityInspectFileService qualityInspectFileService;
-    @Autowired
-    private ProcurementRecordService procurementRecordService;
-    @Autowired
-    private StockUtils stockUtils;
 
 
     /**
      * 鏂板
+     *
      * @param qualityInspectDto
      * @return
      */
@@ -55,33 +43,35 @@
 
     /**
      * 鍒犻櫎
+     *
      * @param ids
      * @return
      */
     @DeleteMapping("/del")
     public AjaxResult delQualityInspect(@RequestBody List<Integer> ids) {
-        if(CollectionUtils.isEmpty(ids)){
+        if (CollectionUtils.isEmpty(ids)) {
             return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
         }
         //濡傛灉宸茬粡鎻愪氦灏变笉鍏佽鍒犻櫎
         List<QualityInspect> qualityInspects = qualityInspectService.listByIds(ids);
         for (QualityInspect qualityInspect : qualityInspects) {
-            if(qualityInspect.getInspectState()==1){
-               throw new RuntimeException("宸叉彁浜ょ殑鏁版嵁涓嶅厑璁稿垹闄�");
+            if (qualityInspect.getInspectState() == 1) {
+                throw new RuntimeException("宸叉彁浜ょ殑鏁版嵁涓嶅厑璁稿垹闄�");
             }
         }
         //鍒犻櫎妫�楠屽弬鏁�
         qualityInspectParamService.remove(Wrappers.<QualityInspectParam>lambdaQuery()
-        .in(QualityInspectParam::getInspectId,ids));
+                .in(QualityInspectParam::getInspectId, ids));
         //鍒犻櫎妫�楠岄檮浠�
         qualityInspectFileService.remove(Wrappers.<QualityInspectFile>lambdaQuery()
-        .in(QualityInspectFile::getInspectId,ids));
+                .in(QualityInspectFile::getInspectId, ids));
         //鍒犻櫎妫�楠屽崟
         return AjaxResult.success(qualityInspectService.removeBatchByIds(ids));
     }
 
     /**
      * 璇︽儏
+     *
      * @param id
      * @return
      */
@@ -92,6 +82,7 @@
 
     /**
      * 淇敼
+     *
      * @param qualityInspectDto
      * @return
      */
@@ -101,28 +92,31 @@
     }
 
     /**
-     *鍒嗛〉鏌ヨ
+     * 鍒嗛〉鏌ヨ
+     *
      * @param page
      * @param qualityInspect
      * @return
      */
     @GetMapping("/listPage")
-    public AjaxResult qualityInspectListPage(Page page, QualityInspect qualityInspect) {
+    public AjaxResult qualityInspectListPage(Page page, QualityInspectDto qualityInspect) {
         return AjaxResult.success(qualityInspectService.qualityInspectListPage(page, qualityInspect));
     }
 
     /**
      * 瀵煎嚭
+     *
      * @param response
      * @param qualityInspect
      */
     @PostMapping("/export")
-    public void qualityInspectExport(HttpServletResponse response,QualityInspect qualityInspect) {
+    public void qualityInspectExport(HttpServletResponse response, QualityInspect qualityInspect) {
         qualityInspectService.qualityInspectExport(response, qualityInspect);
     }
 
     /**
      * 鎻愪氦
+     *
      * @param qualityInspect
      * @return
      */
@@ -133,11 +127,12 @@
 
     /**
      * 涓嬭浇
+     *
      * @param response
      * @param qualityInspect
      */
     @PostMapping("/down")
-    public void down(HttpServletResponse response,@RequestBody QualityInspect qualityInspect) {
+    public void down(HttpServletResponse response, @RequestBody QualityInspect qualityInspect) {
         qualityInspectService.down(response, qualityInspect);
     }
 }
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectFileController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectFileController.java
index 4428fd7..bc5df62 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectFileController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityInspectFileController.java
@@ -12,8 +12,8 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java
index 3d6df0c..263b201 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java
@@ -12,8 +12,8 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityReportController.java b/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
index e60216d..4d005b0 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityReportController.java
@@ -2,9 +2,10 @@
 
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.quality.service.QualityReportService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiModelProperty;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -16,18 +17,18 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-01-14 03:39:49
  */
-@Api(tags = "璐ㄩ噺绠$悊")
+@Tag(name = "璐ㄩ噺绠$悊")
 @RestController
 @RequestMapping("/qualityReport")
+@AllArgsConstructor
 public class QualityReportController {
 
-    @Autowired
     private QualityReportService qualityReportService;
 
     /**
      * 鑾峰彇妫�楠岀粺璁℃暟鎹�
      */
-    @ApiOperation("鑾峰彇妫�楠岀粺璁℃暟鎹�")
+    @Operation(summary = "鑾峰彇妫�楠岀粺璁℃暟鎹�")
     @GetMapping("/getInspectStatistics")
     public AjaxResult getInspectStatistics() {
         return AjaxResult.success(qualityReportService.getInspectStatistics());
@@ -36,7 +37,7 @@
     /**
      * 鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�
      */
-    @ApiOperation("鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�")
+    @Operation(summary = "鑾峰彇鍚堟牸鐜囩粺璁℃暟鎹�")
     @GetMapping("/getPassRateStatistics")
     public AjaxResult getPassRateStatistics() {
         return AjaxResult.success(qualityReportService.getPassRateStatistics());
@@ -45,7 +46,7 @@
     /**
      * 鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�
      */
-    @ApiOperation("鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�")
+    @Operation(summary = "鑾峰彇鏈堝害鍚堟牸鐜囩粺璁℃暟鎹�")
     @GetMapping("/getMonthlyPassRateStatistics")
     public AjaxResult getMonthlyPassRateStatistics(@RequestParam("year") String year) {
         return AjaxResult.success(qualityReportService.getMonthlyPassRateStatistics(year));
@@ -54,7 +55,7 @@
     /**
      * 鑾峰彇骞村害鎬诲悎鏍肩巼缁熻鏁版嵁
      */
-    @ApiOperation("鑾峰彇骞村害鎬诲悎鏍肩巼缁熻鏁版嵁")
+    @Operation(summary = "鑾峰彇骞村害鎬诲悎鏍肩巼缁熻鏁版嵁")
     @GetMapping("/getYearlyPassRateStatistics")
     public AjaxResult getYearlyPassRateStatistics(@RequestParam("year") String year) {
         return AjaxResult.success(qualityReportService.getYearlyPassRateStatistics(year));
@@ -63,7 +64,7 @@
     /**
      * 鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁
      */
-    @ApiOperation("鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁")
+    @Operation(summary = "鑾峰彇鏈堝害瀹屾垚鏄庣粏鏁版嵁")
     @GetMapping("/getMonthlyCompletionDetails")
     public AjaxResult getMonthlyCompletionDetails(@RequestParam("year") String year) {
         return AjaxResult.success(qualityReportService.getMonthlyCompletionDetails(year));
@@ -72,7 +73,7 @@
     /**
      * 鑾峰彇鐑偣妫�娴嬫寚鏍囩粺璁�
      */
-    @ApiOperation("鑾峰彇鐑偣妫�娴嬫寚鏍囩粺璁�")
+    @Operation(summary = "鑾峰彇鐑偣妫�娴嬫寚鏍囩粺璁�")
     @GetMapping("/getTopParameters")
     public AjaxResult getTopParameters(@RequestParam("modelType") Integer modelType) {
         return AjaxResult.success(qualityReportService.getTopParameters(modelType));
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java
index 801eaaf..539f3f7 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardBindingController.java
@@ -1,12 +1,9 @@
 package com.ruoyi.quality.controller;
 
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.quality.pojo.QualityTestStandardBinding;
-import com.ruoyi.quality.pojo.QualityTestStandardParam;
 import com.ruoyi.quality.service.QualityTestStandardBindingService;
-import com.ruoyi.quality.service.QualityTestStandardParamService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
@@ -22,13 +19,14 @@
  */
 @RestController
 @RequestMapping("/qualityTestStandardBinding")
+@AllArgsConstructor
 public class QualityTestStandardBindingController {
 
-    @Autowired
     private QualityTestStandardBindingService qualityTestStandardBindingService;
 
     /**
      * 鏂板妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�
+     *
      * @param qualityTestStandardBindings
      * @return
      */
@@ -39,19 +37,21 @@
 
     /**
      * 鍒犻櫎妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�
+     *
      * @param ids
      * @return
      */
     @DeleteMapping("/del")
     public AjaxResult delQualityTestStandard(@RequestBody List<Integer> ids) {
-        if(CollectionUtils.isEmpty(ids)){
+        if (CollectionUtils.isEmpty(ids)) {
             return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
         }
         return AjaxResult.success(qualityTestStandardBindingService.removeBatchByIds(ids));
     }
 
     /**
-     *妫�娴嬫寚鏍囩淮鎶ゆ煡璇�
+     * 妫�娴嬫寚鏍囩淮鎶ゆ煡璇�
+     *
      * @return
      */
     @GetMapping("/list")
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java
index 014729b..a61ffed 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java
@@ -10,8 +10,8 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Nonnull;
-import javax.annotation.Resource;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java
index 55508ec..e5c883c 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityTestStandardParamController.java
@@ -6,6 +6,7 @@
 import com.ruoyi.quality.pojo.QualityTestStandard;
 import com.ruoyi.quality.pojo.QualityTestStandardParam;
 import com.ruoyi.quality.service.QualityTestStandardParamService;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
@@ -22,9 +23,9 @@
  */
 @RestController
 @RequestMapping("/qualityTestStandardParam")
+@AllArgsConstructor
 public class QualityTestStandardParamController {
 
-    @Autowired
     private QualityTestStandardParamService qualityTestStandardParamService;
 
     /**
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
index e558c30..3b20f82 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
@@ -7,8 +7,8 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java b/src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java
index 9bd4ca9..0a51a19 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java
@@ -6,10 +6,10 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.quality.pojo.QualityInspectParam;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
@@ -23,4 +23,10 @@
     //妫�楠岄」鐩�
     private List<QualityInspectParam> qualityInspectParams;
 
+    private String salesContractNo;
+
+
+    private String workOrderNo;
+    private String purchaseContractNo;
+
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java b/src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java
index f1e92d6..7ff7687 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java
@@ -1,24 +1,23 @@
 package com.ruoyi.quality.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
 import java.io.Serializable;
 
 @Data
-@ApiModel(value = "QualityInspectStatDto", description = "璐ㄩ噺妫�楠岀粺璁TO")
+@Schema(name = "QualityInspectStatDto", description = "璐ㄩ噺妫�楠岀粺璁TO")
 public class QualityInspectStatDto implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "绫诲埆(0:鍘熸潗鏂�;1:鍗婃垚鍝�;2:鎴愬搧)")
+    @Schema(description = "绫诲埆(0:鍘熸潗鏂�;1:鍗婃垚鍝�;2:鎴愬搧)")
     private Integer modelType;
 
-    @ApiModelProperty(value = "鎬绘暟閲�")
+    @Schema(description = "鎬绘暟閲�")
     private BigDecimal totalCount;
 
-    @ApiModelProperty(value = "宸插畬鎴愭暟閲�")
+    @Schema(description = "宸插畬鎴愭暟閲�")
     private BigDecimal completedCount;
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java
index c8ac682..a39c45c 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.quality.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -11,19 +10,19 @@
  * 璐ㄩ噺鏈堝害瀹屾垚鏄庣粏DTO
  */
 @Data
-@ApiModel(value = "QualityMonthlyDetailDto", description = "璐ㄩ噺鏈堝害瀹屾垚鏄庣粏DTO")
+@Schema(name = "QualityMonthlyDetailDto", description = "璐ㄩ噺鏈堝害瀹屾垚鏄庣粏DTO")
 public class QualityMonthlyDetailDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "鏈堜唤")
+    @Schema(description = "鏈堜唤")
     private String month;
 
-    @ApiModelProperty(value = "鍘熸潗鏂�")
+    @Schema(description = "鍘熸潗鏂�")
     private BigDecimal rawMaterialCount;
 
-    @ApiModelProperty(value = "鍗婃垚鍝�")
+    @Schema(description = "鍗婃垚鍝�")
     private BigDecimal processCount;
 
-    @ApiModelProperty(value = "鎴愬搧")
+    @Schema(description = "鎴愬搧")
     private BigDecimal outgoingCount;
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java
index c38f715..264a9f9 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.quality.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -11,31 +10,31 @@
  * 璐ㄩ噺鏈堝害鍚堟牸鐜囩粺璁TO
  */
 @Data
-@ApiModel(value = "QualityMonthlyPassRateDto", description = "璐ㄩ噺鏈堝害鍚堟牸鐜囩粺璁TO")
+@Schema(name = "QualityMonthlyPassRateDto", description = "璐ㄩ噺鏈堝害鍚堟牸鐜囩粺璁TO")
 public class QualityMonthlyPassRateDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "鏈堜唤(涓�鏈�, 浜屾湀...)")
+    @Schema(description = "鏈堜唤(涓�鏈�, 浜屾湀...)")
     private String month;
 
-    @ApiModelProperty(value = "绫诲埆(0:鍘熸潗鏂�;1:鍗婃垚鍝�;2:鎴愬搧)")
+    @Schema(description = "绫诲埆(0:鍘熸潗鏂�;1:鍗婃垚鍝�;2:鎴愬搧)")
     private Integer modelType;
 
-    @ApiModelProperty(value = "鎬绘暟閲�")
+    @Schema(description = "鎬绘暟閲�")
     private BigDecimal totalCount;
 
-    @ApiModelProperty(value = "宸插畬鎴愭暟閲�")
+    @Schema(description = "宸插畬鎴愭暟閲�")
     private BigDecimal completedCount;
 
-    @ApiModelProperty(value = "鍚堟牸鏁伴噺")
+    @Schema(description = "鍚堟牸鏁伴噺")
     private BigDecimal qualifiedCount;
 
-    @ApiModelProperty(value = "涓嶅悎鏍兼暟閲�")
+    @Schema(description = "涓嶅悎鏍兼暟閲�")
     private BigDecimal unqualifiedCount;
 
-    @ApiModelProperty(value = "瀹屾垚鍗犳瘮")
+    @Schema(description = "瀹屾垚鍗犳瘮")
     private BigDecimal completionRate;
 
-    @ApiModelProperty(value = "鍚堟牸鐜囧崰姣�")
+    @Schema(description = "鍚堟牸鐜囧崰姣�")
     private BigDecimal passRate;
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java
index f0d517b..60ee442 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.quality.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -10,19 +9,19 @@
  * 璐ㄩ噺鏈堝害鍚堟牸鐜囧寘瑁匘TO锛堟寜鏈堝垎缁勶級
  */
 @Data
-@ApiModel(value = "QualityMonthlyPassRateWrapperDto", description = "璐ㄩ噺鏈堝害鍚堟牸鐜囧寘瑁匘TO锛堟寜鏈堝垎缁勶級")
+@Schema(name = "QualityMonthlyPassRateWrapperDto", description = "璐ㄩ噺鏈堝害鍚堟牸鐜囧寘瑁匘TO锛堟寜鏈堝垎缁勶級")
 public class QualityMonthlyPassRateWrapperDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "鏈堜唤")
+    @Schema(description = "鏈堜唤")
     private String month;
 
-    @ApiModelProperty(value = "鍘熸潗鏂�")
+    @Schema(description = "鍘熸潗鏂�")
     private QualityPassRateDto rawMaterial;
 
-    @ApiModelProperty(value = "鍗婃垚鍝�")
+    @Schema(description = "鍗婃垚鍝�")
     private QualityPassRateDto process;
 
-    @ApiModelProperty(value = "鎴愬搧")
+    @Schema(description = "鎴愬搧")
     private QualityPassRateDto outgoing;
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java b/src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java
index 0675981..ef4eb9b 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.quality.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -11,16 +10,16 @@
  * 妫�楠屾寚鏍囩粺璁TO
  */
 @Data
-@ApiModel(value = "QualityParameterStatDto", description = "妫�楠屾寚鏍囩粺璁TO")
+@Schema(name = "QualityParameterStatDto", description = "妫�楠屾寚鏍囩粺璁TO")
 public class QualityParameterStatDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "鎸囨爣鍚嶇О")
+    @Schema(description = "鎸囨爣鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏁伴噺")
+    @Schema(description = "鏁伴噺")
     private BigDecimal count;
 
-    @ApiModelProperty(value = "鐧惧垎姣�")
+    @Schema(description = "鐧惧垎姣�")
     private BigDecimal percentage;
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java b/src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java
index b322528..1948e38 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.quality.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -11,29 +10,29 @@
  * 璐ㄩ噺鍚堟牸鐜囩粺璁TO
  */
 @Data
-@ApiModel(value = "QualityPassRateDto", description = "璐ㄩ噺鍚堟牸鐜囩粺璁TO")
+@Schema(name = "QualityPassRateDto", description = "璐ㄩ噺鍚堟牸鐜囩粺璁TO")
 public class QualityPassRateDto implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "绫诲埆(0:鍘熸潗鏂�;1:鍗婃垚鍝�;2:鎴愬搧)")
+    @Schema(description = "绫诲埆(0:鍘熸潗鏂�;1:鍗婃垚鍝�;2:鎴愬搧)")
     private Integer modelType;
 
-    @ApiModelProperty(value = "鎬绘暟閲�")
+    @Schema(description = "鎬绘暟閲�")
     private BigDecimal totalCount;
 
-    @ApiModelProperty(value = "宸插畬鎴愭暟閲�")
+    @Schema(description = "宸插畬鎴愭暟閲�")
     private BigDecimal completedCount;
 
-    @ApiModelProperty(value = "鍚堟牸鏁伴噺")
+    @Schema(description = "鍚堟牸鏁伴噺")
     private BigDecimal qualifiedCount;
 
-    @ApiModelProperty(value = "涓嶅悎鏍兼暟閲�")
+    @Schema(description = "涓嶅悎鏍兼暟閲�")
     private BigDecimal unqualifiedCount;
 
-    @ApiModelProperty(value = "瀹屾垚鍗犳瘮")
+    @Schema(description = "瀹屾垚鍗犳瘮")
     private BigDecimal completionRate;
 
-    @ApiModelProperty(value = "鍚堟牸鐜囧崰姣�")
+    @Schema(description = "鍚堟牸鐜囧崰姣�")
     private BigDecimal passRate;
 }
diff --git a/src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java b/src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java
index 0be4e8b..038dbc7 100644
--- a/src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java
+++ b/src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java
@@ -1,7 +1,6 @@
 package com.ruoyi.quality.dto;
 
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -12,13 +11,13 @@
  * 璐ㄦ鐑偣鎸囨爣缁熻缁撴灉DTO (鍗曠被鍨�)
  */
 @Data
-@ApiModel(value = "QualityTopParameterDto", description = "璐ㄦ鐑偣鎸囨爣缁熻缁撴灉DTO (鍗曠被鍨�)")
+@Schema(name = "QualityTopParameterDto", description = "璐ㄦ鐑偣鎸囨爣缁熻缁撴灉DTO (鍗曠被鍨�)")
 public class QualityTopParameterDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty(value = "鎬绘娴嬮」娆℃暟閲�")
+    @Schema(description = "鎬绘娴嬮」娆℃暟閲�")
     private BigDecimal totalCount;
 
-    @ApiModelProperty(value = "鎸囨爣缁熻鍒楄〃 (Top 4 + 鍏朵粬)")
+    @Schema(description = "鎸囨爣缁熻鍒楄〃 (Top 4 + 鍏朵粬)")
     private List<QualityParameterStatDto> list;
 }
diff --git a/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java b/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java
index 388ebcc..2b87d5e 100644
--- a/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java
+++ b/src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java
@@ -14,7 +14,7 @@
 public interface QualityInspectMapper extends BaseMapper<QualityInspect> {
 
 
-    IPage<QualityInspect> qualityInspectListPage(Page page, @Param("qualityInspect") QualityInspect qualityInspect);
+    IPage<QualityInspectDto> qualityInspectListPage(Page page, @Param("qualityInspect") QualityInspect qualityInspect);
 
     List<QualityInspect> qualityInspectExport(@Param("qualityInspect") QualityInspect qualityInspect);
 
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java b/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
index 9d23429..9d8a07d 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
@@ -4,10 +4,10 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
@@ -113,23 +113,23 @@
 
 
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
@@ -149,12 +149,10 @@
     //涓嶅悎鏍肩幇璞�
     private String defectivePhenomena;
 
-    @ApiModelProperty("鍏宠仈妫�娴嬫爣鍑嗕富琛╥d")
+    @Schema(description = "鍏宠仈妫�娴嬫爣鍑嗕富琛╥d")
     private Long testStandardId;
 
 
-    @TableField(exist = false)
-    private String workOrderNo;
-    @TableField(exist = false)
-    private String purchaseContractNo;
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityInspectFile.java b/src/main/java/com/ruoyi/quality/pojo/QualityInspectFile.java
index 6ef6dd9..1ecf5cd 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityInspectFile.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityInspectFile.java
@@ -2,10 +2,10 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.time.LocalDateTime;
 
@@ -24,38 +24,41 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty(value = "鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private int fileSize;
 
-    @ApiModelProperty(value = "妫�楠孖D")
+    @Schema(description = "妫�楠孖D")
     @NotBlank(message = "妫�楠宨d涓嶈兘涓虹┖!")
     private Long inspectId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityInspectParam.java b/src/main/java/com/ruoyi/quality/pojo/QualityInspectParam.java
index 91092d2..f765f9f 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityInspectParam.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityInspectParam.java
@@ -2,10 +2,10 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.time.LocalDateTime;
 
@@ -64,23 +64,23 @@
 
 
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
@@ -89,4 +89,7 @@
     private Integer index;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java b/src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java
index d2fb853..0bc6071 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java
@@ -8,8 +8,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -24,7 +23,7 @@
 @Getter
 @Setter
 @TableName("quality_test_standard")
-@ApiModel(value = "QualityTestStandard瀵硅薄", description = "妫�娴嬫爣鍑嗕富琛�")
+@Schema(name = "QualityTestStandard瀵硅薄", description = "妫�娴嬫爣鍑嗕富琛�")
 public class QualityTestStandard implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -32,41 +31,44 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鏍囧噯缂栧彿")
+    @Schema(description = "鏍囧噯缂栧彿")
     private String standardNo;
 
-    @ApiModelProperty("鏍囧噯鍚嶇О")
+    @Schema(description = "鏍囧噯鍚嶇О")
     private String standardName;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
 
-    @ApiModelProperty("绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty("鐘舵��")
+    @Schema(description = "鐘舵��")
     private String state;
 
-    @ApiModelProperty("绫诲埆(0:鍘熸潗鏂欐楠�;1:杩囩▼妫�楠�;2:鍑哄巶妫�楠�)")
+    @Schema(description = "绫诲埆(0:鍘熸潗鏂欐楠�;1:杩囩▼妫�楠�;2:鍑哄巶妫�楠�)")
     private Integer inspectType;
 
-    @ApiModelProperty("宸ュ簭id")
+    @Schema(description = "宸ュ簭id")
     private Integer processId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardBinding.java b/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardBinding.java
index 3b15f5d..3a24901 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardBinding.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardBinding.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,7 +22,7 @@
 @Getter
 @Setter
 @TableName("quality_test_standard_binding")
-@ApiModel(value = "QualityTestStandardBinding瀵硅薄", description = "妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�")
+@Schema(name = "QualityTestStandardBinding瀵硅薄", description = "妫�娴嬫爣鍑嗕富琛ㄤ笌浜у搧鍏宠仈琛�")
 public class QualityTestStandardBinding implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -31,29 +30,32 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("浜у搧ID")
+    @Schema(description = "浜у搧ID")
     private Long productId;
 
-    @ApiModelProperty("鍏宠仈妫�娴嬫爣鍑嗕富琛╥d")
+    @Schema(description = "鍏宠仈妫�娴嬫爣鍑嗕富琛╥d")
     private Integer testStandardId;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
 
-    @ApiModelProperty("绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardParam.java b/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardParam.java
index 1abd96f..2638991 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardParam.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityTestStandardParam.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,7 +22,7 @@
 @Getter
 @Setter
 @TableName("quality_test_standard_param")
-@ApiModel(value = "QualityTestStandardParam瀵硅薄", description = "妫�娴嬫爣鍑嗗弬鏁�")
+@Schema(name = "QualityTestStandardParam瀵硅薄", description = "妫�娴嬫爣鍑嗗弬鏁�")
 public class QualityTestStandardParam implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -31,41 +30,44 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍙傛暟椤�")
+    @Schema(description = "鍙傛暟椤�")
     private String parameterItem;
 
-    @ApiModelProperty("鍗曚綅")
+    @Schema(description = "鍗曚綅")
     private String unit;
 
-    @ApiModelProperty("鏍囧噯鍊�")
+    @Schema(description = "鏍囧噯鍊�")
     private String standardValue;
 
-    @ApiModelProperty("鍐呮帶鍊�")
+    @Schema(description = "鍐呮帶鍊�")
     private String controlValue;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
 
-    @ApiModelProperty("绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty("鍏宠仈妫�娴嬫爣鍑嗕富琛╥d")
+    @Schema(description = "鍏宠仈妫�娴嬫爣鍑嗕富琛╥d")
     private Long testStandardId;
 
-    @ApiModelProperty("榛樿鍊�")
+    @Schema(description = "榛樿鍊�")
     private String defaultValue;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
index d2f8e88..31984af 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java
@@ -4,10 +4,10 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
@@ -113,31 +113,34 @@
 
 
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty("鍏宠仈妫�娴媔d")
+    @Schema(description = "鍏宠仈妫�娴媔d")
     private Long inspectId;
 
 
-    @ApiModelProperty("鏄惁涓嶅悎鏍煎鐞嗚嚜宸辨柊澧�")
+    @Schema(description = "鏄惁涓嶅悎鏍煎鐞嗚嚜宸辨柊澧�")
     @TableField(exist = false)
     private Boolean method;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java b/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java
index 92bc88f..d78a5ca 100644
--- a/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java
+++ b/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.quality.dto.QualityInspectDto;
 import com.ruoyi.quality.pojo.QualityInspect;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 public interface IQualityInspectService extends IService<QualityInspect> {
 
@@ -15,7 +15,7 @@
 
     int updateQualityInspect(QualityInspectDto qualityInspectDto);
 
-    IPage<QualityInspect> qualityInspectListPage(Page page, QualityInspect qualityInspect);
+    IPage<QualityInspectDto> qualityInspectListPage(Page page, QualityInspectDto qualityInspect);
 
     void qualityInspectExport(HttpServletResponse response, QualityInspect qualityInspect);
 
diff --git a/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java b/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java
index ceff474..e35bc02 100644
--- a/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java
+++ b/src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.quality.pojo.QualityUnqualified;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 public interface IQualityUnqualifiedService extends IService<QualityUnqualified> {
 
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index 8a1e066..8c53500 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -9,7 +9,6 @@
 import com.deepoove.poi.XWPFTemplate;
 import com.deepoove.poi.config.Configure;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.procurementrecord.service.ProcurementRecordService;
@@ -24,12 +23,14 @@
 import com.ruoyi.quality.service.IQualityInspectParamService;
 import com.ruoyi.quality.service.IQualityInspectService;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.stock.dto.StockInventoryDto;
+import com.ruoyi.stock.service.StockInventoryService;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URLEncoder;
@@ -43,6 +44,7 @@
 public class QualityInspectServiceImpl extends ServiceImpl<QualityInspectMapper, QualityInspect> implements IQualityInspectService {
 
     private final StockUtils stockUtils;
+    private final StockInventoryService stockInventoryService;
     private QualityInspectMapper qualityInspectMapper;
 
     private IQualityInspectParamService qualityInspectParamService;
@@ -98,7 +100,14 @@
             qualityUnqualifiedMapper.insert(qualityUnqualified);
         } else {
             //鍚堟牸鐩存帴鍏ュ簱
-            stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId());
+            // stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId());
+            //浠呮坊鍔犲叆搴撹褰�
+            StockInventoryDto stockInventoryDto = new StockInventoryDto();
+            stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode()));
+            stockInventoryDto.setRecordId(qualityInspect.getId());
+            stockInventoryDto.setProductModelId(qualityInspect.getProductModelId());
+            stockInventoryDto.setQualitity(qualityInspect.getQuantity());
+            stockInventoryService.addStockInRecordOnly(stockInventoryDto);
         }
         qualityInspect.setInspectState(1);//宸叉彁浜�
         return qualityInspectMapper.updateById(qualityInspect);
@@ -171,7 +180,7 @@
     }
 
     @Override
-    public IPage<QualityInspect> qualityInspectListPage(Page page, QualityInspect qualityInspect) {
+    public IPage<QualityInspectDto> qualityInspectListPage(Page page, QualityInspectDto qualityInspect) {
         return qualityInspectMapper.qualityInspectListPage(page, qualityInspect);
     }
 
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java
index f01f315..d59b610 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java
@@ -1,14 +1,11 @@
 package com.ruoyi.quality.service.impl;
 
-import com.ruoyi.basic.service.IProductModelService;
-import com.ruoyi.basic.service.IProductService;
 import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.production.service.ProductOrderService;
 import com.ruoyi.quality.dto.*;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.quality.service.QualityReportService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -20,10 +17,10 @@
 
 
 @Service
+@RequiredArgsConstructor
 public class QualityReportServiceImpl implements QualityReportService {
 
-    @Autowired
-    private QualityInspectMapper qualityInspectMapper;
+    private final QualityInspectMapper qualityInspectMapper;
 
     @Override
     public List<QualityInspectStatDto> getInspectStatistics() {
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardBindingServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardBindingServiceImpl.java
index 86c6e7f..a581977 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardBindingServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardBindingServiceImpl.java
@@ -1,12 +1,12 @@
 package com.ruoyi.quality.service.impl;
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.ruoyi.quality.dto.QualityTestStandardBindingDto;
-import com.ruoyi.quality.pojo.QualityTestStandardBinding;
-import com.ruoyi.quality.mapper.QualityTestStandardBindingMapper;
-import com.ruoyi.quality.service.QualityTestStandardBindingService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.quality.dto.QualityTestStandardBindingDto;
+import com.ruoyi.quality.mapper.QualityTestStandardBindingMapper;
+import com.ruoyi.quality.pojo.QualityTestStandardBinding;
+import com.ruoyi.quality.service.QualityTestStandardBindingService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -20,10 +20,10 @@
  * @since 2026-01-13 03:39:40
  */
 @Service
+@RequiredArgsConstructor
 public class QualityTestStandardBindingServiceImpl extends ServiceImpl<QualityTestStandardBindingMapper, QualityTestStandardBinding> implements QualityTestStandardBindingService {
 
-    @Autowired
-    private QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
+    private final QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
 
     @Override
     public List<QualityTestStandardBindingDto> listBinding(Long testStandardId) {
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardServiceImpl.java
index 371ab5d..ed777a7 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardServiceImpl.java
@@ -1,23 +1,18 @@
 package com.ruoyi.quality.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.basic.mapper.ProductModelMapper;
-import com.ruoyi.basic.pojo.ProductModel;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.mapper.QualityTestStandardBindingMapper;
+import com.ruoyi.quality.mapper.QualityTestStandardMapper;
 import com.ruoyi.quality.mapper.QualityTestStandardParamMapper;
 import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.quality.pojo.QualityTestStandard;
-import com.ruoyi.quality.mapper.QualityTestStandardMapper;
-import com.ruoyi.quality.pojo.QualityTestStandardBinding;
 import com.ruoyi.quality.pojo.QualityTestStandardParam;
 import com.ruoyi.quality.service.IQualityTestStandardService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.quality.service.QualityTestStandardParamService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -33,22 +28,13 @@
  * @since 2026-01-13 03:40:24
  */
 @Service
+@RequiredArgsConstructor
 public class QualityTestStandardServiceImpl extends ServiceImpl<QualityTestStandardMapper, QualityTestStandard> implements IQualityTestStandardService {
 
-    @Autowired
-    private QualityTestStandardMapper qualityTestStandardMapper;
-
-    @Autowired
-    private QualityTestStandardParamMapper qualityTestStandardParamMapper;
-
-    @Autowired
-    private QualityTestStandardParamService qualityTestStandardParamService;
-
-    @Autowired
-    private QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
-
-    @Autowired
-    private QualityInspectMapper qualityInspectMapper;
+    private final QualityTestStandardMapper qualityTestStandardMapper;
+    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
+    private final QualityTestStandardParamService qualityTestStandardParamService;
+    private final QualityInspectMapper qualityInspectMapper;
 
     @Override
     public IPage<QualityTestStandard> qualityTestStandardListPage(Page page, QualityTestStandard qualityTestStandard) {
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
index 1650690..0296ef4 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -1,24 +1,26 @@
 package com.ruoyi.quality.service.impl;
 
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.mapper.ProductProcessRouteItemMapper;
-import com.ruoyi.production.mapper.ProductProcessRouteMapper;
-import com.ruoyi.production.mapper.ProductWorkOrderMapper;
+import com.ruoyi.production.mapper.ProductionOperationTaskMapper;
+import com.ruoyi.production.mapper.ProductionOrderMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingMapper;
+import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper;
 import com.ruoyi.production.mapper.ProductionProductMainMapper;
-import com.ruoyi.production.pojo.*;
-import com.ruoyi.production.service.ProductOrderService;
+import com.ruoyi.production.pojo.ProductionOperationTask;
+import com.ruoyi.production.pojo.ProductionOrder;
+import com.ruoyi.production.pojo.ProductionOrderRouting;
+import com.ruoyi.production.pojo.ProductionOrderRoutingOperation;
+import com.ruoyi.production.pojo.ProductionProductMain;
 import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
 import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.quality.pojo.QualityUnqualified;
@@ -28,25 +30,27 @@
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @AllArgsConstructor
 @Service
 public class QualityUnqualifiedServiceImpl extends ServiceImpl<QualityUnqualifiedMapper, QualityUnqualified> implements IQualityUnqualifiedService {
 
     private final StockUtils stockUtils;
-    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
-    private IQualityInspectService qualityInspectService;
-    private ProductOrderService productOrderService;
-    private ProductionProductMainMapper productionProductMainMapper;
-    private ProductProcessRouteMapper productProcessRouteMapper;
-    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
-    private ProductWorkOrderMapper productWorkOrderMapper;
-    private StockUninventoryService stockUninventoryService;
+    private final QualityUnqualifiedMapper qualityUnqualifiedMapper;
+    private final IQualityInspectService qualityInspectService;
+    private final ProductionProductMainMapper productionProductMainMapper;
+    private final ProductionOrderMapper productionOrderMapper;
+    private final ProductionOrderRoutingMapper productionOrderRoutingMapper;
+    private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper;
+    private final ProductionOperationTaskMapper productionOperationTaskMapper;
+    private final StockUninventoryService stockUninventoryService;
 
     @Override
     public IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) {
@@ -56,7 +60,7 @@
     @Override
     public void qualityUnqualifiedExport(HttpServletResponse response, QualityUnqualified qualityUnqualified) {
         List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.qualityUnqualifiedExport(qualityUnqualified);
-        ExcelUtil<QualityUnqualified> util = new ExcelUtil<QualityUnqualified>(QualityUnqualified.class);
+        ExcelUtil<QualityUnqualified> util = new ExcelUtil<>(QualityUnqualified.class);
         util.exportExcel(response, qualityUnqualifieds, "涓嶅悎鏍肩鐞嗗鍑�");
     }
 
@@ -68,92 +72,41 @@
             switch (qualityUnqualified.getDealResult()) {
                 case "杩斾慨":
                 case "杩斿伐":
-                    //鍒ゆ柇璐ㄦ琛ㄦ槸鍚︽湁鐩稿叧鐨勬姤宸d,濡傛灉鏈夋姤宸d,閭d箞杩斿伐闇�瑕侀噸鏂板垱寤虹敓浜ц鍗曢噸鏂扮敓浜�
                     if (ObjectUtils.isNotNull(qualityInspect.getProductMainId())) {
-                        //杩斿伐闇�瑕侀噸鏂板垱寤虹敓浜ц鍗曢噸鏂扮敓浜�
-                        ProductOrder productOrder = productionProductMainMapper.getOrderByMainId(qualityInspect.getProductMainId());
-                        ProductOrder order = new ProductOrder();
-                        BeanUtils.copyProperties(productOrder, order);
-                        order.setId(null);
-                        order.setQuantity(unqualified.getQuantity());
-                        order.setCompleteQuantity(BigDecimal.ZERO);
-                        order.setStartTime(null);
-                        order.setEndTime(null);
-                        productOrderService.save(order);
-                        //鏂板鐢熶骇璁㈠崟涓嬬殑宸ヨ壓璺嚎涓昏〃
-                        ProductProcessRoute productProcessRoute = productProcessRouteMapper.selectList(Wrappers.<ProductProcessRoute>lambdaQuery().eq(ProductProcessRoute::getProductOrderId, productOrder.getId()).orderByDesc(ProductProcessRoute::getId)).get(0);
-                        ProductProcessRoute newProcessRoute = new ProductProcessRoute();
-                        BeanUtils.copyProperties(productProcessRoute, newProcessRoute);
-                        newProcessRoute.setId(null);
-                        newProcessRoute.setProductOrderId(order.getId());
-                        productProcessRouteMapper.insert(newProcessRoute);
-                        //鏂板鐢熶骇璁㈠崟涓嬬殑宸ヨ壓璺嚎瀛愯〃
-                        List<ProductProcessRouteItem> processRouteItems = productProcessRouteItemMapper.selectList(new QueryWrapper<ProductProcessRouteItem>().lambda().eq(ProductProcessRouteItem::getProductRouteId, productProcessRoute.getId()));
-                        // 鐢熸垚褰撳墠鏃ユ湡鐨勫墠缂�锛氬勾鏈堟棩
-                        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
-                        for (ProductProcessRouteItem processRouteItem : processRouteItems) {
-                            ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
-                            BeanUtils.copyProperties(processRouteItem, productProcessRouteItem);
-                            productProcessRouteItem.setId(null);
-                            productProcessRouteItem.setProductRouteId(newProcessRoute.getId());
-                            int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
-                            if (insert > 0) {
-                                // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶у伐鍗曞彿
-                                ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectMax(datePrefix);
-                                int sequenceNumber = 1; // 榛樿搴忓彿
-                                if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
-                                    String lastNo = lastWorkOrder.getWorkOrderNo().toString();
-                                    if (lastNo.startsWith(datePrefix)) {
-                                        String seqStr = lastNo.substring(datePrefix.length());
-                                        try {
-                                            sequenceNumber = Integer.parseInt(seqStr) + 1;
-                                        } catch (NumberFormatException e) {
-                                            sequenceNumber = 1;
-                                        }
-                                    }
-                                }
-                                // 鐢熸垚瀹屾暣鐨勫伐鍗曞彿
-                                String workOrderNoStr = "FG" + String.format("%s%03d", datePrefix, sequenceNumber);
-                                ProductWorkOrder productWorkOrder = new ProductWorkOrder();
-                                productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
-                                productWorkOrder.setProductOrderId(order.getId());
-                                productWorkOrder.setPlanQuantity(order.getQuantity());
-                                productWorkOrder.setWorkOrderNo(workOrderNoStr);
-                                productWorkOrder.setStatus(1);
-                                productWorkOrderMapper.insert(productWorkOrder);
-                            }
+                        ProductionProductMain sourceMain = productionProductMainMapper.selectById(qualityInspect.getProductMainId());
+                        if (sourceMain == null || sourceMain.getProductionOperationTaskId() == null) {
+                            throw new ServiceException("鍘嗗彶鎶ュ伐鏈粦瀹氱敓浜у伐鍗曪紝鏃犳硶鎸夋柊妯″瀷杩斾慨/杩斿伐");
                         }
+                        createReworkProductionByNewModel(sourceMain, unqualified.getQuantity());
                     }
                     break;
                 case "鎶ュ簾":
-                    //璋冪敤涓嶅悎鏍煎簱瀛樻帴鍙� 鍏ヤ笉鍚堟牸搴�
-                    stockUtils.addUnStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId());
+                    stockUtils.addUnStock(qualityInspect.getProductModelId(), unqualified.getQuantity(),
+                            StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId());
                     break;
                 case "璁╂鏀捐":
-                    //璋冪敤鎻愪氦鍚堟牸鐨勬帴鍙�
-                    stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
+                    stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(),
+                            StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
                     break;
                 default:
                     break;
             }
         } else {
-            //鏌ヨ瀵瑰簲鐨勮鏍煎瀷鍙穒d
             Long modelId = qualityUnqualifiedMapper.getModelId(qualityUnqualified.getProductName(), qualityUnqualified.getModel());
             switch (qualityUnqualified.getDealResult()) {
                 case "鎶ュ簾":
-                    //璋冪敤涓嶅悎鏍煎簱瀛樻帴鍙� 鍏ヤ笉鍚堟牸搴�
-                    stockUtils.addUnStock(modelId, unqualified.getQuantity(), StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId());
+                    stockUtils.addUnStock(modelId, unqualified.getQuantity(),
+                            StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId());
                     break;
                 case "璁╂鏀捐":
-                    //璋冪敤鎻愪氦鍚堟牸鐨勬帴鍙�
-                    stockUtils.addStock(modelId, unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
+                    stockUtils.addStock(modelId, unqualified.getQuantity(),
+                            StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
                     break;
                 default:
                     break;
             }
-
         }
-        qualityUnqualified.setInspectState(1);//宸插鐞�
+        qualityUnqualified.setInspectState(1);
         return qualityUnqualifiedMapper.updateById(qualityUnqualified);
     }
 
@@ -161,4 +114,110 @@
     public QualityUnqualified getUnqualified(Integer id) {
         return qualityUnqualifiedMapper.getUnqualified(id);
     }
+
+    private void createReworkProductionByNewModel(ProductionProductMain sourceMain, BigDecimal quantity) {
+        ProductionOperationTask sourceTask = productionOperationTaskMapper.selectById(sourceMain.getProductionOperationTaskId());
+        if (sourceTask == null) {
+            throw new ServiceException("鍏宠仈鐨勭敓浜у伐鍗曚笉瀛樺湪");
+        }
+        ProductionOrder sourceOrder = productionOrderMapper.selectById(sourceTask.getProductionOrderId());
+        if (sourceOrder == null) {
+            throw new ServiceException("鍏宠仈鐨勭敓浜ц鍗曚笉瀛樺湪");
+        }
+
+        ProductionOrder newOrder = new ProductionOrder();
+        BeanUtils.copyProperties(sourceOrder, newOrder);
+        newOrder.setId(null);
+        newOrder.setNpsNo(generateNextProductionOrderNo("FG"));
+        newOrder.setQuantity(defaultDecimal(quantity));
+        newOrder.setCompleteQuantity(BigDecimal.ZERO);
+        newOrder.setStartTime(null);
+        newOrder.setEndTime(null);
+        newOrder.setCreateTime(null);
+        newOrder.setUpdateTime(null);
+        productionOrderMapper.insert(newOrder);
+
+        Map<Long, Long> routingIdMap = new HashMap<>();
+        List<ProductionOrderRouting> sourceRoutings = productionOrderRoutingMapper.selectList(
+                Wrappers.<ProductionOrderRouting>lambdaQuery()
+                        .eq(ProductionOrderRouting::getProductionOrderId, sourceOrder.getId())
+                        .orderByAsc(ProductionOrderRouting::getId));
+        for (ProductionOrderRouting sourceRouting : sourceRoutings) {
+            ProductionOrderRouting newRouting = new ProductionOrderRouting();
+            BeanUtils.copyProperties(sourceRouting, newRouting);
+            newRouting.setId(null);
+            newRouting.setProductionOrderId(newOrder.getId());
+            newRouting.setCreateTime(null);
+            newRouting.setUpdateTime(null);
+            productionOrderRoutingMapper.insert(newRouting);
+            routingIdMap.put(sourceRouting.getId(), newRouting.getId());
+        }
+
+        List<ProductionOrderRoutingOperation> sourceOperations = productionOrderRoutingOperationMapper.selectList(
+                Wrappers.<ProductionOrderRoutingOperation>lambdaQuery()
+                        .eq(ProductionOrderRoutingOperation::getProductionOrderId, sourceOrder.getId())
+                        .orderByAsc(ProductionOrderRoutingOperation::getDragSort)
+                        .orderByAsc(ProductionOrderRoutingOperation::getId));
+        for (ProductionOrderRoutingOperation sourceOperation : sourceOperations) {
+            ProductionOrderRoutingOperation newOperation = new ProductionOrderRoutingOperation();
+            BeanUtils.copyProperties(sourceOperation, newOperation);
+            newOperation.setId(null);
+            newOperation.setProductionOrderId(newOrder.getId());
+            newOperation.setOrderRoutingId(routingIdMap.get(sourceOperation.getOrderRoutingId()));
+            newOperation.setCreateTime(null);
+            newOperation.setUpdateTime(null);
+            productionOrderRoutingOperationMapper.insert(newOperation);
+
+            ProductionOperationTask newTask = new ProductionOperationTask();
+            newTask.setProductionOrderRoutingOperationId(newOperation.getId());
+            newTask.setProductionOrderId(newOrder.getId());
+            newTask.setPlanQuantity(newOrder.getQuantity());
+            newTask.setCompleteQuantity(BigDecimal.ZERO);
+            newTask.setWorkOrderNo(generateNextTaskNo("FG"));
+            newTask.setStatus(1);
+            productionOperationTaskMapper.insert(newTask);
+        }
+    }
+
+    private String generateNextProductionOrderNo(String prefix) {
+        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        String orderPrefix = prefix + datePrefix;
+        ProductionOrder latestOrder = productionOrderMapper.selectOne(
+                Wrappers.<ProductionOrder>lambdaQuery()
+                        .likeRight(ProductionOrder::getNpsNo, orderPrefix)
+                        .orderByDesc(ProductionOrder::getNpsNo)
+                        .last("limit 1"));
+        int sequence = 1;
+        if (latestOrder != null && latestOrder.getNpsNo() != null && latestOrder.getNpsNo().startsWith(orderPrefix)) {
+            try {
+                sequence = Integer.parseInt(latestOrder.getNpsNo().substring(orderPrefix.length())) + 1;
+            } catch (NumberFormatException ignored) {
+                sequence = 1;
+            }
+        }
+        return orderPrefix + String.format("%04d", sequence);
+    }
+
+    private String generateNextTaskNo(String prefix) {
+        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        String taskPrefix = prefix + datePrefix;
+        ProductionOperationTask latestTask = productionOperationTaskMapper.selectOne(
+                Wrappers.<ProductionOperationTask>lambdaQuery()
+                        .likeRight(ProductionOperationTask::getWorkOrderNo, taskPrefix)
+                        .orderByDesc(ProductionOperationTask::getWorkOrderNo)
+                        .last("limit 1"));
+        int sequence = 1;
+        if (latestTask != null && latestTask.getWorkOrderNo() != null && latestTask.getWorkOrderNo().startsWith(taskPrefix)) {
+            try {
+                sequence = Integer.parseInt(latestTask.getWorkOrderNo().substring(taskPrefix.length())) + 1;
+            } catch (NumberFormatException ignored) {
+                sequence = 1;
+            }
+        }
+        return taskPrefix + String.format("%03d", sequence);
+    }
+
+    private BigDecimal defaultDecimal(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value;
+    }
 }
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java b/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
index 3db1660..400998a 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
@@ -3,11 +3,10 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.safe.pojo.SafeAccident;
-import com.ruoyi.safe.pojo.SafeContingencyPlan;
 import com.ruoyi.safe.service.SafeAccidentService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -22,31 +21,31 @@
  */
 @RestController
 @RequestMapping("/safeAccident")
-@Api(tags = "瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍")
+@AllArgsConstructor
+@Tag(name = "瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍")
 public class SafeAccidentController {
 
-    @Autowired
     private SafeAccidentService safeAccidentService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page page, SafeAccident safeAccident) {
         return R.ok(safeAccidentService.pageSafeAccident(page, safeAccident));
     }
 
-    @ApiOperation("鏂板浜嬫晠涓婃姤璁板綍")
+    @Operation(summary = "鏂板浜嬫晠涓婃姤璁板綍")
     @PostMapping()
     public R add(@RequestBody SafeAccident safeAccident) {
         return R.ok(safeAccidentService.save(safeAccident));
     }
 
-    @ApiOperation("淇敼浜嬫晠涓婃姤璁板綍")
+    @Operation(summary = "淇敼浜嬫晠涓婃姤璁板綍")
     @PutMapping ()
     public R update(@RequestBody  SafeAccident safeAccident) {
         return R.ok(safeAccidentService.updateById(safeAccident));
     }
 
-    @ApiOperation("鍒犻櫎浜嬫晠涓婃姤璁板綍")
+    @Operation(summary = "鍒犻櫎浜嬫晠涓婃姤璁板綍")
     @DeleteMapping("/{ids}")
     public R delSafeAccident(@RequestBody List<Integer> ids) {
         return R.ok(safeAccidentService.removeBatchByIds(ids));
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java b/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java
index 7e13eb8..bdedc46 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java
@@ -1,19 +1,15 @@
 package com.ruoyi.safe.controller;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.dto.ProcessRouteDto;
-import com.ruoyi.production.pojo.ProcessRoute;
 import com.ruoyi.safe.pojo.SafeCertification;
 import com.ruoyi.safe.service.SafeCertificationService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -26,31 +22,31 @@
  */
 @RestController
 @RequestMapping("/safeCertification")
-@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
+@Tag(name = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
+@AllArgsConstructor
 public class SafeCertificationController {
 
-    @Autowired
     private SafeCertificationService safeCertificationService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page<SafeCertification> page, SafeCertification safeCertification) {
         return R.ok(safeCertificationService.pageSafeCertification(page, safeCertification));
     }
 
-    @ApiOperation("鏂板瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
+    @Operation(summary = "鏂板瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
     @PostMapping()
     public R add(@RequestBody SafeCertification safeCertification) {
         return R.ok(safeCertificationService.save(safeCertification));
     }
 
-    @ApiOperation("淇敼瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
+    @Operation(summary = "淇敼瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
     @PutMapping ()
     public R update(@RequestBody  SafeCertification safeCertification) {
         return R.ok(safeCertificationService.updateById(safeCertification));
     }
 
-    @ApiOperation("鍒犻櫎瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
+    @Operation(summary = "鍒犻櫎瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
     @DeleteMapping("/{ids}")
     public R delSafeCertification(@RequestBody List<Integer> ids) {
         return R.ok(safeCertificationService.removeBatchByIds(ids));
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeCertificationFileController.java b/src/main/java/com/ruoyi/safe/controller/SafeCertificationFileController.java
index 589f5b7..49e3e1d 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeCertificationFileController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeCertificationFileController.java
@@ -2,18 +2,15 @@
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.production.pojo.ProductWorkOrderFile;
-import com.ruoyi.production.service.ProductWorkOrderFileService;
 import com.ruoyi.safe.pojo.SafeCertificationFile;
 import com.ruoyi.safe.service.SafeCertificationFileService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.annotation.Resource;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
 import java.util.List;
 
 /**
@@ -26,7 +23,7 @@
  */
 @RestController
 @RequestMapping("/safeCertificationFile")
-@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�--闄勪欢")
+@Tag(name = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�--闄勪欢")
 public class SafeCertificationFileController {
 
     @Resource
@@ -39,7 +36,7 @@
      * @return
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public R add(@RequestBody SafeCertificationFile safeCertificationFile) {
         return R.ok(safeCertificationFileService.save(safeCertificationFile));
     }
@@ -50,7 +47,7 @@
      * @return
      */
     @DeleteMapping("/del")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public R delSafeCertificationFile(@RequestBody List<Integer> ids) {
         if(CollectionUtils.isEmpty(ids)){
             return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -66,7 +63,7 @@
      * @return
      */
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R listPage(Page page, SafeCertificationFile safeCertificationFile) {
         return R.ok(safeCertificationFileService.page(page, Wrappers.<SafeCertificationFile>lambdaQuery().eq(SafeCertificationFile::getSafeCertificationId,safeCertificationFile.getSafeCertificationId())));
     }
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java b/src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java
index 33d32bd..d5d835d 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java
@@ -2,13 +2,11 @@
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.safe.pojo.SafeCertification;
 import com.ruoyi.safe.pojo.SafeContingencyPlan;
-import com.ruoyi.safe.service.SafeCertificationService;
 import com.ruoyi.safe.service.SafeContingencyPlanService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -23,31 +21,31 @@
  */
 @RestController
 @RequestMapping("/safeContingencyPlan")
-@Api(tags = "瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃�")
+@Tag(name = "瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃�")
+@AllArgsConstructor
 public class SafeContingencyPlanController {
 
-    @Autowired
-    private SafeContingencyPlanService safeContingencyPlanService;
+    private final SafeContingencyPlanService safeContingencyPlanService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page page, SafeContingencyPlan safeContingencyPlan) {
         return R.ok(safeContingencyPlanService.pageSafeContingencyPlan(page, safeContingencyPlan));
     }
 
-    @ApiOperation("鏂板搴旀�ラ妗堟煡闃�")
+    @Operation(summary = "鏂板搴旀�ラ妗堟煡闃�")
     @PostMapping()
     public R add(@RequestBody SafeContingencyPlan safeContingencyPlan) {
         return R.ok(safeContingencyPlanService.save(safeContingencyPlan));
     }
 
-    @ApiOperation("淇敼搴旀�ラ妗堟煡闃�")
+    @Operation(summary = "淇敼搴旀�ラ妗堟煡闃�")
     @PutMapping ()
     public R update(@RequestBody  SafeContingencyPlan safeContingencyPlan) {
         return R.ok(safeContingencyPlanService.updateById(safeContingencyPlan));
     }
 
-    @ApiOperation("鍒犻櫎搴旀�ラ妗堟煡闃�")
+    @Operation(summary = "鍒犻櫎搴旀�ラ妗堟煡闃�")
     @DeleteMapping("/{ids}")
     public R delSafeCertification(@RequestBody List<Integer> ids) {
         return R.ok(safeContingencyPlanService.removeBatchByIds(ids));
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeHazardController.java b/src/main/java/com/ruoyi/safe/controller/SafeHazardController.java
index 60aa9ee..b433d04 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeHazardController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeHazardController.java
@@ -2,13 +2,11 @@
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.safe.pojo.SafeCertification;
 import com.ruoyi.safe.pojo.SafeHazard;
-import com.ruoyi.safe.service.SafeCertificationService;
 import com.ruoyi.safe.service.SafeHazardService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -23,31 +21,31 @@
  */
 @RestController
 @RequestMapping("/safeHazard")
-@Api(tags = "瀹夊叏鐢熶骇--鍗遍櫓婧愬彴璐�")
+@Tag(name = "瀹夊叏鐢熶骇--鍗遍櫓婧愬彴璐�")
+@AllArgsConstructor
 public class SafeHazardController {
 
-    @Autowired
     private SafeHazardService safeHazardService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page page, SafeHazard safeHazard) {
         return R.ok(safeHazardService.pageSafeHazard(page, safeHazard));
     }
 
-    @ApiOperation("鏂板鍗遍櫓婧愬彴璐�")
+    @Operation(summary = "鏂板鍗遍櫓婧愬彴璐�")
     @PostMapping()
     public R add(@RequestBody SafeHazard safeHazard) {
         return R.ok(safeHazardService.save(safeHazard));
     }
 
-    @ApiOperation("淇敼鍗遍櫓婧愬彴璐�")
+    @Operation(summary = "淇敼鍗遍櫓婧愬彴璐�")
     @PutMapping ()
     public R update(@RequestBody  SafeHazard safeHazard) {
         return R.ok(safeHazardService.updateById(safeHazard));
     }
 
-    @ApiOperation("鍒犻櫎鍗遍櫓婧愬彴璐�")
+    @Operation(summary = "鍒犻櫎鍗遍櫓婧愬彴璐�")
     @DeleteMapping("/{ids}")
     public R delSafeHazard(@RequestBody List<Integer> ids) {
         return R.ok(safeHazardService.delSafeHazard(ids));
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeHazardRecordController.java b/src/main/java/com/ruoyi/safe/controller/SafeHazardRecordController.java
index 9e4e139..681efa5 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeHazardRecordController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeHazardRecordController.java
@@ -3,13 +3,11 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.safe.dto.SafeHazardRecordDto;
-import com.ruoyi.safe.pojo.SafeHazard;
 import com.ruoyi.safe.pojo.SafeHazardRecord;
 import com.ruoyi.safe.service.SafeHazardRecordService;
-import com.ruoyi.safe.service.SafeHazardService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -24,31 +22,31 @@
  */
 @RestController
 @RequestMapping("/safeHazardRecord")
-@Api(tags = "瀹夊叏鐢熶骇--鍗遍櫓鐗╂枡绠℃帶")
+@Tag(name = "瀹夊叏鐢熶骇--鍗遍櫓鐗╂枡绠℃帶")
+@AllArgsConstructor
 public class SafeHazardRecordController {
 
-    @Autowired
     private SafeHazardRecordService safeHazardRecordService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page page, SafeHazardRecordDto safeHazardRecordDto) {
         return R.ok(safeHazardRecordService.pageSafeHazardRecord(page, safeHazardRecordDto));
     }
 
-    @ApiOperation("棰嗙敤")
+    @Operation(summary = "棰嗙敤")
     @PostMapping("/borrow")
     public R borrow(@RequestBody SafeHazardRecord safeHazardRecord) {
         return R.ok(safeHazardRecordService.borrow(safeHazardRecord));
     }
 
-    @ApiOperation("褰掕繕")
+    @Operation(summary = "褰掕繕")
     @PutMapping("/return")
     public R returnSafeHazardRecord(@RequestBody  SafeHazardRecord safeHazardRecord) {
         return R.ok(safeHazardRecordService.returnSafeHazardRecord(safeHazardRecord));
     }
 
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     @DeleteMapping("/{ids}")
     public R delSafeHazardRecord(@RequestBody List<Integer> ids) {
         return R.ok(safeHazardRecordService.delSafeHazardRecord(ids));
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeHiddenController.java b/src/main/java/com/ruoyi/safe/controller/SafeHiddenController.java
index f8186ae..f77f294 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeHiddenController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeHiddenController.java
@@ -3,13 +3,11 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.safe.dto.SafeHiddenDto;
-import com.ruoyi.safe.pojo.SafeHazard;
 import com.ruoyi.safe.pojo.SafeHidden;
-import com.ruoyi.safe.service.SafeHazardService;
 import com.ruoyi.safe.service.SafeHiddenService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -24,31 +22,31 @@
  */
 @RestController
 @RequestMapping("/safeHidden")
-@Api(tags = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤")
+@AllArgsConstructor
+@Tag(name = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤")
 public class SafeHiddenController {
 
-    @Autowired
     private SafeHiddenService safeHiddenService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page page, SafeHiddenDto safeHiddenDto) {
         return R.ok(safeHiddenService.pageSafeHidden(page, safeHiddenDto));
     }
 
-    @ApiOperation("鏂板闅愭偅鎺掓煡")
+    @Operation(summary = "鏂板闅愭偅鎺掓煡")
     @PostMapping()
     public R add(@RequestBody SafeHidden safeHidden) {
         return R.ok(safeHiddenService.add(safeHidden));
     }
 
-    @ApiOperation("淇敼闅愭偅鎺掓煡(鏁存敼/楠屾敹)")
+    @Operation(summary = "淇敼闅愭偅鎺掓煡(鏁存敼/楠屾敹)")
     @PutMapping ()
     public R update(@RequestBody SafeHidden safeHidden) {
         return R.ok(safeHiddenService.updateById(safeHidden));
     }
 
-    @ApiOperation("鍒犻櫎闅愭偅鎺掓煡")
+    @Operation(summary = "鍒犻櫎闅愭偅鎺掓煡")
     @DeleteMapping("/{ids}")
     public R delSafeHidden(@RequestBody List<Integer> ids) {
         return R.ok(safeHiddenService.delSafeHidden(ids));
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeHiddenFileController.java b/src/main/java/com/ruoyi/safe/controller/SafeHiddenFileController.java
index 6d229c0..511bdb7 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeHiddenFileController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeHiddenFileController.java
@@ -5,12 +5,12 @@
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.safe.pojo.SafeHiddenFile;
 import com.ruoyi.safe.service.SafeHiddenFileService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
@@ -23,7 +23,7 @@
  */
 @RestController
 @RequestMapping("/safeHiddenFile")
-@Api(tags = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤--闄勪欢")
+@Tag(name = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤--闄勪欢")
 public class SafeHiddenFileController {
 
     @Resource
@@ -36,7 +36,7 @@
      * @return
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public R add(@RequestBody SafeHiddenFile safeHiddenFile) {
         return R.ok(safeHiddenFileService.save(safeHiddenFile));
     }
@@ -47,7 +47,7 @@
      * @return
      */
     @DeleteMapping("/del")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public R delSafeHiddenFile(@RequestBody List<Integer> ids) {
         if(CollectionUtils.isEmpty(ids)){
             return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -63,7 +63,7 @@
      * @return
      */
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R listPage(Page page, SafeHiddenFile safeHiddenFile) {
         return R.ok(safeHiddenFileService.page(page, Wrappers.<SafeHiddenFile>lambdaQuery().eq(SafeHiddenFile::getSafeHiddenId,safeHiddenFile.getSafeHiddenId())));
     }
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java b/src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java
index 3ea4689..dd8b6f5 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java
@@ -3,18 +3,16 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.safe.dto.SafeTrainingDto;
-import com.ruoyi.safe.pojo.SafeAccident;
 import com.ruoyi.safe.pojo.SafeTraining;
 import com.ruoyi.safe.pojo.SafeTrainingDetails;
-import com.ruoyi.safe.service.SafeAccidentService;
 import com.ruoyi.safe.service.SafeTrainingDetailsService;
 import com.ruoyi.safe.service.SafeTrainingService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -27,52 +25,50 @@
  */
 @RestController
 @RequestMapping("/safeTraining")
-@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳")
+@Tag(name = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳")
+@RequiredArgsConstructor
 public class SafeTrainingController {
 
-    @Autowired
-    private SafeTrainingService safeTrainingService;
-
-    @Autowired
-    private SafeTrainingDetailsService safeTrainingDetailsService;
+    private final SafeTrainingService safeTrainingService;
+    private final SafeTrainingDetailsService safeTrainingDetailsService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page page, SafeTrainingDto safeTrainingDto) {
         return R.ok(safeTrainingService.pageSafeTraining(page, safeTrainingDto));
     }
 
-    @ApiOperation("鏂板/缂栬緫瀹夊叏鍩硅鑰冩牳")
+    @Operation(summary = "鏂板/缂栬緫瀹夊叏鍩硅鑰冩牳")
     @PostMapping()
     public R addOrUpdate(@RequestBody SafeTraining safeTraining) {
         return R.ok(safeTrainingService.addOrUpdate(safeTraining));
     }
 
-    @ApiOperation("绛惧埌")
+    @Operation(summary = "绛惧埌")
     @PostMapping ("/sign")
     public R sign(@RequestBody SafeTrainingDetails safeTrainingDetails) {
         return R.ok(safeTrainingDetailsService.save(safeTrainingDetails));
     }
 
-    @ApiOperation("缁撴灉鏄庣粏鏌ヨ")
+    @Operation(summary = "缁撴灉鏄庣粏鏌ヨ")
     @GetMapping ("/getSafeTraining")
     public R getSafeTraining(Long id) {
         return R.ok(safeTrainingService.getSafeTraining(id));
     }
 
-    @ApiOperation("缁撴灉鏄庣粏淇濆瓨")
+    @Operation(summary = "缁撴灉鏄庣粏淇濆瓨")
     @PostMapping ("/saveSafeTraining")
     public R saveSafeTraining(@RequestBody SafeTrainingDto safeTrainingDto) {
         return R.ok(safeTrainingService.saveSafeTraining(safeTrainingDto));
     }
 
-    @ApiOperation("鍒犻櫎瀹夊叏鍩硅鑰冩牳")
+    @Operation(summary = "鍒犻櫎瀹夊叏鍩硅鑰冩牳")
     @DeleteMapping("/{ids}")
     public R delSafeTraining(@RequestBody List<Integer> ids) {
         return R.ok(safeTrainingService.delSafeTraining(ids));
     }
 
-    @ApiOperation("瀵煎嚭")
+    @Operation(summary = "瀵煎嚭")
     @PostMapping ("/export")
     public void export(HttpServletResponse response, @RequestBody SafeTraining safeTraining) {
         safeTrainingService.export(response,safeTraining.getId());
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeTrainingDetailsController.java b/src/main/java/com/ruoyi/safe/controller/SafeTrainingDetailsController.java
index 75bcfb9..63a03e4 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeTrainingDetailsController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeTrainingDetailsController.java
@@ -2,16 +2,13 @@
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.safe.dto.SafeTrainingDto;
-import com.ruoyi.safe.pojo.SafeTraining;
 import com.ruoyi.safe.pojo.SafeTrainingDetails;
 import com.ruoyi.safe.service.SafeTrainingDetailsService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletResponse;
 
 /**
  * <p>
@@ -23,20 +20,20 @@
  */
 @RestController
 @RequestMapping("/safeTrainingDetails")
-@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏")
+@Tag(name = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏")
+@AllArgsConstructor
 public class SafeTrainingDetailsController {
 
 
-    @Autowired
-    private SafeTrainingDetailsService safeTrainingDetailsService;
+    private final SafeTrainingDetailsService safeTrainingDetailsService;
 
     @GetMapping("/page")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R page(Page page, SafeTrainingDetails safeTrainingDetails) {
         return R.ok(safeTrainingDetailsService.pageDetails(page, safeTrainingDetails));
     }
 
-    @ApiOperation("瀵煎嚭")
+    @Operation(summary = "瀵煎嚭")
     @PostMapping("/export")
     public void export(HttpServletResponse response, @RequestBody SafeTrainingDetails safeTrainingDetails) {
         safeTrainingDetailsService.export(response,safeTrainingDetails.getUserId());
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeTrainingFileController.java b/src/main/java/com/ruoyi/safe/controller/SafeTrainingFileController.java
index 3057900..5d18a03 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeTrainingFileController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeTrainingFileController.java
@@ -6,12 +6,12 @@
 import com.ruoyi.safe.pojo.SafeHiddenFile;
 import com.ruoyi.safe.pojo.SafeTrainingFile;
 import com.ruoyi.safe.service.SafeTrainingFileService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
@@ -24,7 +24,7 @@
  */
 @RestController
 @RequestMapping("/safeTrainingFile")
-@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢")
+@Tag(name = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢")
 public class SafeTrainingFileController {
 
     @Resource
@@ -37,7 +37,7 @@
      * @return
      */
     @PostMapping("/add")
-    @ApiOperation("鏂板")
+    @Operation(summary = "鏂板")
     public R add(@RequestBody SafeTrainingFile safeHiddenFile) {
         return R.ok(safeTrainingFileService.save(safeHiddenFile));
     }
@@ -48,7 +48,7 @@
      * @return
      */
     @DeleteMapping("/del")
-    @ApiOperation("鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     public R delSafeHiddenFile(@RequestBody List<Integer> ids) {
         if(CollectionUtils.isEmpty(ids)){
             return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
@@ -64,7 +64,7 @@
      * @return
      */
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public R listPage(Page page, SafeTrainingFile safeTrainingFile) {
         return R.ok(safeTrainingFileService.page(page, Wrappers.<SafeTrainingFile>lambdaQuery().eq(SafeTrainingFile::getSafeTrainingId,safeTrainingFile.getSafeTrainingId())));
     }
diff --git a/src/main/java/com/ruoyi/safe/dto/SafeHazardRecordDto.java b/src/main/java/com/ruoyi/safe/dto/SafeHazardRecordDto.java
index 3d2c2e0..49615ff 100644
--- a/src/main/java/com/ruoyi/safe/dto/SafeHazardRecordDto.java
+++ b/src/main/java/com/ruoyi/safe/dto/SafeHazardRecordDto.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.safe.pojo.SafeHazardRecord;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.Getter;
 import lombok.Setter;
@@ -18,25 +17,25 @@
 @Data
 public class SafeHazardRecordDto extends SafeHazardRecord {
 
-    @ApiModelProperty("棰嗙敤浜�")
+    @Schema(description = "棰嗙敤浜�")
     private String applyUserName;
 
-    @ApiModelProperty("褰掕繕浜�")
+    @Schema(description = "褰掕繕浜�")
     private String returnUserName;
 
-    @ApiModelProperty("鍗遍櫓婧愬悕绉�")
+    @Schema(description = "鍗遍櫓婧愬悕绉�")
     private String name;
 
-    @ApiModelProperty("鍗遍櫓婧愮紪鐮�")
+    @Schema(description = "鍗遍櫓婧愮紪鐮�")
     private String code;
 
-    @ApiModelProperty("鍗遍櫓婧愮被鍨�")
+    @Schema(description = "鍗遍櫓婧愮被鍨�")
     private String type;
 
-    @ApiModelProperty("椋庨櫓绛夌骇")
+    @Schema(description = "椋庨櫓绛夌骇")
     private String riskLevel;
 
-    @ApiModelProperty("鎵�鍦ㄤ綅缃�")
+    @Schema(description = "鎵�鍦ㄤ綅缃�")
     private String location;
 
 
diff --git a/src/main/java/com/ruoyi/safe/dto/SafeHiddenDto.java b/src/main/java/com/ruoyi/safe/dto/SafeHiddenDto.java
index fedb6a0..f99b423 100644
--- a/src/main/java/com/ruoyi/safe/dto/SafeHiddenDto.java
+++ b/src/main/java/com/ruoyi/safe/dto/SafeHiddenDto.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.safe.pojo.SafeHidden;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.Getter;
 import lombok.Setter;
@@ -17,12 +16,12 @@
 @Data
 public class SafeHiddenDto extends SafeHidden {
 
-    @ApiModelProperty("涓婃姤浜�")
+    @Schema(description = "涓婃姤浜�")
     private String createUserName;
 
-    @ApiModelProperty("鏁存敼璐d换浜�")
+    @Schema(description = "鏁存敼璐d换浜�")
     private String rectifyUserName;
 
-    @ApiModelProperty("楠屾敹浜�")
+    @Schema(description = "楠屾敹浜�")
     private String verifyUserName;
 }
diff --git a/src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java b/src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java
index 0eb6da5..bbdf02e 100644
--- a/src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java
+++ b/src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.safe.pojo.SafeTrainingDetails;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.Getter;
 import lombok.Setter;
@@ -16,13 +15,13 @@
 @Data
 public class SafeTrainingDetailsDto extends SafeTrainingDetails {
 
-    @ApiModelProperty("鍩硅浜哄憳缂栧彿")
+    @Schema(description = "鍩硅浜哄憳缂栧彿")
     private String userName;
 
-    @ApiModelProperty("鍩硅浜哄憳鍚嶇О")
+    @Schema(description = "鍩硅浜哄憳鍚嶇О")
     private String nickName;
 
-    @ApiModelProperty("鎵嬫満鍙风爜")
+    @Schema(description = "鎵嬫満鍙风爜")
     private String phonenumber;
 
 
diff --git a/src/main/java/com/ruoyi/safe/dto/SafeTrainingDto.java b/src/main/java/com/ruoyi/safe/dto/SafeTrainingDto.java
index 0b8d7cd..fc64f64 100644
--- a/src/main/java/com/ruoyi/safe/dto/SafeTrainingDto.java
+++ b/src/main/java/com/ruoyi/safe/dto/SafeTrainingDto.java
@@ -3,7 +3,7 @@
 import com.ruoyi.safe.pojo.SafeTraining;
 import com.ruoyi.safe.pojo.SafeTrainingDetails;
 import com.ruoyi.safe.pojo.SafeTrainingFile;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.List;
@@ -11,16 +11,16 @@
 @Data
 public class SafeTrainingDto extends SafeTraining {
 
-    @ApiModelProperty("鎶ュ悕浜烘暟")
+    @Schema(description = "鎶ュ悕浜烘暟")
     private Integer nums;
 
-    @ApiModelProperty("璇勪环浜�")
+    @Schema(description = "璇勪环浜�")
     private String assessmentUserName;
 
-    @ApiModelProperty("闄勪欢闆嗗悎")
+    @Schema(description = "闄勪欢闆嗗悎")
     private List<SafeTrainingFile> safeTrainingFileList;
 
-    @ApiModelProperty("鍩硅璁板綍浜哄憳璇︽儏闆嗗悎")
+    @Schema(description = "鍩硅璁板綍浜哄憳璇︽儏闆嗗悎")
     private List<SafeTrainingDetailsDto> safeTrainingDetailsDtoList;
 
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeAccident.java b/src/main/java/com/ruoyi/safe/pojo/SafeAccident.java
index 8bbc898..74a46b6 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeAccident.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeAccident.java
@@ -10,8 +10,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -27,7 +26,7 @@
 @Getter
 @Setter
 @TableName("safe_accident")
-@ApiModel(value = "SafeAccident瀵硅薄", description = "瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍")
+@Schema(name = "SafeAccident瀵硅薄", description = "瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍")
 public class SafeAccident implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -35,61 +34,61 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("浜嬫晠缂栧彿")
+    @Schema(description = "浜嬫晠缂栧彿")
     private String accidentCode;
 
-    @ApiModelProperty("浜嬫晠鍚嶇О")
+    @Schema(description = "浜嬫晠鍚嶇О")
     private String accidentName;
 
-    @ApiModelProperty("浜嬫晠绫诲瀷")
+    @Schema(description = "浜嬫晠绫诲瀷")
     private String accidentType;
 
-    @ApiModelProperty("浜嬫晠鍙戠敓鏃堕棿")
+    @Schema(description = "浜嬫晠鍙戠敓鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime happenTime;
 
-    @ApiModelProperty("浜嬫晠鍙戠敓浣嶇疆")
+    @Schema(description = "浜嬫晠鍙戠敓浣嶇疆")
     private String happenLocation;
 
-    @ApiModelProperty("浜嬫晠绛夌骇")
+    @Schema(description = "浜嬫晠绛夌骇")
     private String accidentGrade;
 
-    @ApiModelProperty("浜嬫晠鐩存帴鍘熷洜")
+    @Schema(description = "浜嬫晠鐩存帴鍘熷洜")
     private String accidentCause;
 
-    @ApiModelProperty("浜嬫晠鏍规湰鍘熷洜")
+    @Schema(description = "浜嬫晠鏍规湰鍘熷洜")
     private String rootCause;
 
-    @ApiModelProperty("浜哄憳鎹熷け鎯呭喌")
+    @Schema(description = "浜哄憳鎹熷け鎯呭喌")
     private String personLoss;
 
-    @ApiModelProperty("鐩存帴璐骇鎹熷け锛堝厓锛�	")
+    @Schema(description = "鐩存帴璐骇鎹熷け锛堝厓锛�	")
     private BigDecimal assetLoss;
 
-    @ApiModelProperty("鐢熶骇褰卞搷鎯呭喌")
+    @Schema(description = "鐢熶骇褰卞搷鎯呭喌")
     private String productionLoss;
 
-    @ApiModelProperty("鐜板満搴旀�ュ缃帾鏂�")
+    @Schema(description = "鐜板満搴旀�ュ缃帾鏂�")
     private String handleMeasures;
 
-    @ApiModelProperty("浜嬫晠璐d换浜�")
+    @Schema(description = "浜嬫晠璐d换浜�")
     private String responsiblePerson;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("涓婃姤鏃堕棿")
+    @Schema(description = "涓婃姤鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("涓婃姤浜篿d")
+    @Schema(description = "涓婃姤浜篿d")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("涓婃姤浜�")
+    @Schema(description = "涓婃姤浜�")
     @TableField(exist = false)
     private String createUserName;
 
@@ -103,4 +102,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeCertification.java b/src/main/java/com/ruoyi/safe/pojo/SafeCertification.java
index 60a768a..770e123 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeCertification.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeCertification.java
@@ -10,8 +10,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -27,7 +26,7 @@
 @Getter
 @Setter
 @TableName("safe_certification")
-@ApiModel(value = "SafeCertification瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
+@Schema(name = "SafeCertification瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
 public class SafeCertification implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -35,22 +34,22 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("瑙勭▼璧勮川鍚嶇О")
+    @Schema(description = "瑙勭▼璧勮川鍚嶇О")
     private String name;
 
-    @ApiModelProperty("瑙勭▼璧勮川缂栧彿")
+    @Schema(description = "瑙勭▼璧勮川缂栧彿")
     private String code;
 
-    @ApiModelProperty("瑙勭▼璧勮川绫诲瀷")
+    @Schema(description = "瑙勭▼璧勮川绫诲瀷")
     private String type;
 
-    @ApiModelProperty("鐗堟湰鍙�")
+    @Schema(description = "鐗堟湰鍙�")
     private String version;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("鏈夋晥鏈�")
+    @Schema(description = "鏈夋晥鏈�")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate effectiveTime;
@@ -73,4 +72,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeCertificationFile.java b/src/main/java/com/ruoyi/safe/pojo/SafeCertificationFile.java
index e9efecc..cc59b6f 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeCertificationFile.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeCertificationFile.java
@@ -7,12 +7,11 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 
 /**
  * <p>
@@ -25,7 +24,7 @@
 @Getter
 @Setter
 @TableName("safe_certification_file")
-@ApiModel(value = "SafeCertificationFile瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�--闄勪欢")
+@Schema(name = "SafeCertificationFile瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�--闄勪欢")
 public class SafeCertificationFile implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -33,7 +32,7 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鍏宠仈瀹夊叏鐢熶骇璧勮川id")
+    @Schema(description = "鍏宠仈瀹夊叏鐢熶骇璧勮川id")
     @NotBlank(message = "鍏宠仈瀹夊叏鐢熶骇璧勮川id涓嶈兘涓虹┖")
     private Integer safeCertificationId;
 
@@ -57,4 +56,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java b/src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java
index 2cad42f..869d84f 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java
@@ -10,8 +10,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -27,7 +26,7 @@
 @Getter
 @Setter
 @TableName("safe_contingency_plan")
-@ApiModel(value = "SafeContingencyPlan瀵硅薄", description = "瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃�")
+@Schema(name = "SafeContingencyPlan瀵硅薄", description = "瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃�")
 public class SafeContingencyPlan implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -35,34 +34,34 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("搴旀�ラ妗堢紪鐮�")
+    @Schema(description = "搴旀�ラ妗堢紪鐮�")
     private String planCode;
 
-    @ApiModelProperty("搴旀�ラ妗堝悕绉�")
+    @Schema(description = "搴旀�ラ妗堝悕绉�")
     private String planName;
 
-    @ApiModelProperty("棰勬绫诲瀷")
+    @Schema(description = "棰勬绫诲瀷")
     private String planType;
 
-    @ApiModelProperty("閫傜敤鑼冨洿")
+    @Schema(description = "閫傜敤鑼冨洿")
     private String applyScope;
 
-    @ApiModelProperty("鏍稿績璐d换浜�")
+    @Schema(description = "鏍稿績璐d换浜�")
     private Integer coreResponsorUserId;
 
-    @ApiModelProperty("鏍稿績璐d换浜�")
+    @Schema(description = "鏍稿績璐d换浜�")
     @TableField(exist = false)
     private String coreResponsorUserName;
 
-    @ApiModelProperty("搴旀�ュ缃楠�")
+    @Schema(description = "搴旀�ュ缃楠�")
     private String execSteps;
 
-    @ApiModelProperty("鍙戝竷鐢熸晥鏃堕棿")
+    @Schema(description = "鍙戝竷鐢熸晥鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate publishTime;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
     @TableField(fill = FieldFill.INSERT)
@@ -73,7 +72,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏈�鍚庝慨璁㈡椂闂�")
+    @Schema(description = "鏈�鍚庝慨璁㈡椂闂�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@@ -84,4 +83,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeHazard.java b/src/main/java/com/ruoyi/safe/pojo/SafeHazard.java
index 43e5c1e..ca88032 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeHazard.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeHazard.java
@@ -10,8 +10,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -27,7 +26,7 @@
 @Getter
 @Setter
 @TableName("safe_hazard")
-@ApiModel(value = "SafeHazard瀵硅薄", description = "瀹夊叏鐢熶骇--鍗遍櫓婧愬彴璐�")
+@Schema(name = "SafeHazard瀵硅薄", description = "瀹夊叏鐢熶骇--鍗遍櫓婧愬彴璐�")
 public class SafeHazard implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -35,41 +34,41 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鍗遍櫓婧愬悕绉�")
+    @Schema(description = "鍗遍櫓婧愬悕绉�")
     private String name;
 
-    @ApiModelProperty("鍗遍櫓婧愮紪鐮�")
+    @Schema(description = "鍗遍櫓婧愮紪鐮�")
     private String code;
 
-    @ApiModelProperty("鍗遍櫓婧愮被鍨�")
+    @Schema(description = "鍗遍櫓婧愮被鍨�")
     private String type;
 
-    @ApiModelProperty("椋庨櫓绛夌骇")
+    @Schema(description = "椋庨櫓绛夌骇")
     private String riskLevel;
 
-    @ApiModelProperty("鎵�鍦ㄤ綅缃�")
+    @Schema(description = "鎵�鍦ㄤ綅缃�")
     private String location;
 
-    @ApiModelProperty("瑙勬牸 / 椋庨櫓鎻忚堪")
+    @Schema(description = "瑙勬牸 / 椋庨櫓鎻忚堪")
     private String specInfo;
 
-    @ApiModelProperty("绠℃帶鎺柦")
+    @Schema(description = "绠℃帶鎺柦")
     private String controlMeasures;
 
-    @ApiModelProperty("绠℃帶璐d换浜� ID")
+    @Schema(description = "绠℃帶璐d换浜� ID")
     private Integer principalUserId;
 
-    @ApiModelProperty("绠℃帶璐d换浜�")
+    @Schema(description = "绠℃帶璐d换浜�")
     @TableField(exist = false)
     private String principalUser;
 
-    @ApiModelProperty("璐d换浜鸿仈绯荤數璇�")
+    @Schema(description = "璐d换浜鸿仈绯荤數璇�")
     private String principalMobile;
 
-    @ApiModelProperty("搴撳瓨鏁伴噺")
+    @Schema(description = "搴撳瓨鏁伴噺")
     private BigDecimal stockQty;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
     @TableField(fill = FieldFill.INSERT)
@@ -90,4 +89,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeHazardRecord.java b/src/main/java/com/ruoyi/safe/pojo/SafeHazardRecord.java
index 45ff844..79b59aa 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeHazardRecord.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeHazardRecord.java
@@ -11,8 +11,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -28,7 +27,7 @@
 @Getter
 @Setter
 @TableName("safe_hazard_record")
-@ApiModel(value = "SafeHazardRecord瀵硅薄", description = "瀹夊叏鐢熶骇--鍗遍櫓鐗╂枡绠℃帶")
+@Schema(name = "SafeHazardRecord瀵硅薄", description = "瀹夊叏鐢熶骇--鍗遍櫓鐗╂枡绠℃帶")
 public class SafeHazardRecord implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -36,35 +35,35 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鍗曞彿")
+    @Schema(description = "鍗曞彿")
     private String materialRecordCode;
 
-    @ApiModelProperty("鍏宠仈鍗遍櫓婧愬彴璐� ID")
+    @Schema(description = "鍏宠仈鍗遍櫓婧愬彴璐� ID")
     private Integer safeHazardId;
 
-    @ApiModelProperty("棰嗙敤浜� ID")
+    @Schema(description = "棰嗙敤浜� ID")
     private Integer applyUserId;
 
-    @ApiModelProperty("棰嗙敤鏃堕棿")
+    @Schema(description = "棰嗙敤鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate applyTime;
 
-    @ApiModelProperty("棰嗙敤鏁伴噺")
+    @Schema(description = "棰嗙敤鏁伴噺")
     private BigDecimal applyQty;
 
-    @ApiModelProperty("棰嗙敤鐢ㄩ��")
+    @Schema(description = "棰嗙敤鐢ㄩ��")
     private String applyPurpose;
 
-    @ApiModelProperty("褰掕繕浜� ID")
+    @Schema(description = "褰掕繕浜� ID")
     private Integer returnUserId;
 
-    @ApiModelProperty("褰掕繕鏃堕棿")
+    @Schema(description = "褰掕繕鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate returnTime;
 
-    @ApiModelProperty("褰掕繕鎯呭喌璇存槑")
+    @Schema(description = "褰掕繕鎯呭喌璇存槑")
     private String returnRemark;
 
     @TableField(fill = FieldFill.INSERT)
@@ -85,4 +84,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeHidden.java b/src/main/java/com/ruoyi/safe/pojo/SafeHidden.java
index ba64039..1b10824 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeHidden.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeHidden.java
@@ -1,22 +1,15 @@
 package com.ruoyi.safe.pojo;
 
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
 import java.io.Serializable;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Getter;
-import lombok.Setter;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import javax.validation.constraints.NotBlank;
 
 /**
  * <p>
@@ -26,10 +19,9 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-01-28 11:10:54
  */
-@Getter
-@Setter
+@Data
 @TableName("safe_hidden")
-@ApiModel(value = "SafeHidden瀵硅薄", description = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤")
+@Schema(name = "SafeHidden瀵硅薄", description = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤")
 public class SafeHidden implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -37,63 +29,63 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("闅愭偅缂栧彿")
+    @Schema(description = "闅愭偅缂栧彿")
     private String hiddenCode;
 
-    @ApiModelProperty("闅愭偅绫诲瀷")
+    @Schema(description = "闅愭偅绫诲瀷")
     private String type;
 
-    @ApiModelProperty("闅愭偅椋庨櫓绛夌骇")
+    @Schema(description = "闅愭偅椋庨櫓绛夌骇")
     private String riskLevel;
 
-    @ApiModelProperty("闅愭偅鍏蜂綋浣嶇疆")
+    @Schema(description = "闅愭偅鍏蜂綋浣嶇疆")
     private String location;
 
-    @ApiModelProperty("闅愭偅鎻忚堪")
+    @Schema(description = "闅愭偅鎻忚堪")
     private String hiddenDesc;
 
-    @ApiModelProperty("鏁存敼璐d换浜� ID")
+    @Schema(description = "鏁存敼璐d换浜� ID")
     @NotBlank(message = "鏁存敼璐d换浜轰笉鑳戒负绌�")
     private Integer rectifyUserId;
 
-    @ApiModelProperty("鏁存敼浜鸿仈绯荤數璇�")
+    @Schema(description = "鏁存敼浜鸿仈绯荤數璇�")
     private String rectifyUserMobile;
 
-    @ApiModelProperty("鏁存敼瀹屾垚鏈熼檺(鏃ユ湡)")
+    @Schema(description = "鏁存敼瀹屾垚鏈熼檺(鏃ユ湡)")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @NotBlank(message = "鏁存敼瀹屾垚鏈熼檺涓嶈兘涓虹┖")
     private LocalDate rectifyTime;
 
-    @ApiModelProperty("鏁存敼鍏蜂綋鎺柦")
+    @Schema(description = "鏁存敼鍏蜂綋鎺柦")
     private String rectifyMeasures;
 
-    @ApiModelProperty("瀹為檯鏁存敼瀹屾垚鏃堕棿")
+    @Schema(description = "瀹為檯鏁存敼瀹屾垚鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate rectifyActualTime;
 
-    @ApiModelProperty("楠屾敹浜� ID")
+    @Schema(description = "楠屾敹浜� ID")
     private Integer verifyUserId;
 
-    @ApiModelProperty("楠屾敹缁撴灉")
+    @Schema(description = "楠屾敹缁撴灉")
     private String verifyResult;
 
-    @ApiModelProperty("楠屾敹鎰忚")
+    @Schema(description = "楠屾敹鎰忚")
     private String verifyRemark;
 
-    @ApiModelProperty("楠屾敹鏃堕棿")
+    @Schema(description = "楠屾敹鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate verifyTime;
 
-    @ApiModelProperty("涓婃姤鏃堕棿")
+    @Schema(description = "涓婃姤鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("涓婃姤浜篿d")
+    @Schema(description = "涓婃姤浜篿d")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
@@ -107,4 +99,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeHiddenFile.java b/src/main/java/com/ruoyi/safe/pojo/SafeHiddenFile.java
index 59f67d1..320af53 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeHiddenFile.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeHiddenFile.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,7 +22,7 @@
 @Getter
 @Setter
 @TableName("safe_hidden_file")
-@ApiModel(value = "SafeHiddenFile瀵硅薄", description = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤--闄勪欢")
+@Schema(name = "SafeHiddenFile瀵硅薄", description = "瀹夊叏鐢熶骇--闅愭偅鎺掓煡涓婃姤--闄勪欢")
 public class SafeHiddenFile implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -31,7 +30,7 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鍏宠仈闅愭偅鎺掓煡涓婃姤id")
+    @Schema(description = "鍏宠仈闅愭偅鎺掓煡涓婃姤id")
     private Integer safeHiddenId;
 
     private String name;
@@ -54,4 +53,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeTraining.java b/src/main/java/com/ruoyi/safe/pojo/SafeTraining.java
index f9ecc29..b4add43 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeTraining.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeTraining.java
@@ -11,13 +11,12 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 
 /**
  * <p>
@@ -30,7 +29,7 @@
 @Getter
 @Setter
 @TableName("safe_training")
-@ApiModel(value = "SafeTraining瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳")
+@Schema(name = "SafeTraining瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳")
 public class SafeTraining implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -38,68 +37,68 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("璇剧▼缂栧彿")
+    @Schema(description = "璇剧▼缂栧彿")
     private String courseCode;
 
-    @ApiModelProperty("鍩硅鐩爣")
+    @Schema(description = "鍩硅鐩爣")
     private String trainingObjectives;
 
-    @ApiModelProperty("鍩硅鍐呭")
+    @Schema(description = "鍩硅鍐呭")
     private String trainingContent;
 
-    @ApiModelProperty("鍩硅鏂瑰紡")
+    @Schema(description = "鍩硅鏂瑰紡")
     private String trainingMode;
 
-    @ApiModelProperty("鐘舵��(0锛氭湭寮�濮�1锛氳繘琛屼腑锛�2锛氬凡缁撴潫)")
+    @Schema(description = "鐘舵��(0锛氭湭寮�濮�1锛氳繘琛屼腑锛�2锛氬凡缁撴潫)")
     private Integer state;
 
-    @ApiModelProperty("鍙傚姞瀵硅薄")
+    @Schema(description = "鍙傚姞瀵硅薄")
     private String participants;
 
-    @ApiModelProperty("鍩硅鍦扮偣")
+    @Schema(description = "鍩硅鍦扮偣")
     private String placeTraining;
 
-    @ApiModelProperty("鍩硅璁插笀")
+    @Schema(description = "鍩硅璁插笀")
     private String trainingLecturer;
 
-    @ApiModelProperty("鍩硅鏃ユ湡")
+    @Schema(description = "鍩硅鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @NotBlank(message = "鍩硅鏃ユ湡涓嶈兘涓虹┖")
     private LocalDate trainingDate;
 
-    @ApiModelProperty("寮�濮嬫椂闂�(鏃跺垎绉�)")
+    @Schema(description = "寮�濮嬫椂闂�(鏃跺垎绉�)")
     @NotBlank(message = "寮�濮嬫椂闂翠笉鑳戒负绌�")
     private String openingTime;
 
-    @ApiModelProperty("缁撴潫鏃堕棿(鏃跺垎绉�)")
+    @Schema(description = "缁撴潫鏃堕棿(鏃跺垎绉�)")
     @NotBlank(message = "缁撴潫鏃堕棿涓嶈兘涓虹┖")
     private String endTime;
 
-    @ApiModelProperty("璇鹃瀛﹀垎")
+    @Schema(description = "璇鹃瀛﹀垎")
     private String projectCredits;
 
-    @ApiModelProperty("璇炬椂")
+    @Schema(description = "璇炬椂")
     private Double classHour;
 
-    @ApiModelProperty("鑰冩牳鏂瑰紡")
+    @Schema(description = "鑰冩牳鏂瑰紡")
     private String assessmentMethod;
 
-    @ApiModelProperty("鏈鍩硅缁煎悎璇勪环")
+    @Schema(description = "鏈鍩硅缁煎悎璇勪环")
     private String comprehensiveAssessment;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remarks;
 
-    @ApiModelProperty("璇勪环浜篿d")
+    @Schema(description = "璇勪环浜篿d")
     private Integer assessmentUserId;
 
-    @ApiModelProperty("璇勪环鏃堕棿")
+    @Schema(description = "璇勪环鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate assessmentDate;
 
-    @ApiModelProperty("鍩硅鎽樿")
+    @Schema(description = "鍩硅鎽樿")
     private String trainingAbstract;
 
     @TableField(fill = FieldFill.INSERT)
@@ -120,4 +119,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java
index a53ea3d..a0611d9 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java
@@ -1,22 +1,17 @@
 package com.ruoyi.safe.pojo;
 
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import java.io.Serializable;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
+import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
 
 /**
  * <p>
@@ -29,7 +24,7 @@
 @Getter
 @Setter
 @TableName("safe_training_details")
-@ApiModel(value = "SafeTrainingDetails瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏")
+@Schema(name = "SafeTrainingDetails瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏")
 public class SafeTrainingDetails implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -37,14 +32,14 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鐢ㄦ埛琛ㄦ牸锛坲ser锛変富閿�")
+    @Schema(description = "鐢ㄦ埛琛ㄦ牸锛坲ser锛変富閿�")
     @NotBlank(message = "鐢ㄦ埛id涓嶈兘涓虹┖")
     private Long userId;
 
-    @ApiModelProperty("鍏宠仈瀹夊叏鍩硅鑰冩牳id")
+    @Schema(description = "鍏宠仈瀹夊叏鍩硅鑰冩牳id")
     private Integer safeTrainingId;
 
-    @ApiModelProperty("鑰冩牳缁撴灉")
+    @Schema(description = "鑰冩牳缁撴灉")
     private String examinationResults;
 
     @TableField(fill = FieldFill.INSERT)
@@ -67,29 +62,32 @@
     private Integer tenantId;
 
 
-    @ApiModelProperty("鍩硅鏃ユ湡")
+    @Schema(description = "鍩硅鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @TableField(exist = false)
     private LocalDate trainingDate;
 
-    @ApiModelProperty("璇剧▼缂栧彿")
+    @Schema(description = "璇剧▼缂栧彿")
     @TableField(exist = false)
     private String courseCode;
 
-    @ApiModelProperty("鍩硅鍐呭")
+    @Schema(description = "鍩硅鍐呭")
     @TableField(exist = false)
     private String trainingContent;
 
-    @ApiModelProperty("鍩硅璇炬椂")
+    @Schema(description = "鍩硅璇炬椂")
     @TableField(exist = false)
     private Double classHour;
 
-    @ApiModelProperty("璇鹃瀛﹀垎")
+    @Schema(description = "璇鹃瀛﹀垎")
     @TableField(exist = false)
     private String projectCredits;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     @TableField(exist = false)
     private String remarks;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java
index 9ed72a7..482d197 100644
--- a/src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,7 +22,7 @@
 @Getter
 @Setter
 @TableName("safe_training_file")
-@ApiModel(value = "SafeTrainingFile瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢")
+@Schema(name = "SafeTrainingFile瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢")
 public class SafeTrainingFile implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -31,7 +30,7 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("鍏宠仈瀹夊叏鍩硅鑰冩牳id")
+    @Schema(description = "鍏宠仈瀹夊叏鍩硅鑰冩牳id")
     private Integer safeTrainingId;
 
     private String name;
@@ -54,4 +53,7 @@
 
     @TableField(fill = FieldFill.INSERT)
     private Integer tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java b/src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java
index 8a06f05..4f20efc 100644
--- a/src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java
+++ b/src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.safe.pojo.SafeTrainingDetails;
 import com.baomidou.mybatisplus.extension.service.IService;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * <p>
diff --git a/src/main/java/com/ruoyi/safe/service/SafeTrainingService.java b/src/main/java/com/ruoyi/safe/service/SafeTrainingService.java
index 56f2e6e..ab9f3cc 100644
--- a/src/main/java/com/ruoyi/safe/service/SafeTrainingService.java
+++ b/src/main/java/com/ruoyi/safe/service/SafeTrainingService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.safe.pojo.SafeTraining;
 import com.baomidou.mybatisplus.extension.service.IService;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java
index 131ba24..94b38e9 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java
@@ -2,11 +2,11 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.safe.pojo.SafeAccident;
-import com.ruoyi.safe.mapper.SafeAccidentMapper;
-import com.ruoyi.safe.service.SafeAccidentService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.safe.mapper.SafeAccidentMapper;
+import com.ruoyi.safe.pojo.SafeAccident;
+import com.ruoyi.safe.service.SafeAccidentService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 /**
@@ -18,10 +18,10 @@
  * @since 2026-01-28 02:40:31
  */
 @Service
+@RequiredArgsConstructor
 public class SafeAccidentServiceImpl extends ServiceImpl<SafeAccidentMapper, SafeAccident> implements SafeAccidentService {
 
-    @Autowired
-    private SafeAccidentMapper safeAccidentMapper;
+    private final SafeAccidentMapper safeAccidentMapper;
 
     @Override
     public IPage<SafeAccident> pageSafeAccident(Page page, SafeAccident safeAccident) {
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeCertificationServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeCertificationServiceImpl.java
index 51162bc..575ed96 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeCertificationServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeCertificationServiceImpl.java
@@ -2,11 +2,11 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.safe.pojo.SafeCertification;
-import com.ruoyi.safe.mapper.SafeCertificationMapper;
-import com.ruoyi.safe.service.SafeCertificationService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.safe.mapper.SafeCertificationMapper;
+import com.ruoyi.safe.pojo.SafeCertification;
+import com.ruoyi.safe.service.SafeCertificationService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 /**
@@ -18,10 +18,10 @@
  * @since 2026-01-28 09:26:33
  */
 @Service
+@RequiredArgsConstructor
 public class SafeCertificationServiceImpl extends ServiceImpl<SafeCertificationMapper, SafeCertification> implements SafeCertificationService {
 
-    @Autowired
-    private SafeCertificationMapper safeCertificationMapper;
+    private final SafeCertificationMapper safeCertificationMapper;
 
 
     @Override
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java
index b3ebd98..7072c69 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java
@@ -2,11 +2,11 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.safe.pojo.SafeContingencyPlan;
-import com.ruoyi.safe.mapper.SafeContingencyPlanMapper;
-import com.ruoyi.safe.service.SafeContingencyPlanService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.safe.mapper.SafeContingencyPlanMapper;
+import com.ruoyi.safe.pojo.SafeContingencyPlan;
+import com.ruoyi.safe.service.SafeContingencyPlanService;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 /**
@@ -18,10 +18,10 @@
  * @since 2026-01-28 02:07:29
  */
 @Service
+@RequiredArgsConstructor
 public class SafeContingencyPlanServiceImpl extends ServiceImpl<SafeContingencyPlanMapper, SafeContingencyPlan> implements SafeContingencyPlanService {
 
-    @Autowired
-    private SafeContingencyPlanMapper safeContingencyPlanMapper;
+    private final SafeContingencyPlanMapper safeContingencyPlanMapper;
 
     @Override
     public IPage<SafeContingencyPlan> pageSafeContingencyPlan(Page page, SafeContingencyPlan safeContingencyPlan) {
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java
index 2d6fa1d..fc46ab6 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java
@@ -3,15 +3,15 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.safe.dto.SafeHazardRecordDto;
 import com.ruoyi.safe.mapper.SafeHazardMapper;
+import com.ruoyi.safe.mapper.SafeHazardRecordMapper;
 import com.ruoyi.safe.pojo.SafeHazard;
 import com.ruoyi.safe.pojo.SafeHazardRecord;
-import com.ruoyi.safe.mapper.SafeHazardRecordMapper;
 import com.ruoyi.safe.service.SafeHazardRecordService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -29,12 +29,11 @@
  */
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class SafeHazardRecordServiceImpl extends ServiceImpl<SafeHazardRecordMapper, SafeHazardRecord> implements SafeHazardRecordService {
 
-    @Autowired
-    private SafeHazardRecordMapper safeHazardRecordMapper;
-    @Autowired
-    private SafeHazardMapper safeHazardMapper;
+    private final SafeHazardRecordMapper safeHazardRecordMapper;
+    private final SafeHazardMapper safeHazardMapper;
 
     @Override
     public IPage<SafeHazardRecordDto> pageSafeHazardRecord(Page page, SafeHazardRecordDto safeHazardRecordDto) {
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeHazardServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeHazardServiceImpl.java
index 18939e6..a2cbc96 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeHazardServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeHazardServiceImpl.java
@@ -3,13 +3,13 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.safe.mapper.SafeHazardMapper;
 import com.ruoyi.safe.mapper.SafeHazardRecordMapper;
 import com.ruoyi.safe.pojo.SafeHazard;
-import com.ruoyi.safe.mapper.SafeHazardMapper;
 import com.ruoyi.safe.pojo.SafeHazardRecord;
 import com.ruoyi.safe.service.SafeHazardService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -23,13 +23,12 @@
  * @since 2026-01-28 10:09:24
  */
 @Service
+@RequiredArgsConstructor
 public class SafeHazardServiceImpl extends ServiceImpl<SafeHazardMapper, SafeHazard> implements SafeHazardService {
 
-    @Autowired
-    private SafeHazardMapper safeHazardMapper;
+    private final SafeHazardMapper safeHazardMapper;
 
-    @Autowired
-    private SafeHazardRecordMapper safeHazardRecordMapper;
+    private final SafeHazardRecordMapper safeHazardRecordMapper;
 
     @Override
     public IPage<SafeHazard> pageSafeHazard(Page page, SafeHazard safeHazard) {
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java
index 460c1d3..7aead53 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java
@@ -3,17 +3,15 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.project.system.domain.SysNotice;
-import com.ruoyi.project.system.mapper.SysNoticeMapper;
 import com.ruoyi.project.system.service.ISysDictDataService;
 import com.ruoyi.project.system.service.ISysNoticeService;
-import com.ruoyi.project.system.service.impl.SysNoticeServiceImpl;
 import com.ruoyi.safe.dto.SafeHiddenDto;
-import com.ruoyi.safe.pojo.SafeHidden;
 import com.ruoyi.safe.mapper.SafeHiddenMapper;
+import com.ruoyi.safe.pojo.SafeHidden;
 import com.ruoyi.safe.service.SafeHiddenService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -32,15 +30,13 @@
  */
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class SafeHiddenServiceImpl extends ServiceImpl<SafeHiddenMapper, SafeHidden> implements SafeHiddenService {
 
-    @Autowired
-    private SafeHiddenMapper safeHiddenMapper;
-    @Autowired
-    private ISysNoticeService sysNoticeService;
+    private final SafeHiddenMapper safeHiddenMapper;
+    private final ISysNoticeService sysNoticeService;
 
-    @Autowired
-    private ISysDictDataService sysDictDataService;
+    private final ISysDictDataService sysDictDataService;
 
 
     @Override
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java
index 2804aa3..db2af40 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java
@@ -2,21 +2,19 @@
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.deepoove.poi.XWPFTemplate;
 import com.deepoove.poi.config.Configure;
 import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
-import com.ruoyi.safe.dto.SafeTrainingDetailsDto;
-import com.ruoyi.safe.dto.SafeTrainingDto;
-import com.ruoyi.safe.pojo.SafeTrainingDetails;
 import com.ruoyi.safe.mapper.SafeTrainingDetailsMapper;
+import com.ruoyi.safe.pojo.SafeTrainingDetails;
 import com.ruoyi.safe.service.SafeTrainingDetailsService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URLEncoder;
@@ -32,13 +30,12 @@
  * @since 2026-01-29 10:54:15
  */
 @Service
+@RequiredArgsConstructor
 public class SafeTrainingDetailsServiceImpl extends ServiceImpl<SafeTrainingDetailsMapper, SafeTrainingDetails> implements SafeTrainingDetailsService {
 
-    @Autowired
-    private SafeTrainingDetailsMapper safeTrainingDetailsMapper;
+    private final SafeTrainingDetailsMapper safeTrainingDetailsMapper;
 
-    @Autowired
-    private SysUserMapper sysUserMapper;
+    private final SysUserMapper sysUserMapper;
 
     @Override
     public IPage<SafeTrainingDetails> pageDetails(Page page, SafeTrainingDetails safeTrainingDetails) {
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
index 05f1ae7..ee9c814 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
@@ -5,37 +5,29 @@
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.deepoove.poi.XWPFTemplate;
 import com.deepoove.poi.config.Configure;
 import com.ruoyi.common.utils.HackLoopTableRenderPolicy;
-import com.ruoyi.production.pojo.ProductOrder;
-import com.ruoyi.production.pojo.ProductWorkOrder;
-import com.ruoyi.project.system.domain.SysNotice;
 import com.ruoyi.safe.dto.SafeTrainingDetailsDto;
 import com.ruoyi.safe.dto.SafeTrainingDto;
 import com.ruoyi.safe.mapper.SafeTrainingDetailsMapper;
 import com.ruoyi.safe.mapper.SafeTrainingFileMapper;
-import com.ruoyi.safe.pojo.SafeTraining;
 import com.ruoyi.safe.mapper.SafeTrainingMapper;
+import com.ruoyi.safe.pojo.SafeTraining;
 import com.ruoyi.safe.pojo.SafeTrainingDetails;
 import com.ruoyi.safe.pojo.SafeTrainingFile;
 import com.ruoyi.safe.service.SafeTrainingService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URLEncoder;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 
@@ -48,16 +40,14 @@
  * @since 2026-01-29 10:54:06
  */
 @Service
+@RequiredArgsConstructor
 public class SafeTrainingServiceImpl extends ServiceImpl<SafeTrainingMapper, SafeTraining> implements SafeTrainingService {
 
-    @Autowired
-    private SafeTrainingMapper safeTrainingMapper;
+    private final SafeTrainingMapper safeTrainingMapper;
 
-    @Autowired
-    private SafeTrainingFileMapper safeTrainingFileMapper;
+    private final SafeTrainingFileMapper safeTrainingFileMapper;
 
-    @Autowired
-    private SafeTrainingDetailsMapper safeTrainingDetailsMapper;
+    private final SafeTrainingDetailsMapper safeTrainingDetailsMapper;
 
     @Override
     public IPage<SafeTrainingDto> pageSafeTraining(Page page, SafeTrainingDto safeTrainingDto) {
diff --git a/src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java b/src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java
index b7ce1c1..0559ff8 100644
--- a/src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java
@@ -7,30 +7,22 @@
 import com.ruoyi.sales.dto.InvoiceLedgerDto;
 import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
 import com.ruoyi.sales.mapper.InvoiceLedgerFileMapper;
-import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper;
-import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
 import com.ruoyi.sales.service.InvoiceLedgerService;
 import io.jsonwebtoken.lang.Collections;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
-import java.time.LocalDateTime;
 import java.util.List;
 
 @RestController
 @RequestMapping("/invoiceLedger")
+@AllArgsConstructor
 public class InvoiceLedgerController {
 
-    @Autowired
     private InvoiceLedgerService invoiceLedgerService;
-
-    @Autowired
-    private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-
-    @Autowired
     private InvoiceLedgerFileMapper invoiceLedgerFileMapper;
 
     /**
diff --git a/src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java b/src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java
index 5606148..8ea6c11 100644
--- a/src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java
+++ b/src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java
@@ -8,18 +8,18 @@
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.service.InvoiceRegistrationService;
 import io.jsonwebtoken.lang.Collections;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/invoiceRegistration")
+@AllArgsConstructor
 public class InvoiceRegistrationController {
 
-    @Autowired
     private InvoiceRegistrationService invoiceRegistrationService;
 
     /**
diff --git a/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java b/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java
index 3c610a1..8ad4f02 100644
--- a/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java
+++ b/src/main/java/com/ruoyi/sales/controller/MetricStatisticsController.java
@@ -4,9 +4,9 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.sales.dto.StatisticsTableDto;
 import com.ruoyi.sales.service.impl.MetricStatisticsServiceImpl;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -15,21 +15,21 @@
  * @author :yys
  * @date : 2026/1/15 9:39
  */
-@Api(tags = "鎸囨爣缁熻")
+@Tag(name = "鎸囨爣缁熻")
 @RestController
 @RequestMapping("/metricStatistics")
+@AllArgsConstructor
 public class MetricStatisticsController extends BaseController {
 
-    @Autowired
     private MetricStatisticsServiceImpl metricStatisticsService;
 
-    @ApiOperation("澶撮儴鎬昏")
+    @Operation(summary = "澶撮儴鎬昏")
     @GetMapping("/total")
     public AjaxResult total() {
         return metricStatisticsService.total();
     }
 
-    @ApiOperation("缁熻琛�")
+    @Operation(summary = "缁熻琛�")
     @GetMapping("/statisticsTable")
     public AjaxResult statisticsTable(StatisticsTableDto statisticsTableDto) {
         return metricStatisticsService.statisticsTable(statisticsTableDto);
diff --git a/src/main/java/com/ruoyi/sales/controller/PaymentShippingController.java b/src/main/java/com/ruoyi/sales/controller/PaymentShippingController.java
index c67d438..f88a0e6 100644
--- a/src/main/java/com/ruoyi/sales/controller/PaymentShippingController.java
+++ b/src/main/java/com/ruoyi/sales/controller/PaymentShippingController.java
@@ -9,9 +9,9 @@
 import com.ruoyi.sales.mapper.PaymentShippingMapper;
 import com.ruoyi.sales.pojo.PaymentShipping;
 import com.ruoyi.sales.service.PaymentShippingService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -23,34 +23,32 @@
  */
 @RestController
 @RequestMapping("/paymentShipping")
-@Api(tags = "鏀粯涓庡彂璐х鐞�")
+@Tag(name = "鏀粯涓庡彂璐х鐞�")
+@AllArgsConstructor
 public class PaymentShippingController extends BaseController {
 
-    @Autowired
     private PaymentShippingService paymentShippingService;
-
-    @Autowired
     private PaymentShippingMapper paymentShippingMapper;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ鏀粯涓庡彂璐т俊鎭�")
+    @Operation(summary = "鍒嗛〉鏌ヨ鏀粯涓庡彂璐т俊鎭�")
     public AjaxResult listPage(Page page, PaymentShipping paymentShipping) {
         IPage<PaymentShipping> listPage = paymentShippingService.listPage(page, paymentShipping);
         return AjaxResult.success(listPage);
     }
 
     @PostMapping("/add")
-    @ApiOperation("娣诲姞鏀粯涓庡彂璐т俊鎭�")
+    @Operation(summary = "娣诲姞鏀粯涓庡彂璐т俊鎭�")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody PaymentShipping paymentShipping) {
-        String ord = OrderUtils.countTodayByCreateTime(paymentShippingMapper, "ORD");
+        String ord = OrderUtils.countTodayByCreateTime(paymentShippingMapper, "ORD","order_no");
         paymentShipping.setOrderNo(ord);
         boolean save = paymentShippingService.save(paymentShipping);
         return save ? success() : error();
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼鏀粯涓庡彂璐т俊鎭�")
+    @Operation(summary = "淇敼鏀粯涓庡彂璐т俊鎭�")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody PaymentShipping paymentShipping) {
         boolean update = paymentShippingService.updateById(paymentShipping);
@@ -58,7 +56,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎鏀粯涓庡彂璐т俊鎭�")
+    @Operation(summary = "鍒犻櫎鏀粯涓庡彂璐т俊鎭�")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids){
         if (CollectionUtils.isEmpty(ids)){
diff --git a/src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java b/src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java
index aa10b54..5512a8d 100644
--- a/src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java
@@ -9,20 +9,17 @@
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.purchase.dto.InvoicePurchaseDto;
 import com.ruoyi.sales.dto.InvoiceLedgerDto;
 import com.ruoyi.sales.dto.ReceiptPaymentDto;
 import com.ruoyi.sales.dto.ReceiptPaymentRecordDto;
-import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.pojo.ReceiptPayment;
-import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.service.ReceiptPaymentService;
-import io.swagger.annotations.ApiModelProperty;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -31,9 +28,9 @@
 
 @RestController
 @RequestMapping("/receiptPayment")
+@AllArgsConstructor
 public class ReceiptPaymentController extends BaseController {
 
-    @Autowired
     private ReceiptPaymentService receiptPaymentService;
 
     /**
@@ -113,7 +110,7 @@
         return AjaxResult.success(receiptPaymentService.bindInvoiceNoRegPage(page,receiptPaymentDto));
     }
 
-    @ApiModelProperty("瀵煎嚭鍥炴鐧昏")
+    @Schema(description = "瀵煎嚭鍥炴鐧昏")
     @PostMapping("/export")
     public void export(HttpServletResponse response, String ids) {
         if (ids == null || ids.isEmpty()) {
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
index cbef46f..ceb3702 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -4,6 +4,8 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -19,17 +21,18 @@
 import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.service.ICommonFileService;
 import com.ruoyi.sales.service.ISalesLedgerService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import com.ruoyi.sales.vo.SalesLedgerVo;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.annotations.ApiParam;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.basic.utils.FileUtil;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -48,33 +51,29 @@
 @RestController
 @RequestMapping("/sales/ledger")
 @AllArgsConstructor
-@Api(tags = "閿�鍞彴璐�")
+@Tag(name = "閿�鍞彴璐�")
 @Slf4j
 public class SalesLedgerController extends BaseController {
 
     private ISalesLedgerService salesLedgerService;
-
     private ICommonFileService commonFileService;
-
-    @Autowired
     private InvoiceLedgerMapper invoiceLedgerMapper;
-
-    @Autowired
     private ReceiptPaymentMapper receiptPaymentMapper;
+    private final FileUtil fileUtil;
 
     /**
      * 瀵煎叆閿�鍞彴璐�
      */
     @Log(title = "瀵煎叆閿�鍞彴璐�", businessType = BusinessType.INSERT)
     @PostMapping("/import")
-    @ApiOperation("瀵煎叆閿�鍞彴璐�")
+    @Operation(summary = "瀵煎叆閿�鍞彴璐�")
     public AjaxResult importData(@RequestParam("file")
                                  @ApiParam(value = "Excel鏂囦欢", required = true)
                                  MultipartFile file) {
         return salesLedgerService.importData(file);
     }
 
-    @ApiOperation("瀵煎嚭閿�鍞彴璐︽ā鏉�")
+    @Operation(summary = "瀵煎嚭閿�鍞彴璐︽ā鏉�")
     @PostMapping("/exportTemplate")
     public void exportTemplate(HttpServletResponse response) {
         // 1. 妯℃澘鏂囦欢鍦╮esources/static涓嬬殑璺緞
@@ -155,13 +154,13 @@
     @PostMapping("/export")
     public void export(HttpServletResponse response, SalesLedgerDto salesLedgerDto) {
         Page page = new Page(-1,-1);
-        IPage<SalesLedger> salesLedgerIPage = listPage(page, salesLedgerDto);
-        ExcelUtil<SalesLedger> util = new ExcelUtil<SalesLedger>(SalesLedger.class);
+        IPage<SalesLedgerVo> salesLedgerIPage = listPage(page, salesLedgerDto);
+        ExcelUtil<SalesLedgerVo> util = new ExcelUtil<SalesLedgerVo>(SalesLedgerVo.class);
         if(salesLedgerIPage == null){
             util.exportExcel(response, new ArrayList<>(), "閿�鍞彴璐︽暟鎹�");
             return;
         }
-        List<SalesLedger> list = salesLedgerIPage.getRecords();
+        List<SalesLedgerVo> list = salesLedgerIPage.getRecords();
         util.exportExcel(response, list, "閿�鍞彴璐︽暟鎹�");
     }
 
@@ -174,8 +173,8 @@
         Page page = new Page();
         page.setCurrent(-1);
         page.setSize(-1);
-        IPage<SalesLedger> salesLedgerIPage = listPage(page, salesLedgerDto);
-        ExcelUtil<SalesLedger> util = new ExcelUtil<SalesLedger>(SalesLedger.class);
+        IPage<SalesLedgerVo> salesLedgerIPage = listPage(page, salesLedgerDto);
+        ExcelUtil<SalesLedgerVo> util = new ExcelUtil<SalesLedgerVo>(SalesLedgerVo.class);
         util.exportExcel(response, salesLedgerIPage == null ? new ArrayList<>() : salesLedgerIPage.getRecords(), "瀵煎嚭寮�绁ㄧ櫥璁板垪琛�");
     }
 
@@ -257,8 +256,8 @@
      * 鏌ヨ閿�鍞彴璐﹀垪琛�
      */
     @GetMapping("/listPage")
-    public IPage<SalesLedger> listPage(Page page, SalesLedgerDto salesLedgerDto) {
-        IPage<SalesLedger> iPage = salesLedgerService.selectSalesLedgerListPage(page, salesLedgerDto);
+    public IPage<SalesLedgerVo> listPage(Page page, SalesLedgerDto salesLedgerDto) {
+        IPage<SalesLedgerVo> iPage = salesLedgerService.selectSalesLedgerListPage(page, salesLedgerDto);
 
         //  鏌ヨ缁撴灉涓虹┖,鐩存帴杩斿洖
         if (CollectionUtils.isEmpty(iPage.getRecords())) {
@@ -301,10 +300,10 @@
             }
         }
 
-        for (SalesLedger salesLedger : iPage.getRecords()) {
-            Long ledgerId = salesLedger.getId();
+        for (SalesLedgerVo salesLedgerVo : iPage.getRecords()) {
+            Long ledgerId = salesLedgerVo.getId();
             // 鍚堝悓鎬婚噾棰�
-            BigDecimal contractAmount = salesLedger.getContractAmount() == null ? BigDecimal.ZERO : salesLedger.getContractAmount();
+            BigDecimal contractAmount = salesLedgerVo.getContractAmount() == null ? BigDecimal.ZERO : salesLedgerVo.getContractAmount();
             // 寮�绁ㄦ�婚鍜屽洖娆炬�婚
             BigDecimal invoiceTotal = invoiceTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
             BigDecimal receiptPaymentAmountTotal = receiptTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
@@ -321,15 +320,17 @@
                 noReceiptPaymentAmountTotal = BigDecimal.ZERO;
             }
 
-            salesLedger.setNoInvoiceAmountTotal(noInvoiceAmountTotal);
-            salesLedger.setInvoiceTotal(invoiceTotal);
-            salesLedger.setReceiptPaymentAmountTotal(receiptPaymentAmountTotal);
-            salesLedger.setNoReceiptAmount(noReceiptPaymentAmountTotal);
+            salesLedgerVo.setNoInvoiceAmountTotal(noInvoiceAmountTotal);
+            salesLedgerVo.setInvoiceTotal(invoiceTotal);
+            salesLedgerVo.setReceiptPaymentAmountTotal(receiptPaymentAmountTotal);
+            salesLedgerVo.setNoReceiptAmount(noReceiptPaymentAmountTotal);
 
             //  濡傛灉宸茬粡鏈夎繃寮�绁ㄦ垨鍥炴鎿嶄綔,鍒欎笉鍏佽缂栬緫
             boolean hasInvoiceOperation = invoiceTotal.compareTo(BigDecimal.ZERO) > 0;
             boolean hasReceiptOperation = receiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) > 0;
-            salesLedger.setIsEdit(!(hasInvoiceOperation || hasReceiptOperation));
+            salesLedgerVo.setIsEdit(!(hasInvoiceOperation || hasReceiptOperation));
+
+            salesLedgerVo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.SALES_LEDGER, ledgerId));
         }
 
         if (ObjectUtils.isNotEmpty(salesLedgerDto.getStatus())) {
@@ -344,7 +345,7 @@
         return iPage;
     }
 
-    @ApiOperation("鏌ヨ閿�鍞彴璐︽秷鑰楃墿鏂欎俊鎭�")
+    @Operation(summary = "鏌ヨ閿�鍞彴璐︽秷鑰楃墿鏂欎俊鎭�")
     @GetMapping("/getSalesLedgerWithProductsLoss")
     public R getSalesLedgerWithProductsLoss(Long salesLedgerId) {
         return R.ok(salesLedgerService.getSalesLedgerWithProductsLoss(salesLedgerId));
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
index aed72ef..411291c 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
@@ -1,34 +1,29 @@
 package com.ruoyi.sales.controller;
 
-import javax.servlet.http.HttpServletResponse;
-
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
-import com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy;
-import com.ruoyi.procurementrecord.service.ProcurementRecordService;
-import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.sales.dto.SalesLedgerProductDto;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import com.ruoyi.sales.service.ISalesLedgerProductService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.framework.web.page.TableDataInfo;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.procurementrecord.service.ProcurementRecordService;
+import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
+import com.ruoyi.sales.dto.SalesLedgerProductDto;
+import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.service.ISalesLedgerProductService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 浜у搧淇℃伅Controller
@@ -37,15 +32,14 @@
  * @date 2025-05-08
  */
 @RestController
+@RequiredArgsConstructor
 @RequestMapping("/sales/product")
 public class SalesLedgerProductController extends BaseController
 {
-    @Autowired
-    private ISalesLedgerProductService salesLedgerProductService;
-    @Autowired
-    private ProcurementRecordService procurementRecordService;
-    @Autowired
-    private StockUtils stockUtils;
+    private final ISalesLedgerProductService salesLedgerProductService;
+    private final ProcurementRecordService procurementRecordService;
+    private final StockUtils stockUtils;
+    private final PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
 
 
     /**
@@ -74,6 +68,14 @@
     @GetMapping("/list")
     public AjaxResult list(SalesLedgerProduct salesLedgerProduct) {
         List<SalesLedgerProduct> list = salesLedgerProductService.selectSalesLedgerProductList(salesLedgerProduct);
+        if (CollUtil.isEmpty(list)) {
+            return AjaxResult.success(list);
+        }
+        //
+        List<Long> productIds = list.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
+        List<SimpleReturnOrderGroupDto> groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
+        Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, item -> item.getSumReturnQuantity()));
+
         list.forEach(item -> {
             if (item.getFutureTickets().compareTo(BigDecimal.ZERO) == 0) {
                 item.setFutureTickets(BigDecimal.ZERO);
@@ -95,6 +97,10 @@
                     item.setApproveStatus(1);
                 }
             }
+            // 缁熻閫�璐ф暟閲�
+            BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO);
+            item.setReturnQuality(returnQuality);
+            item.setAvailableQuality(item.getQuantity().subtract(returnQuality));
         });
         return AjaxResult.success(list);
     }
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesQuotationController.java b/src/main/java/com/ruoyi/sales/controller/SalesQuotationController.java
index f2e7928..f9251f8 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesQuotationController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesQuotationController.java
@@ -1,21 +1,20 @@
 package com.ruoyi.sales.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.sales.dto.SalesQuotationDto;
 import com.ruoyi.sales.service.SalesQuotationService;
-import org.springframework.beans.factory.annotation.Autowired;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletResponse;
 
 @RestController
 @RequestMapping("/sales/quotation")
+@AllArgsConstructor
 public class SalesQuotationController {
-    @Autowired
-    private SalesQuotationService salesQuotationService;
+    private final SalesQuotationService salesQuotationService;
     @GetMapping("/list")
     public AjaxResult getList(Page page, SalesQuotationDto salesQuotationDto) {
         return AjaxResult.success(salesQuotationService.listPage(page, salesQuotationDto));
diff --git a/src/main/java/com/ruoyi/sales/controller/SalespersonManagementController.java b/src/main/java/com/ruoyi/sales/controller/SalespersonManagementController.java
index 7d40587..5f64f8c 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalespersonManagementController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalespersonManagementController.java
@@ -4,12 +4,11 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
 import com.ruoyi.sales.pojo.SalespersonManagement;
 import com.ruoyi.sales.service.SalespersonManagementService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -21,22 +20,21 @@
  */
 @RestController
 @RequestMapping("/salespersonManagement")
-@Api(tags = "涓氬姟鍛樼鐞�")
+@Tag(name = "涓氬姟鍛樼鐞�")
+@AllArgsConstructor
 public class SalespersonManagementController extends BaseController {
 
-
-    @Autowired
     private SalespersonManagementService salespersonManagementService;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍒嗛〉鏌ヨ涓氬姟鍛樹俊鎭�")
+    @Operation(summary = "鍒嗛〉鏌ヨ涓氬姟鍛樹俊鎭�")
     public AjaxResult listPage(Page page, SalespersonManagement salespersonManagement) {
         IPage<SalespersonManagement> listPage = salespersonManagementService.listPage(page, salespersonManagement);
         return AjaxResult.success(listPage);
     }
 
     @PostMapping("/add")
-    @ApiOperation("娣诲姞涓氬姟鍛樹俊鎭�")
+    @Operation(summary = "娣诲姞涓氬姟鍛樹俊鎭�")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody SalespersonManagement salespersonManagement) {
         boolean save = salespersonManagementService.save(salespersonManagement);
@@ -44,7 +42,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼涓氬姟鍛樹俊鎭�")
+    @Operation(summary = "淇敼涓氬姟鍛樹俊鎭�")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody SalespersonManagement salespersonManagement) {
         boolean update = salespersonManagementService.updateById(salespersonManagement);
@@ -52,7 +50,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎涓氬姟鍛樹俊鎭�")
+    @Operation(summary = "鍒犻櫎涓氬姟鍛樹俊鎭�")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if (ids == null || ids.isEmpty()) {
diff --git a/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java b/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
index 49548e1..8c95270 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
@@ -13,39 +13,35 @@
 import com.ruoyi.sales.pojo.ShipmentApproval;
 import com.ruoyi.sales.service.ISalesLedgerProductService;
 import com.ruoyi.sales.service.ShipmentApprovalService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
 @RequestMapping("/shipmentApproval")
-@Api(tags = "鍙戣揣瀹℃壒绠$悊")
+@Tag(name = "鍙戣揣瀹℃壒绠$悊")
+@AllArgsConstructor
 public class ShipmentApprovalController extends BaseController {
 
-    @Autowired
-    private ShipmentApprovalService shipmentApprovalService;
-    @Autowired
-    private ShipmentApprovalMapper shipmentApprovalMapper;
-
-    @Autowired
-    private ISalesLedgerProductService salesLedgerProductService;
-    @Autowired
-    private StockUtils stockUtils;
+    private final ShipmentApprovalService shipmentApprovalService;
+    private final ShipmentApprovalMapper shipmentApprovalMapper;
+    private final ISalesLedgerProductService salesLedgerProductService;
+    private final StockUtils stockUtils;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍙戣揣瀹℃壒鍒楄〃")
+    @Operation(summary = "鍙戣揣瀹℃壒鍒楄〃")
     public AjaxResult listPage(Page page, ShipmentApproval req) {
         IPage<ShipmentApproval> listPage = shipmentApprovalService.listPage(page,req);
         return AjaxResult.success(listPage);
     }
 
     @PostMapping("/update")
-    @ApiOperation("鍙戣揣瀹℃壒,鏇存柊鍙戣揣瀹℃壒鐘舵��")
+    @Operation(summary = "鍙戣揣瀹℃壒,鏇存柊鍙戣揣瀹℃壒鐘舵��")
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult update(@RequestBody ShipmentApproval req) {
 
@@ -99,9 +95,9 @@
      * 瀵煎嚭鍙戣揣淇℃伅绠$悊
      */
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭鍙戣揣瀹℃壒")
+    @Operation(summary = "瀵煎嚭鍙戣揣瀹℃壒")
     public void export(HttpServletResponse response) {
-        List<ShipmentApproval> list = shipmentApprovalService.list(null);
+        List<ShipmentApproval> list = shipmentApprovalService.list();
         ExcelUtil<ShipmentApproval> util = new ExcelUtil<ShipmentApproval>(ShipmentApproval.class);
         util.exportExcel(response, list, "鍙戣揣瀹℃壒");
     }
diff --git a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
index db3c5b9..458be2d 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -1,12 +1,9 @@
 package com.ruoyi.sales.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.approve.mapper.ApproveProcessMapper;
+import com.ruoyi.approve.bean.vo.ApproveProcessVO;
 import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
-import com.ruoyi.approve.vo.ApproveProcessVO;
-import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -15,27 +12,18 @@
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.other.service.impl.TempFileServiceImpl;
-import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.sales.dto.ShippingInfoDto;
-import com.ruoyi.sales.mapper.ShipmentApprovalMapper;
 import com.ruoyi.sales.mapper.ShippingInfoMapper;
-import com.ruoyi.sales.pojo.SalesLedger;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import com.ruoyi.sales.pojo.ShipmentApproval;
 import com.ruoyi.sales.pojo.ShippingInfo;
-import com.ruoyi.sales.service.ISalesLedgerProductService;
-import com.ruoyi.sales.service.ISalesLedgerService;
 import com.ruoyi.sales.service.ShippingInfoService;
-import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.apache.commons.collections4.CollectionUtils;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.time.LocalDate;
 import java.util.List;
@@ -46,35 +34,29 @@
  */
 @RestController
 @RequestMapping("/shippingInfo")
-@Api(tags = "鍙戣揣淇℃伅绠$悊")
+@Tag(name = "鍙戣揣淇℃伅绠$悊")
+@AllArgsConstructor
 public class ShippingInfoController extends BaseController {
 
-    @Autowired
     private ShippingInfoService shippingInfoService;
-
-    @Autowired
-    private CommonFileServiceImpl commonFileService;
-
-    @Autowired
     private ApproveProcessServiceImpl approveProcessService;
-    @Autowired
-    private StockUtils stockUtils;
+    private ShippingInfoMapper shippingInfoMapper;
 
 
     @GetMapping("/listPage")
-    @ApiOperation("鍙戣揣淇℃伅鍒楄〃")
+    @Operation(summary = "鍙戣揣淇℃伅鍒楄〃")
     public AjaxResult listPage(Page page, ShippingInfo req) {
         IPage<ShippingInfoDto> listPage = shippingInfoService.listPage(page,req);
         return AjaxResult.success(listPage);
     }
 
     @PostMapping("/add")
-    @ApiOperation("娣诲姞鍙戣揣淇℃伅")
+    @Operation(summary = "娣诲姞鍙戣揣淇℃伅")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "鍙戣揣淇℃伅绠$悊", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody ShippingInfoDto req) throws Exception {
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        String sh = OrderUtils.countTodayByCreateTime(shippingInfoMapper, "SH");
+        String sh = OrderUtils.countTodayByCreateTime(shippingInfoMapper, "SH","shipping_no");
         // 鍙戣揣瀹℃壒
         ApproveProcessVO approveProcessVO = new ApproveProcessVO();
         approveProcessVO.setApproveType(7);
@@ -87,11 +69,11 @@
         // 娣诲姞鍙戣揣娑堟伅
         req.setShippingNo(sh);
         req.setStatus("寰呭鏍�");
-        boolean save = shippingInfoService.save(req);
+        boolean save = shippingInfoService.add(req);
         return save ? AjaxResult.success() : AjaxResult.error();
     }
 
-    @ApiOperation("鍙戣揣鎵e簱瀛�")
+    @Operation(summary = "鍙戣揣鎵e簱瀛�")
     @PostMapping("/deductStock")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "鍙戣揣淇℃伅绠$悊", businessType = BusinessType.UPDATE)
@@ -100,7 +82,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼鍙戣揣淇℃伅")
+    @Operation(summary = "淇敼鍙戣揣淇℃伅")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "鍙戣揣淇℃伅绠$悊", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody ShippingInfo req) {
@@ -113,7 +95,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎鍙戣揣淇℃伅")
+    @Operation(summary = "鍒犻櫎鍙戣揣淇℃伅")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "鍙戣揣淇℃伅绠$悊", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
@@ -121,14 +103,11 @@
         return shippingInfoService.delete(ids) ? AjaxResult.success("鍒犻櫎鎴愬姛") : AjaxResult.error("鍒犻櫎澶辫触");
     }
 
-    @Autowired
-    private ShippingInfoMapper shippingInfoMapper;
-
     /**
      * 瀵煎嚭鍙戣揣淇℃伅绠$悊
      */
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭鍙戣揣淇℃伅")
+    @Operation(summary = "瀵煎嚭鍙戣揣淇℃伅")
     public void export(HttpServletResponse response) {
         List<ShippingInfo> list = shippingInfoMapper.listAll();
         ExcelUtil<ShippingInfo> util = new ExcelUtil<ShippingInfo>(ShippingInfo.class);
@@ -137,8 +116,13 @@
 
 
     @GetMapping("/getByCustomerName")
-    @ApiOperation("閫氳繃瀹㈡埛鍚嶇О鏌ヨ")
+    @Operation(summary = "閫氳繃瀹㈡埛鍚嶇О鏌ヨ")
     public AjaxResult getByCustomerName(String customerName) {
         return AjaxResult.success(shippingInfoService.getShippingInfoByCustomerName(customerName));
     }
+
+    @GetMapping("/getDateil/{id}")
+    public R getDateil(@PathVariable("id") Long id) {
+        return R.ok(shippingInfoService.getDetail(id));
+    }
 }
diff --git a/src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java b/src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java
new file mode 100644
index 0000000..c235b3e
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingProductDetailController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.sales.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@RestController
+@RequestMapping("/shippingProductDetail")
+public class ShippingProductDetailController {
+
+}
diff --git a/src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java b/src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java
index c638ebb..8f15d3b 100644
--- a/src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java
@@ -3,7 +3,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.common.vo.FileVo;
 import com.ruoyi.sales.pojo.InvoiceLedger;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -16,41 +16,41 @@
 
     private List<FileVo> fileList;
 
-    @ApiModelProperty(value = "鏌ヨ鏂囨湰")
+    @Schema(description = "鏌ヨ鏂囨湰")
     private String searchText;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
-    @ApiModelProperty(value = "瀹㈡埛ID")
+    @Schema(description = "瀹㈡埛ID")
     private Integer customerId;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
+    @Schema(description = "瀹㈡埛鍚堝悓鍙�")
     private String customerContractNo;
 
-    @ApiModelProperty(value = "涓氬姟鍛�")
+    @Schema(description = "涓氬姟鍛�")
     private String salesman;
 
-    @ApiModelProperty(value = "鍙戠エ鏂囦欢鍚�")
+    @Schema(description = "鍙戠エ鏂囦欢鍚�")
     private String invoiceFileName;
 
-    @ApiModelProperty(value = "鍥炴閲戦")
+    @Schema(description = "鍥炴閲戦")
     private BigDecimal receiptPaymentAmount;
 
-    @ApiModelProperty(value = "鍥炴鏃ユ湡")
+    @Schema(description = "鍥炴鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date receiptPaymentDate;
 
-    @ApiModelProperty(value = "鏈洖娆鹃噾棰�")
+    @Schema(description = "鏈洖娆鹃噾棰�")
     private BigDecimal unReceiptPaymentAmount;
 
-    @ApiModelProperty(value = "绋庣巼")
+    @Schema(description = "绋庣巼")
     private BigDecimal taxRate;
 
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     private String salesContractNo;
 
-    @ApiModelProperty(value = "閿�鍞悎鍚孖D")
+    @Schema(description = "閿�鍞悎鍚孖D")
     private Integer salesLedgerId;
 
     private String paymentMethod;
diff --git a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java b/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java
index 05e8509..af7dedc 100644
--- a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java
@@ -2,7 +2,7 @@
 
 import com.ruoyi.sales.pojo.InvoiceRegistration;
 import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -11,19 +11,19 @@
 @Data
 public class InvoiceRegistrationDto extends InvoiceRegistration {
 
-    @ApiModelProperty(name = "寮�绁ㄧ櫥璁颁骇鍝侀泦鍚�")
+    @Schema(description = "寮�绁ㄧ櫥璁颁骇鍝侀泦鍚�")
     private List<InvoiceRegistrationProductDto> productDtoList;
 
-    @ApiModelProperty(name = "瀹㈡埛鍚堝悓鍙�")
+    @Schema(description = "瀹㈡埛鍚堝悓鍙�")
     private String customerContractNo;
 
-    @ApiModelProperty(name = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
-    @ApiModelProperty(name = "鍚堝悓閲戦")
+    @Schema(description = "鍚堝悓閲戦")
     private BigDecimal contractAmount;
 
-    @ApiModelProperty(name = "鏈紑绁ㄩ噾棰�")
+    @Schema(description = "鏈紑绁ㄩ噾棰�")
     private BigDecimal noInvoiceAmountTotal;
 
 }
diff --git a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java b/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java
index 23fe6b4..4f94afc 100644
--- a/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java
@@ -6,7 +6,7 @@
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.InvoiceLedgerFile;
 import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,28 +18,28 @@
 @Data
 public class InvoiceRegistrationProductDto extends InvoiceRegistrationProduct {
 
-    @ApiModelProperty(name = "瀹㈡埛鍚堝悓鍙�")
+    @Schema(description = "瀹㈡埛鍚堝悓鍙�")
     private String customerContractNo;
 
-    @ApiModelProperty(name = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customerName;
 
-    @ApiModelProperty(name = "閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     private String salesContractNo;
 
-    @ApiModelProperty(name = "闄勪欢")
+    @Schema(description = "闄勪欢")
     private List<FileVo> fileList;
 
-    @ApiModelProperty(value = "鍙戠エ鍙�")
+    @Schema(description = "鍙戠エ鍙�")
     private String invoiceNo;
 
-    @ApiModelProperty(value = "鍙戠エ閲戦")
+    @Schema(description = "鍙戠エ閲戦")
     private BigDecimal invoiceTotal;
 
-    @ApiModelProperty(value = "寮�绁ㄤ汉")
+    @Schema(description = "寮�绁ㄤ汉")
     private String invoicePerson;
 
-    @ApiModelProperty(value = "寮�绁ㄦ椂闂�")
+    @Schema(description = "寮�绁ㄦ椂闂�")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate invoiceDate;
@@ -49,10 +49,10 @@
     @TableField(exist = false)
     private String invoiceDateEnd;
 
-    @ApiModelProperty(value = "寮�绁ㄥ彴璐d")
+    @Schema(description = "寮�绁ㄥ彴璐d")
     private Integer invoiceLedgerId;
 
-    @ApiModelProperty(value = "鍙戠エ鏂囦欢鍚�")
+    @Schema(description = "鍙戠エ鏂囦欢鍚�")
     private String invoiceFileName;
 
     private List<InvoiceLedgerFile> commonFiles;
diff --git a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java
index 1afb02c..fb2004a 100644
--- a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java
@@ -4,7 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.ReceiptPayment;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -15,23 +15,23 @@
 @Data
 public class ReceiptPaymentDto extends ReceiptPayment {
 
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
+    @Schema(description = "瀹㈡埛鍚堝悓鍙�")
     @Excel(name = "瀹㈡埛鍚堝悓鍙�")
     private String customerContractNo;
 
-    @ApiModelProperty(value = "鐘舵��")
+    @Schema(description = "鐘舵��")
     @Excel(name = "鐘舵��")
     private String statusName;
 
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     @Excel(name = "瀹㈡埛鍚嶇О")
     private String customerName;
 
     @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "寮�绁ㄦ棩鏈�",width = 30,dateFormat = "yyyy-MM-dd")
-    @ApiModelProperty(value = "寮�绁ㄦ棩鏈�")
+    @Schema(description = "寮�绁ㄦ棩鏈�")
     private Date invoiceDate;
 
     @TableField(exist = false)
@@ -39,42 +39,42 @@
     @TableField(exist = false)
     private String invoiceDateEnd;
 
-    @ApiModelProperty(value = "鏌ヨ鏂囨湰")
+    @Schema(description = "鏌ヨ鏂囨湰")
     private String searchText;
 
-    @ApiModelProperty(value = "閿�鍞彴璐ales_ledger")
+    @Schema(description = "閿�鍞彴璐ales_ledger")
     @Excel(isExport = false)
     private Long salesLedgerId;
 
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     @Excel(name = "閿�鍞悎鍚屽彿")
     private String salesContractNo;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇ОID")
+    @Schema(description = "瀹㈡埛鍚嶇ОID")
     @Excel(isExport = false)
     private Integer customerId;
 
-    @ApiModelProperty(value = "鍙戠エ鍙�")
+    @Schema(description = "鍙戠エ鍙�")
     @Excel(name = "鍙戠エ鍙�")
     private String invoiceNo;
 
-    @ApiModelProperty(value = "鍙戠エ閲戦")
+    @Schema(description = "鍙戠エ閲戦")
     @Excel(name = "鍙戠エ閲戦")
     private BigDecimal invoiceTotal;
 
-    @ApiModelProperty(value = "绋庣巼锛�%锛�")
+    @Schema(description = "绋庣巼锛�%锛�")
     @Excel(name = "绋庣巼锛�%锛�")
     private BigDecimal taxRate;
 
-    @ApiModelProperty(value = "浜у搧澶х被")
+    @Schema(description = "浜у搧澶х被")
     @Excel(name = "浜у搧澶х被")
     private String productCategory;
 
-    @ApiModelProperty(value = "鍥炴閲戦")
+    @Schema(description = "鍥炴閲戦")
     @Excel(name = "鍥炴閲戦")
     private BigDecimal receiptPaymentAmountTotal;
 
-    @ApiModelProperty(value = "寰呭洖娆鹃噾棰�")
+    @Schema(description = "寰呭洖娆鹃噾棰�")
     @Excel(name = "寰呭洖娆鹃噾棰�")
     private BigDecimal noReceiptAmount;
 
@@ -89,7 +89,7 @@
     @Excel(isExport = false)
     private String receiptPaymentDateEnd;
 
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
+    @Schema(description = "椤圭洰鍚嶇О")
     @Excel(name = "椤圭洰鍚嶇О")
     private String projectName;
 
diff --git a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java
index 2cda02b..4212961 100644
--- a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java
@@ -2,7 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -10,44 +10,44 @@
 @Data
 public class ReceiptPaymentExeclDto {
 
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     @Excel(name = "閿�鍞悎鍚屽彿",sort = 1)
     private String salesContractNo;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
+    @Schema(description = "瀹㈡埛鍚堝悓鍙�")
     @Excel(name = "瀹㈡埛鍚堝悓鍙�",sort = 2)
 
     private String customerContractNo;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     @Excel(name = "瀹㈡埛鍚嶇О",sort = 3)
     private String customerName;
 
-    @ApiModelProperty(value = "浜у搧澶х被")
+    @Schema(description = "浜у搧澶х被")
     @Excel(name = "浜у搧澶х被",sort = 4)
     private String productCategory;
 
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
+    @Schema(description = "椤圭洰鍚嶇О")
     @Excel(name = "椤圭洰鍚嶇О",sort = 5)
     private String projectName;
 
-    @ApiModelProperty(value = "鍙戠エ鍙�")
+    @Schema(description = "鍙戠エ鍙�")
     @Excel(name = "鍙戠エ鍙�",sort = 6)
     private String invoiceNo;
 
-    @ApiModelProperty(value = "鍙戠エ閲戦")
+    @Schema(description = "鍙戠エ閲戦")
     @Excel(name = "鍙戠エ閲戦",sort = 7)
     private BigDecimal invoiceTotal;
 
-    @ApiModelProperty(value = "绋庣巼锛�%锛�")
+    @Schema(description = "绋庣巼锛�%锛�")
     @Excel(name = "绋庣巼锛�%锛�",sort = 8)
     private BigDecimal taxRate;
 
-    @ApiModelProperty(value = "鍥炴閲戦")
+    @Schema(description = "鍥炴閲戦")
     @Excel(name = "鍥炴閲戦",sort = 9)
     private BigDecimal receiptPaymentAmountTotal;
 
-    @ApiModelProperty(value = "寰呭洖娆鹃噾棰�")
+    @Schema(description = "寰呭洖娆鹃噾棰�")
     @Excel(name = "寰呭洖娆鹃噾棰�",sort = 10)
     private BigDecimal noReceiptAmount;
 
diff --git a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java
index 42411e1..c2410e8 100644
--- a/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,41 +19,41 @@
 @Data
 public class ReceiptPaymentRecordDto {
 
-    @ApiModelProperty(value = "瀹㈡埛鍚堝悓鍙�")
+    @Schema(description = "瀹㈡埛鍚堝悓鍙�")
     @Excel(name = "瀹㈡埛鍚堝悓鍙�")
     private String customerContractNo;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     @Excel(name = "瀹㈡埛鍚嶇О")
     private String customerName;
 
     @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鐧昏鏃ユ湡",width = 30,dateFormat = "yyyy-MM-dd")
-    @ApiModelProperty(value = "鐧昏鏃ユ湡")
+    @Schema(description = "鐧昏鏃ユ湡")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     @Excel(name = "閿�鍞悎鍚屽彿")
     private String salesContractNo;
 
-    @ApiModelProperty(value = "鍥炴閲戦")
+    @Schema(description = "鍥炴閲戦")
     @Excel(name = "鍥炴閲戦")
     private BigDecimal receiptPaymentAmount;
 
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
+    @Schema(description = "椤圭洰鍚嶇О")
     @Excel(name = "椤圭洰鍚嶇О")
     private String projectName;
 
-    @ApiModelProperty(value = "鍥炴褰㈠紡 0鐢垫眹1鎵垮厬")
+    @Schema(description = "鍥炴褰㈠紡 0鐢垫眹1鎵垮厬")
     @Excel(name = "鍥炴褰㈠紡",readConverterExp = "0=鐢垫眹,1=鎵垮厬")
     private String receiptPaymentType;
 
-    @ApiModelProperty(value = "鐧昏浜�")
+    @Schema(description = "鐧昏浜�")
     @Excel(name = "鐧昏浜�")
     private String registrant;
 
-    @ApiModelProperty(value = "鏉ユ鏃ユ湡")
+    @Schema(description = "鏉ユ鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鏉ユ鏃ユ湡",width = 30,dateFormat = "yyyy-MM-dd")
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
index 05bd888..c119e94 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
@@ -2,9 +2,11 @@
 
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDate;
@@ -48,14 +50,17 @@
     private List<CommonFile> SalesLedgerFiles;
 
     private Integer type;
-    @ApiModelProperty(value = "绛捐鏃ユ湡")
+    @Schema(description = "绛捐鏃ユ湡")
     private LocalDate executionDate;
 
     private Boolean status;
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     private String paymentMethod;
 
-    @ApiModelProperty(value = "浜よ揣鏃ユ湡")
+    @Schema(description = "浜よ揣鏃ユ湡")
     private LocalDate deliveryDate;
+
+    private List<StorageBlobDTO> storageBlobDTOs;
+    private List<StorageBlobVO> StorageBlobVOs;
 }
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
index a4c585b..2430d10 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerImportDto.java
@@ -5,7 +5,7 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -38,12 +38,12 @@
     @Excel(name = "澶囨敞")
     private String remarks;
 
-    @ApiModelProperty(value = "绛捐鏃ユ湡")
+    @Schema(description = "绛捐鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "绛捐鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private Date executionDate;
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     @Excel(name = "浠樻鏂瑰紡")
     private String paymentMethod;
 
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java
index 666ccf4..9867633 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java
@@ -3,7 +3,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 
@@ -59,10 +59,10 @@
     private Integer approvalStatus;
 
 
-    @ApiModelProperty(value = "鏈��璐ф暟")
+    @Schema(description = "鏈��璐ф暟")
     private BigDecimal unQuantity;
 
-    @ApiModelProperty(value = "閫�璐ф�绘暟")
+    @Schema(description = "閫�璐ф�绘暟")
     private BigDecimal totalReturnNum;
 
 }
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java b/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java
index 2f40bdd..4841ffd 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java
@@ -2,14 +2,14 @@
 
 import com.ruoyi.sales.pojo.SalesQuotation;
 import com.ruoyi.sales.pojo.SalesQuotationProduct;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.List;
 
 @Data
 public class SalesQuotationDto extends SalesQuotation {
-    @ApiModelProperty(value = "鎶ヤ环鍟嗗搧")
+    @Schema(description = "鎶ヤ环鍟嗗搧")
     private List<SalesQuotationProduct> products;
 
     /**
diff --git a/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java b/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
index 260d217..e12149f 100644
--- a/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
@@ -1,10 +1,11 @@
 package com.ruoyi.sales.dto;
 
 import com.baomidou.mybatisplus.annotation.TableField;
-import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.dto.StorageBlobVO;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.ShippingInfo;
-import io.swagger.annotations.ApiModelProperty;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
 import lombok.Data;
 
 import java.util.List;
@@ -33,4 +34,12 @@
 
     private String productName;
 
+    private List<StorageBlobDTO> storageBlobDTOs;
+    private List<StorageBlobVO> storageBlobVOs;
+
+    private List<Long> batchNo;
+    private List<ShippingProductDetail> batchNoDetailList;
+
+
+
 }
diff --git a/src/main/java/com/ruoyi/sales/dto/ShippingProductDetailDto.java b/src/main/java/com/ruoyi/sales/dto/ShippingProductDetailDto.java
new file mode 100644
index 0000000..0ef46f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/dto/ShippingProductDetailDto.java
@@ -0,0 +1,16 @@
+package com.ruoyi.sales.dto;
+
+import com.ruoyi.sales.pojo.ShippingProductDetail;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class ShippingProductDetailDto extends ShippingProductDetail {
+
+    private String specificationModel;
+
+    private String  productName;
+
+    private BigDecimal deliveryQuantity;
+}
diff --git a/src/main/java/com/ruoyi/sales/dto/StatisticsTableDto.java b/src/main/java/com/ruoyi/sales/dto/StatisticsTableDto.java
index e6b8ff5..979b54b 100644
--- a/src/main/java/com/ruoyi/sales/dto/StatisticsTableDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/StatisticsTableDto.java
@@ -2,8 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.util.Date;
@@ -13,18 +12,18 @@
  * @date : 2026/1/15 10:18
  */
 @Data
-@ApiModel
+@Schema
 public class StatisticsTableDto{
 
     private String customerName;
 
     private String productCategory;
 
-    @ApiModelProperty(value = "寮�濮嬫椂闂�")
+    @Schema(description = "寮�濮嬫椂闂�")
     @JsonFormat(pattern = "yyyy-MM")
     private Date entryDateStart;
 
-    @ApiModelProperty(value = "缁撴潫鏃堕棿")
+    @Schema(description = "缁撴潫鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM")
     private Date entryDateEnd;
 
diff --git a/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java b/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java
index aee8370..b5d09a7 100644
--- a/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java
+++ b/src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java
@@ -6,7 +6,7 @@
 import com.ruoyi.common.vo.FileVo;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.sales.pojo.InvoiceLedger;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
diff --git a/src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java b/src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java
index 8f042c6..8979504 100644
--- a/src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java
+++ b/src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java
@@ -2,7 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
index 8dfb5f9..9f49265 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
@@ -5,12 +5,12 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.aftersalesservice.pojo.AfterSalesService;
 import com.ruoyi.home.dto.IncomeExpenseAnalysisDto;
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.dto.SalesTrendDto;
 import com.ruoyi.sales.dto.StatisticsTableDto;
 import com.ruoyi.sales.pojo.SalesLedger;
+import com.ruoyi.sales.vo.SalesLedgerVo;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -53,7 +53,7 @@
      * @param salesLedgerDto
      * @return
      */
-    IPage<SalesLedger> selectSalesLedgerListPage(Page page, @Param("salesLedgerDto") SalesLedgerDto salesLedgerDto);
+    IPage<SalesLedgerVo> selectSalesLedgerListPage(Page page, @Param("salesLedgerDto") SalesLedgerDto salesLedgerDto);
 
     /**
      * 鎸夋湀浠界粺璁¤鍗曟暟銆侀攢鍞锛堟敮鎸佷骇鍝佸ぇ绫汇�佸鎴峰悕绉扮瓫閫夛級
@@ -85,5 +85,5 @@
             "</script>")
     List<SalesTrendDto> statisticsTable(@Param("statisticsTableDto")StatisticsTableDto statisticsTableDto);
 
-    IPage<SalesLedgerDto> listSalesLedger(Page page,@Param("ew") SalesLedgerDto salesLedgerDto);
+    IPage<SalesLedgerDto> listSalesLedgerAndShipped(Page page, @Param("ew") SalesLedgerDto salesLedgerDto);
 }
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
index 686fc2e..f8e22b9 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
@@ -3,7 +3,6 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.config.MyBaseMapper;
-import com.ruoyi.production.dto.ProductStructureDto;
 import com.ruoyi.purchase.dto.ProcurementBusinessSummaryDto;
 import com.ruoyi.sales.dto.LossProductModelDto;
 import com.ruoyi.sales.dto.SalesLedgerProductDto;
diff --git a/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java b/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java
index 25b5128..5c7a5bf 100644
--- a/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java
@@ -3,11 +3,10 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto;
 import com.ruoyi.sales.dto.SalesLedgerProductDto;
 import com.ruoyi.sales.dto.ShippingInfoDto;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -25,4 +24,5 @@
 
     List<ShippingInfo> getShippingInfoByCustomerName(String customerName);
 
+    List<ShippingProductDetail> getDateil(Long id);
 }
diff --git a/src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java b/src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java
new file mode 100644
index 0000000..f564ba1
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/mapper/ShippingProductDetailMapper.java
@@ -0,0 +1,22 @@
+package com.ruoyi.sales.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.sales.dto.ShippingProductDetailDto;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@Mapper
+public interface ShippingProductDetailMapper extends BaseMapper<ShippingProductDetail> {
+
+    List<ShippingProductDetailDto> getDetail(Long id);
+}
diff --git a/src/main/java/com/ruoyi/sales/pojo/CommonFile.java b/src/main/java/com/ruoyi/sales/pojo/CommonFile.java
index 239fd0d..9bfd69c 100644
--- a/src/main/java/com/ruoyi/sales/pojo/CommonFile.java
+++ b/src/main/java/com/ruoyi/sales/pojo/CommonFile.java
@@ -1,5 +1,6 @@
 package com.ruoyi.sales.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import com.baomidou.mybatisplus.annotation.*;
 import lombok.Data;
 
@@ -30,6 +31,9 @@
     /** 鍏宠仈琛� */
     private Integer type;
 
+    /** 鏂囦欢澶у皬 */
+    private Long fileSize;
+
     /** 鍒涘缓鏃堕棿 */
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
@@ -37,4 +41,11 @@
     /** 鏇存柊鏃堕棿 */
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java
index bac55ed..ef85b3a 100644
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java
+++ b/src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java
@@ -5,7 +5,7 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -22,41 +22,44 @@
     @TableId(type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty(value = "invoice_registration_product琛ㄤ富閿�")
+    @Schema(description = "invoice_registration_product琛ㄤ富閿�")
     private Integer invoiceRegistrationProductId;
 
-    @ApiModelProperty(value = "鍙戠エ鍙�")
+    @Schema(description = "鍙戠エ鍙�")
     private String invoiceNo;
 
-    @ApiModelProperty(value = "鍙戠エ閲戦")
+    @Schema(description = "鍙戠エ閲戦")
     private BigDecimal invoiceTotal;
 
-    @ApiModelProperty(value = "寮�绁ㄤ汉")
+    @Schema(description = "寮�绁ㄤ汉")
     private String invoicePerson;
 
-    @ApiModelProperty(value = "寮�绁ㄦ椂闂�")
+    @Schema(description = "寮�绁ㄦ椂闂�")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate invoiceDate;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java
index 344b369..0d4a4f5 100644
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java
+++ b/src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java
@@ -2,7 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -10,38 +10,41 @@
 @Data
 public class InvoiceLedgerFile {
 
-    @ApiModelProperty(value = "鏂囦欢ID")
+    @Schema(description = "鏂囦欢ID")
     private Long id;
 
-    @ApiModelProperty(value = "鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty(value = "鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private int fileSize;
 
-    @ApiModelProperty(value = "寮�绁ㄥ彴璐D")
+    @Schema(description = "寮�绁ㄥ彴璐D")
     private Integer invoiceLedgerId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java
index 080bd56..e7a926b 100644
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java
+++ b/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java
@@ -1,7 +1,7 @@
 package com.ruoyi.sales.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -16,38 +16,41 @@
     @TableId(type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty(value = "閿�鍞彴璐ales_ledger涓婚敭")
+    @Schema(description = "閿�鍞彴璐ales_ledger涓婚敭")
     private Integer salesLedgerId;
 
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     private String salesContractNo;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇ОID")
+    @Schema(description = "瀹㈡埛鍚嶇ОID")
     private Integer customerId;
 
-    @ApiModelProperty(value = "涓氬姟鍛�")
+    @Schema(description = "涓氬姟鍛�")
     private String salesman;
 
-    @ApiModelProperty(value = "椤圭洰鍚嶇О")
+    @Schema(description = "椤圭洰鍚嶇О")
     private String projectName;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java b/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java
index 23a2557..75ef549 100644
--- a/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java
@@ -1,7 +1,7 @@
 package com.ruoyi.sales.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -17,71 +17,74 @@
     @TableId(type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty(value = "鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�")
+    @Schema(description = "鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�")
     private Integer salesLedgerId;
 
-    @ApiModelProperty(value = "sales_ledger_product涓婚敭")
+    @Schema(description = "sales_ledger_product涓婚敭")
     private Integer salesLedgerProductId;
 
-    @ApiModelProperty(value = "寮�绁ㄧ櫥璁拌〃invoice_registration涓婚敭")
+    @Schema(description = "寮�绁ㄧ櫥璁拌〃invoice_registration涓婚敭")
     private Integer invoiceRegistrationId;
 
-    @ApiModelProperty(value = "浜у搧澶х被")
+    @Schema(description = "浜у搧澶х被")
     private String productCategory;
 
-    @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     private String specificationModel;
 
-    @ApiModelProperty(value = "鍗曚綅")
+    @Schema(description = "鍗曚綅")
     private String unit;
 
-    @ApiModelProperty(value = "鏁伴噺")
+    @Schema(description = "鏁伴噺")
     private BigDecimal quantity;
 
-    @ApiModelProperty(value = "绋庣巼")
+    @Schema(description = "绋庣巼")
     private BigDecimal taxRate;
 
-    @ApiModelProperty(value = "鍚◣鍗曚环")
+    @Schema(description = "鍚◣鍗曚环")
     private BigDecimal taxInclusiveUnitPrice;
 
-    @ApiModelProperty(value = "鍚◣鎬讳环")
+    @Schema(description = "鍚◣鎬讳环")
     private BigDecimal taxInclusiveTotalPrice;
 
-    @ApiModelProperty(value = "涓嶅惈绋庢�讳环")
+    @Schema(description = "涓嶅惈绋庢�讳环")
     private BigDecimal taxExclusiveTotalPrice;
 
-    @ApiModelProperty(value = "鍙戠エ绫诲瀷")
+    @Schema(description = "鍙戠エ绫诲瀷")
     private String invoiceType;
 
-    @ApiModelProperty(value = "寮�绁ㄦ暟")
+    @Schema(description = "寮�绁ㄦ暟")
     private BigDecimal invoiceNum;
 
-    @ApiModelProperty(value = "鏈紑绁ㄦ暟")
+    @Schema(description = "鏈紑绁ㄦ暟")
     private BigDecimal noInvoiceNum;
 
-    @ApiModelProperty(value = "寮�绁ㄩ噾棰�")
+    @Schema(description = "寮�绁ㄩ噾棰�")
     private BigDecimal invoiceAmount;
 
-    @ApiModelProperty(value = "鏈紑绁ㄩ噾棰�")
+    @Schema(description = "鏈紑绁ㄩ噾棰�")
     private BigDecimal noInvoiceAmount;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/Loss.java b/src/main/java/com/ruoyi/sales/pojo/Loss.java
index ad0a03e..37fa5ff 100644
--- a/src/main/java/com/ruoyi/sales/pojo/Loss.java
+++ b/src/main/java/com/ruoyi/sales/pojo/Loss.java
@@ -1,7 +1,7 @@
 package com.ruoyi.sales.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -24,8 +24,15 @@
 
     private BigDecimal rate;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/PaymentShipping.java b/src/main/java/com/ruoyi/sales/pojo/PaymentShipping.java
index 17a691c..51589cd 100644
--- a/src/main/java/com/ruoyi/sales/pojo/PaymentShipping.java
+++ b/src/main/java/com/ruoyi/sales/pojo/PaymentShipping.java
@@ -2,8 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -17,7 +16,7 @@
  */
 @TableName(value = "payment_shipping")
 @Data
-@ApiModel
+@Schema
 public class PaymentShipping {
 
 
@@ -28,56 +27,59 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "璁㈠崟鍙�")
+    @Schema(description = "璁㈠崟鍙�")
     private String orderNo;
 
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     private String customer;
 
-    @ApiModelProperty(value = "璁㈠崟閲戦")
+    @Schema(description = "璁㈠崟閲戦")
     private String orderAmount;
 
-    @ApiModelProperty(value = "宸蹭粯娆鹃噾棰�")
+    @Schema(description = "宸蹭粯娆鹃噾棰�")
     private String paidAmount;
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     private String paymentMethod;
 
-    @ApiModelProperty(value = "浠樻鐘舵��")
+    @Schema(description = "浠樻鐘舵��")
     private String paymentStatus;
 
-    @ApiModelProperty(value = "鍙戣揣鐘舵��")
+    @Schema(description = "鍙戣揣鐘舵��")
     private String shippingStatus;
 
-    @ApiModelProperty(value = "鍙戣揣鏃ユ湡")
+    @Schema(description = "鍙戣揣鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date shippingDate;
 
-    @ApiModelProperty(value = "鐗╂祦鍗曞彿")
+    @Schema(description = "鐗╂祦鍗曞彿")
     private String trackingNo;
 
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/PurchaseLedgerFile.java b/src/main/java/com/ruoyi/sales/pojo/PurchaseLedgerFile.java
index c0f76bb..1bbac84 100644
--- a/src/main/java/com/ruoyi/sales/pojo/PurchaseLedgerFile.java
+++ b/src/main/java/com/ruoyi/sales/pojo/PurchaseLedgerFile.java
@@ -2,7 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -10,35 +10,38 @@
 @Data
 public class PurchaseLedgerFile {
 
-    @ApiModelProperty(value = "鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty(value = "鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private int fileSize;
 
-    @ApiModelProperty(value = "寮�绁ㄥ彴璐D")
+    @Schema(description = "寮�绁ㄥ彴璐D")
     private Integer purchaseLedgerId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java b/src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java
index d53ae6a..132bfa2 100644
--- a/src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java
+++ b/src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java
@@ -5,7 +5,7 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -23,48 +23,51 @@
     @TableId(type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty(value = "鍥炴褰㈠紡 0鐢垫眹1鎵垮厬")
+    @Schema(description = "鍥炴褰㈠紡 0鐢垫眹1鎵垮厬")
     private String receiptPaymentType;
 
-    @ApiModelProperty(value = "鍥炴閲戦")
+    @Schema(description = "鍥炴閲戦")
     private BigDecimal receiptPaymentAmount;
 
-    @ApiModelProperty(value = "鐧昏浜�")
+    @Schema(description = "鐧昏浜�")
     private String registrant;
 
-    @ApiModelProperty(value = "invoice_ledger寮�绁ㄥ彴璐︿富閿甀D")
+    @Schema(description = "invoice_ledger寮�绁ㄥ彴璐︿富閿甀D")
     private Integer invoiceLedgerId;
 
-    @ApiModelProperty(value = "sales_ledger閿�鍞彴璐︿富閿甀D")
+    @Schema(description = "sales_ledger閿�鍞彴璐︿富閿甀D")
     private Long salesLedgerId;
 
-    @ApiModelProperty(value = "sales_ledger_product閿�鍞彴璐︿骇鍝佷富閿甀D")
+    @Schema(description = "sales_ledger_product閿�鍞彴璐︿骇鍝佷富閿甀D")
     private Long salesLedgerProductId;
 
-    @ApiModelProperty(value = "鏉ユ鏃ユ湡")
+    @Schema(description = "鏉ユ鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate receiptPaymentDate;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
index 36751c2..bc4d02c 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -7,7 +7,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -78,7 +78,7 @@
     private String entryPerson;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "褰曞叆浜�")
+    @Schema(description = "褰曞叆浜�")
     @Excel(name = "褰曞叆浜�")
     private String entryPersonName;
 
@@ -104,40 +104,40 @@
     private BigDecimal contractAmount;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鏈紑绁ㄩ噾棰�(鍏�)")
+    @Schema(description = "鏈紑绁ㄩ噾棰�(鍏�)")
     @Excel(name = "鏈紑绁ㄩ噾棰�")
     private BigDecimal noInvoiceAmountTotal = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "绛捐鏃ユ湡")
+    @Schema(description = "绛捐鏃ユ湡")
     private LocalDate executionDate;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "宸插紑绁ㄩ噾棰�(鍏�)")
+    @Schema(description = "宸插紑绁ㄩ噾棰�(鍏�)")
     @Excel(name = "宸插紑绁ㄩ噾棰�")
     private BigDecimal invoiceTotal = BigDecimal.ZERO;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鍥炴閲戦")
+    @Schema(description = "鍥炴閲戦")
     private BigDecimal receiptPaymentAmountTotal = BigDecimal.ZERO;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "寰呭洖娆鹃噾棰�")
+    @Schema(description = "寰呭洖娆鹃噾棰�")
     private BigDecimal noReceiptAmount = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     private String paymentMethod;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鐢熶骇鐘舵��")
+    @Schema(description = "鐢熶骇鐘舵��")
     private String productionStatus = "鏈紑濮�";
 
     //浜よ揣鏃ユ湡
-    @ApiModelProperty(value = "浜よ揣鏃ユ湡")
+    @Schema(description = "浜よ揣鏃ユ湡")
     @TableField(value = "delivery_date")
     private LocalDate deliveryDate;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "浜よ揣澶╂暟宸�")
+    @Schema(description = "浜よ揣澶╂暟宸�")
     private Integer deliveryDaysDiff;
 
     @TableField(exist = false)
@@ -147,5 +147,16 @@
     @TableField(exist = false)
     //鏄惁鍙紪杈�
     private Boolean isEdit;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "鏄惁鏈夌敓浜ц褰�")
+    @TableField(exist = false)
+    private Boolean hasProductionRecord;
+
 }
 
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index 1df16bd..c909871 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -1,12 +1,13 @@
 package com.ruoyi.sales.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -128,24 +129,24 @@
      */
     private BigDecimal futureTicketsAmount=BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "寮�绁ㄦ暟")
+    @Schema(description = "寮�绁ㄦ暟")
     private BigDecimal invoiceNum = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "鏈紑绁ㄦ暟")
+    @Schema(description = "鏈紑绁ㄦ暟")
     private BigDecimal noInvoiceNum = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "寮�绁ㄩ噾棰�")
+    @Schema(description = "寮�绁ㄩ噾棰�")
     private BigDecimal invoiceAmount = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "鏈紑绁ㄩ噾棰�")
+    @Schema(description = "鏈紑绁ㄩ噾棰�")
     private BigDecimal noInvoiceAmount = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "鏈寮�绁ㄦ暟")
+    @Schema(description = "鏈寮�绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal currentInvoiceNum;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鏈寮�绁ㄩ噾棰�")
+    @Schema(description = "鏈寮�绁ㄩ噾棰�")
     private BigDecimal currentInvoiceAmount;
 
     /**
@@ -158,30 +159,30 @@
      */
     private Long productModelId;
 
-    @ApiModelProperty(value = "鍒濆鏈紑绁ㄦ暟")
+    @Schema(description = "鍒濆鏈紑绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal originalNoInvoiceNum;
 
-    @ApiModelProperty(value = "涓存椂鏈紑绁ㄦ暟")
+    @Schema(description = "涓存椂鏈紑绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal tempNoInvoiceNum;
 
-    @ApiModelProperty(value = "涓存椂鏈紑绁ㄩ噾棰�")
+    @Schema(description = "涓存椂鏈紑绁ㄩ噾棰�")
     @TableField(exist = false)
     private BigDecimal tempnoInvoiceAmount;
 
-    @ApiModelProperty(value = "涓存椂鏈潵绁ㄦ暟")
+    @Schema(description = "涓存椂鏈潵绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal tempFutureTickets;
 
-    @ApiModelProperty(value = "涓存椂鏈潵绁ㄩ噾棰�")
+    @Schema(description = "涓存椂鏈潵绁ㄩ噾棰�")
     @TableField(exist = false)
     private BigDecimal tempFutureTicketsAmount;
 
-    @ApiModelProperty("鐧昏浜�")
+    @Schema(description = "鐧昏浜�")
     private String register;
 
-    @ApiModelProperty("鐧昏鏃ユ湡")
+    @Schema(description = "鐧昏鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "鐧昏鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime registerDate;
@@ -192,11 +193,11 @@
     @TableField(exist = false)
     private String shippingCarNumber;
 
-    @ApiModelProperty("蹇�掑叕鍙�")
+    @Schema(description = "蹇�掑叕鍙�")
     @TableField(exist = false)
     private String expressCompany;
 
-    @ApiModelProperty("蹇�掑崟鍙�")
+    @Schema(description = "蹇�掑崟鍙�")
     @TableField(exist = false)
     private String expressNumber;
 
@@ -209,30 +210,52 @@
     private Date shippingDate;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鍙戣揣鐘舵��")
+    @Schema(description = "鍙戣揣鐘舵��")
     private String shippingStatus = "寰呭彂璐�";
     /**
      * 浜у搧鐘舵��
      */
 //    @TableField(exist = false)
-    @ApiModelProperty(value = "浜у搧鐘舵�侊細1-鍏呰冻")
+    @Schema(description = "浜у搧鐘舵�侊細1-鍏呰冻")
     private Integer approveStatus;
 
-    @ApiModelProperty(value = "寰呭洖娆炬�婚噾棰�")
+    @Schema(description = "寰呭洖娆炬�婚噾棰�")
     private BigDecimal pendingInvoiceTotal;
 
-    @ApiModelProperty(value = "鍥炴鎬婚噾棰�")
+    @Schema(description = "鍥炴鎬婚噾棰�")
     private BigDecimal invoiceTotal = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "寰呬粯娆炬�婚噾棰�")
+    @Schema(description = "寰呬粯娆炬�婚噾棰�")
     private BigDecimal pendingTicketsTotal;
 
-    @ApiModelProperty(value = "浠樻鎬婚噾棰�")
+    @Schema(description = "浠樻鎬婚噾棰�")
     private BigDecimal ticketsTotal = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "鏄惁璐ㄦ")
+    @Schema(description = "鏄惁璐ㄦ")
+    //閽堝閲囪喘鍙拌处锛屾槸鍚﹁川妫�
     private Boolean isChecked;
 
     @TableField(exist = false)
     private Integer hasSufficientStock;
+
+    // 閫�璐ф暟閲�
+    @TableField(exist = false)
+    private BigDecimal returnQuality;
+
+    // 鍙敤鏁伴噺  quantity - returnQuality
+    @TableField(exist = false)
+    private BigDecimal availableQuality;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "鏄惁鐢熶骇")
+    //閽堝閿�鍞彴璐︼紝鏄惁鐢熶骇
+    private Boolean isProduction;
+
+    @TableField(exist = false)
+    private BigDecimal noQuantity;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesQuotation.java b/src/main/java/com/ruoyi/sales/pojo/SalesQuotation.java
index f57293d..b72b3af 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesQuotation.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesQuotation.java
@@ -23,6 +23,9 @@
     @Excel(name = "瀹㈡埛鍚嶇О")
     private String customer;
 
+    @ApiModelProperty(value = "瀹㈡埛id")
+    private Long customerId;
+
     @ApiModelProperty(value = "涓氬姟鍛�")
     @Excel(name = "涓氬姟鍛�")
     private String salesperson;
@@ -67,4 +70,7 @@
     @ApiModelProperty(value = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesQuotationProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesQuotationProduct.java
index 709dacf..3e64d15 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesQuotationProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesQuotationProduct.java
@@ -1,7 +1,7 @@
 package com.ruoyi.sales.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -9,41 +9,44 @@
 @Data
 @TableName("sales_quotation_product")
 public class SalesQuotationProduct {
-    @ApiModelProperty(value = "鎶ヤ环鍟嗗搧ID")
+    @Schema(description = "鎶ヤ环鍟嗗搧ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
-    @ApiModelProperty(value = "閿�鍞姤浠峰崟id")
+    @Schema(description = "閿�鍞姤浠峰崟id")
     private Long salesQuotationId;
 
-    @ApiModelProperty(value = "鍟嗗搧鍚嶇О")
+    @Schema(description = "鍟嗗搧鍚嶇О")
     private String product;
-    @ApiModelProperty(value = "鍟嗗搧瑙勬牸")
+    @Schema(description = "鍟嗗搧瑙勬牸")
     private String specification;
-    @ApiModelProperty(value = "鍗曚綅")
+    @Schema(description = "鍗曚綅")
     private String unit;
-    @ApiModelProperty(value = "鍗曚环")
+    @Schema(description = "鍗曚环")
     private Double unitPrice;
-    @ApiModelProperty(value = "鏁伴噺")
+    @Schema(description = "鏁伴噺")
     private Integer quantity;
-    @ApiModelProperty(value = "閲戦")
+    @Schema(description = "閲戦")
     private Double amount;
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalespersonManagement.java b/src/main/java/com/ruoyi/sales/pojo/SalespersonManagement.java
index a0a6636..f826397 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalespersonManagement.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalespersonManagement.java
@@ -2,8 +2,7 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,7 +18,7 @@
  */
 @TableName(value = "salesperson_management")
 @Data
-@ApiModel
+@Schema
 public class SalespersonManagement {
 
     private static final long serialVersionUID = 1L;
@@ -29,51 +28,54 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "濮撳悕")
+    @Schema(description = "濮撳悕")
     private String name;
 
-    @ApiModelProperty(value = "鑱旂郴鐢佃瘽")
+    @Schema(description = "鑱旂郴鐢佃瘽")
     private String phone;
 
-    @ApiModelProperty(value = "閭")
+    @Schema(description = "閭")
     private String email;
 
-    @ApiModelProperty(value = "閮ㄩ棬")
+    @Schema(description = "閮ㄩ棬")
     private String department;
 
-    @ApiModelProperty(value = "鑱屼綅")
+    @Schema(description = "鑱屼綅")
     private String position;
 
-    @ApiModelProperty(value = "鍏ヨ亴鏃ユ湡")
+    @Schema(description = "鍏ヨ亴鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date hireDate;
 
-    @ApiModelProperty(value = "鏉冮檺")
+    @Schema(description = "鏉冮檺")
     private String permissions;
 
-    @ApiModelProperty(value = "鏉冮檺List")
+    @Schema(description = "鏉冮檺List")
     @TableField(exist = false)
     private List<String> permissionsList;
 
-    @ApiModelProperty(value = "鐘舵��")
+    @Schema(description = "鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/ShipmentApproval.java b/src/main/java/com/ruoyi/sales/pojo/ShipmentApproval.java
index 41a0d34..6399728 100644
--- a/src/main/java/com/ruoyi/sales/pojo/ShipmentApproval.java
+++ b/src/main/java/com/ruoyi/sales/pojo/ShipmentApproval.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,49 +18,49 @@
 public class ShipmentApproval {
     @TableId(type = IdType.AUTO)
     private Long id;
-    @ApiModelProperty(value = "鍙戣揣淇℃伅id")
+    @Schema(description = "鍙戣揣淇℃伅id")
     private Long shippingInfoId;
-    @ApiModelProperty(value = "閿�鍞彴璐d")
+    @Schema(description = "閿�鍞彴璐d")
     private Long salesLedgerId;
-    @ApiModelProperty(value = "閿�鍞姤浠蜂骇鍝佽〃id")
+    @Schema(description = "閿�鍞姤浠蜂骇鍝佽〃id")
     private Long salesLedgerProductId;
-     @ApiModelProperty(value = "鐢宠閮ㄩ棬id")
+     @Schema(description = "鐢宠閮ㄩ棬id")
     private Long approveDeptId;
 
-    @ApiModelProperty(value = "鐢宠閮ㄩ棬鍚嶇О")
+    @Schema(description = "鐢宠閮ㄩ棬鍚嶇О")
     @Excel(name = "鐢宠閮ㄩ棬")
     private String approveDeptName;
-     @ApiModelProperty(value = "瀹℃壒鐢ㄦ埛id")
+     @Schema(description = "瀹℃壒鐢ㄦ埛id")
     private Integer approveUserId;
-    @ApiModelProperty(value = "瀹℃壒鐢ㄦ埛鍚嶇О")
+    @Schema(description = "瀹℃壒鐢ㄦ埛鍚嶇О")
     @Excel(name = "瀹℃壒鐢ㄦ埛")
     private String approveUserNames;
 
     /**
      * 瀹℃壒鐘舵��
      */
-    @ApiModelProperty(value = "瀹℃壒鐘舵�侊細0鏈嚭搴�,1宸插嚭搴�,2寰呭鏍�,3瀹℃牳瀹屾垚,4瀹℃牳澶辫触")
+    @Schema(description = "瀹℃壒鐘舵�侊細0鏈嚭搴�,1宸插嚭搴�,2寰呭鏍�,3瀹℃牳瀹屾垚,4瀹℃牳澶辫触")
     @Excel(name = "瀹℃壒鐘舵��", readConverterExp = "0=鏈嚭搴�,1=宸插嚭搴�,2=寰呭鏍�,3=瀹℃牳瀹屾垚,4=瀹℃牳澶辫触")
     private Integer approveStatus;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
@@ -176,28 +176,28 @@
     @TableField(exist = false)
     private BigDecimal futureTicketsAmount;
 
-    @ApiModelProperty(value = "寮�绁ㄦ暟")
+    @Schema(description = "寮�绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal invoiceNum;
 
-    @ApiModelProperty(value = "鏈紑绁ㄦ暟")
+    @Schema(description = "鏈紑绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal noInvoiceNum;
 
-    @ApiModelProperty(value = "寮�绁ㄩ噾棰�")
+    @Schema(description = "寮�绁ㄩ噾棰�")
     @TableField(exist = false)
     private BigDecimal invoiceAmount;
 
-    @ApiModelProperty(value = "鏈紑绁ㄩ噾棰�")
+    @Schema(description = "鏈紑绁ㄩ噾棰�")
     @TableField(exist = false)
     private BigDecimal noInvoiceAmount;
 
-    @ApiModelProperty(value = "鏈寮�绁ㄦ暟")
+    @Schema(description = "鏈寮�绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal currentInvoiceNum;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鏈寮�绁ㄩ噾棰�")
+    @Schema(description = "鏈寮�绁ㄩ噾棰�")
     private BigDecimal currentInvoiceAmount;
 
     /**
@@ -212,31 +212,31 @@
     @TableField(exist = false)
     private Long productModelId;
 
-    @ApiModelProperty(value = "鍒濆鏈紑绁ㄦ暟")
+    @Schema(description = "鍒濆鏈紑绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal originalNoInvoiceNum;
 
-    @ApiModelProperty(value = "涓存椂鏈紑绁ㄦ暟")
+    @Schema(description = "涓存椂鏈紑绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal tempNoInvoiceNum;
 
-    @ApiModelProperty(value = "涓存椂鏈紑绁ㄩ噾棰�")
+    @Schema(description = "涓存椂鏈紑绁ㄩ噾棰�")
     @TableField(exist = false)
     private BigDecimal tempnoInvoiceAmount;
 
-    @ApiModelProperty(value = "涓存椂鏈潵绁ㄦ暟")
+    @Schema(description = "涓存椂鏈潵绁ㄦ暟")
     @TableField(exist = false)
     private BigDecimal tempFutureTickets;
 
-    @ApiModelProperty(value = "涓存椂鏈潵绁ㄩ噾棰�")
+    @Schema(description = "涓存椂鏈潵绁ㄩ噾棰�")
     @TableField(exist = false)
     private BigDecimal tempFutureTicketsAmount;
 
-    @ApiModelProperty("鐧昏浜�")
+    @Schema(description = "鐧昏浜�")
     @TableField(exist = false)
     private String register;
 
-    @ApiModelProperty("鐧昏鏃ユ湡")
+    @Schema(description = "鐧昏鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @Excel(name = "鐧昏鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     @TableField(exist = false)
@@ -295,7 +295,7 @@
     private String entryPerson;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "褰曞叆浜�")
+    @Schema(description = "褰曞叆浜�")
     @Excel(name = "褰曞叆浜�")
     private String entryPersonName;
 
@@ -321,32 +321,35 @@
     private BigDecimal contractAmount;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鏈紑绁ㄩ噾棰�(鍏�)")
+    @Schema(description = "鏈紑绁ㄩ噾棰�(鍏�)")
     @Excel(name = "鏈紑绁ㄩ噾棰�")
     private BigDecimal noInvoiceAmountTotal = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "绛捐鏃ユ湡")
+    @Schema(description = "绛捐鏃ユ湡")
     @TableField(exist = false)
     private LocalDate executionDate;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "宸插紑绁ㄩ噾棰�(鍏�)")
+    @Schema(description = "宸插紑绁ㄩ噾棰�(鍏�)")
     @Excel(name = "宸插紑绁ㄩ噾棰�")
     private BigDecimal invoiceTotal = BigDecimal.ZERO;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鍥炴閲戦")
+    @Schema(description = "鍥炴閲戦")
     private BigDecimal receiptPaymentAmountTotal = BigDecimal.ZERO;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "寰呭洖娆鹃噾棰�")
+    @Schema(description = "寰呭洖娆鹃噾棰�")
     private BigDecimal noReceiptAmount = BigDecimal.ZERO;
 
-    @ApiModelProperty(value = "浠樻鏂瑰紡")
+    @Schema(description = "浠樻鏂瑰紡")
     @TableField(exist = false)
     private String paymentMethod;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "鐢熶骇鐘舵��")
+    @Schema(description = "鐢熶骇鐘舵��")
     private String productionStatus = "鏈紑濮�";
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java b/src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java
index 82a657c..ed9a268 100644
--- a/src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java
+++ b/src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java
@@ -3,7 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,73 +19,76 @@
 public class ShippingInfo {
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "閿�鍞悎鍚屽彿")
+    @Schema(description = "閿�鍞悎鍚屽彿")
     @Excel(name = "閿�鍞悎鍚屽彿")
     private String salesContractNo;
 
     @TableField(exist = false)
-    @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+    @Schema(description = "瀹㈡埛鍚嶇О")
     @Excel(name = "瀹㈡埛鍚嶇О")
     private String customerName;
 
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "閿�鍞彴璐d")
+    @Schema(description = "閿�鍞彴璐d")
     private Long salesLedgerId;
 
-    @ApiModelProperty(value = "閿�鍞姤浠蜂骇鍝佽〃id")
+    @Schema(description = "閿�鍞姤浠蜂骇鍝佽〃id")
     private Long salesLedgerProductId;
 
-    @ApiModelProperty(value = "鐘舵�� 寰呭鏍� 瀹℃牳涓� 锛屽鏍告嫆缁� 瀹℃牳閫氳繃 宸插彂璐�")
+    @Schema(description = "鐘舵�� 寰呭鏍� 瀹℃牳涓� 锛屽鏍告嫆缁� 瀹℃牳閫氳繃 宸插彂璐�")
     @Excel(name = "鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "鍙戣揣鏃ユ湡")
+    @Schema(description = "鍙戣揣鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鍙戣揣鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
     private Date shippingDate;
 
-    @ApiModelProperty(value = "鍙戣揣缂栧彿")
+    @Schema(description = "鍙戣揣缂栧彿")
     @Excel(name = "鍙戣揣缂栧彿")
     private String shippingNo;
 
-    @ApiModelProperty(value = "蹇�掑崟鍙�")
+    @Schema(description = "蹇�掑崟鍙�")
     @Excel(name = "蹇�掑崟鍙�")
     private String expressNumber;
 
-    @ApiModelProperty(value = "蹇�掑叕鍙�")
+    @Schema(description = "蹇�掑叕鍙�")
     @Excel(name = "蹇�掑叕鍙�")
     private String expressCompany;
 
-    @ApiModelProperty(value = "鍙戣揣绫诲瀷")
+    @Schema(description = "鍙戣揣绫诲瀷")
     @Excel(name = "鍙戣揣绫诲瀷")
     private String type;
 
-    @ApiModelProperty(value = "鍙戣揣杞︾墝鍙�")
+    @Schema(description = "鍙戣揣杞︾墝鍙�")
     @Excel(name = "鍙戣揣杞︾墝鍙�")
     private String shippingCarNumber;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java b/src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java
new file mode 100644
index 0000000..08e7311
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/pojo/ShippingProductDetail.java
@@ -0,0 +1,65 @@
+package com.ruoyi.sales.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@Getter
+@Setter
+@ToString
+@TableName("shipping_product_detail")
+@ApiModel(value = "ShippingProductDetail瀵硅薄", description = "鍙戣揣鍙拌处璇︽儏琛�")
+public class ShippingProductDetail implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭id
+     */
+    @ApiModelProperty("涓婚敭id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 搴撳瓨琛╥d
+     */
+    @ApiModelProperty("搴撳瓨琛╥d")
+    private Long stockInventoryId;
+
+    /**
+     * 鎵规鍙�
+     */
+    @ApiModelProperty("鎵规鍙�")
+    private String batchNo;
+
+    /**
+     * 鍙戣揣鐨勬暟閲�
+     */
+    @ApiModelProperty("鍙戣揣鐨勬暟閲�")
+    private BigDecimal quantity;
+
+    /**
+     * 鍙戣揣鍙拌处id
+     */
+    @ApiModelProperty("鍙戣揣鍙拌处id")
+    private Long shippingInfoId;
+
+    @ApiModelProperty("浜у搧鍨嬪彿id")
+    private Long productModelId;
+}
diff --git a/src/main/java/com/ruoyi/sales/service/ICommonFileService.java b/src/main/java/com/ruoyi/sales/service/ICommonFileService.java
index 398fc5d..6cba7dc 100644
--- a/src/main/java/com/ruoyi/sales/service/ICommonFileService.java
+++ b/src/main/java/com/ruoyi/sales/service/ICommonFileService.java
@@ -1,15 +1,9 @@
 package com.ruoyi.sales.service;
 
-import com.ruoyi.sales.pojo.CommonFile;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-
 public interface ICommonFileService {
 
     int deleteSalesLedgerByIds(Long[] ids);
 
-    CommonFile uploadFile(MultipartFile file, Long id, Integer type) throws IOException;
 
     int delCommonFileByIds(Long[] ids);
 }
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index 79aea98..539e67c 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -11,9 +11,11 @@
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.vo.SalesLedgerVo;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.validation.constraints.NotNull;
+import jakarta.annotation.Nullable;
+import jakarta.validation.constraints.NotNull;
 import java.math.BigDecimal;
 import java.util.List;
 
@@ -32,6 +34,7 @@
     int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto);
 
     List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(@NotNull Long relateId,@NotNull SaleEnum type);
+    List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, @NotNull SaleEnum type);
 
     void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type);
 
@@ -45,7 +48,7 @@
 
     List<MonthlyAmountDto> getAmountHalfYear(Integer type);
 
-    IPage<SalesLedger> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto);
+    IPage<SalesLedgerVo> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto);
 
     AjaxResult importData(MultipartFile file);
 
diff --git a/src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java b/src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java
index ae71649..e9335ca 100644
--- a/src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java
@@ -9,7 +9,7 @@
 import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.List;
 
diff --git a/src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java b/src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java
index 19af693..4044a4e 100644
--- a/src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java
+++ b/src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java
@@ -7,7 +7,7 @@
 import com.ruoyi.sales.dto.SalesLedgerDto;
 import org.springframework.web.bind.annotation.RequestBody;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 public interface InvoiceRegistrationService {
diff --git a/src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java b/src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java
index dbe8971..49378c8 100644
--- a/src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java
+++ b/src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java
@@ -7,7 +7,7 @@
 import com.ruoyi.sales.dto.ReceiptPaymentDto;
 import com.ruoyi.sales.pojo.ReceiptPayment;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
diff --git a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
index 2aa1a13..c3e8a0c 100644
--- a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
+++ b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
@@ -3,13 +3,11 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.procurementrecord.dto.ReturnSaleProductDto;
 import com.ruoyi.sales.dto.SalesLedgerProductDto;
 import com.ruoyi.sales.dto.ShippingInfoDto;
+import com.ruoyi.sales.dto.ShippingProductDetailDto;
 import com.ruoyi.sales.pojo.ShippingInfo;
-import org.apache.ibatis.annotations.Param;
 
-import java.io.IOException;
 import java.util.List;
 
 /**
@@ -19,11 +17,15 @@
 public interface ShippingInfoService extends IService<ShippingInfo>{
     IPage<ShippingInfoDto> listPage(Page page, ShippingInfo req);
 
-    boolean deductStock(ShippingInfoDto req) throws IOException;
+    boolean deductStock(ShippingInfoDto req);
 
     boolean delete(List<Long> ids);
 
     List<SalesLedgerProductDto> getReturnManagementDtoById( Long shippingId);
 
     List<ShippingInfo> getShippingInfoByCustomerName(String customerName);
+
+    boolean add(ShippingInfoDto req);
+
+    List<ShippingProductDetailDto> getDetail(Long id);
 }
diff --git a/src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java b/src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java
new file mode 100644
index 0000000..e874dc8
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/service/ShippingProductDetailService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.sales.service;
+
+import com.ruoyi.sales.pojo.ShippingProductDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+public interface ShippingProductDetailService extends IService<ShippingProductDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
index f3aac49..eb36693 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
@@ -1,32 +1,17 @@
 package com.ruoyi.sales.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.other.mapper.TempFileMapper;
-import com.ruoyi.other.pojo.TempFile;
 import com.ruoyi.sales.mapper.CommonFileMapper;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.service.ICommonFileService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.multipart.MultipartFile;
 
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
 import java.util.List;
-import java.util.UUID;
 
 @Service
 @RequiredArgsConstructor
@@ -36,9 +21,6 @@
     private final CommonFileMapper commonFileMapper;
 
     private final TempFileMapper tempFileMapper;
-
-    @Value("${file.upload-dir}")
-    private String uploadDir;
 
     public List<CommonFile> getFileListByBusinessId(Long businessId,Integer type) {
         return commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, businessId)
@@ -66,105 +48,9 @@
         return commonFileMapper.deleteBatchIds(Arrays.asList(ids));
     }
 
-    @Override
-    public CommonFile uploadFile(MultipartFile file, Long id, Integer type) throws IOException {
-        // 1. 鐢熸垚姝e紡鏂囦欢ID鍜岃矾寰�
-        String tempId = UUID.randomUUID().toString();
-        Path tempFilePath = Paths.get(uploadDir, tempId + "_" + file.getOriginalFilename());
-
-        // 2. 纭繚鐩綍瀛樺湪
-        Path parentDir = tempFilePath.getParent();
-        if (parentDir != null) {
-            Files.createDirectories(parentDir); // 閫掑綊鍒涘缓鐩綍
-        }
-
-        // 3. 淇濆瓨鏂囦欢鍒扮洰褰�
-        file.transferTo(tempFilePath.toFile());
-
-        // 4. 淇濆瓨鏂囦欢璁板綍
-        CommonFile commonFile = new CommonFile();
-        commonFile.setCommonId(id);
-        commonFile.setName(file.getOriginalFilename());
-        commonFile.setUrl(tempFilePath.toString());
-        commonFile.setType(type);
-        commonFileMapper.insert(commonFile);
-        return commonFile;
-    }
 
     @Override
     public int delCommonFileByIds(Long[] ids) {
         return commonFileMapper.deleteBatchIds(Arrays.asList(ids));
-    }
-
-    /**
-     * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
-     *
-     * @param businessId  涓氬姟ID锛堥攢鍞彴璐D锛�
-     * @param tempFileIds 涓存椂鏂囦欢ID鍒楄〃
-     * @throws IOException 鏂囦欢鎿嶄綔寮傚父
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException {
-        if (CollectionUtils.isEmpty(tempFileIds)) {
-            return;
-        }
-
-        // 鏋勫缓姝e紡鐩綍璺緞锛堟寜涓氬姟绫诲瀷鍜屾棩鏈熷垎缁勶級
-        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
-
-        Path formalDirPath = Paths.get(formalDir);
-
-        // 纭繚姝e紡鐩綍瀛樺湪锛堥�掑綊鍒涘缓锛�
-        if (!Files.exists(formalDirPath)) {
-            Files.createDirectories(formalDirPath);
-        }
-
-        for (String tempFileId : tempFileIds) {
-            // 鏌ヨ涓存椂鏂囦欢璁板綍
-            TempFile tempFile = tempFileMapper.selectById(tempFileId);
-            if (tempFile == null) {
-                log.warn("涓存椂鏂囦欢涓嶅瓨鍦紝璺宠繃澶勭悊: {}", tempFileId);
-                continue;
-            }
-
-            // 鏋勫缓姝e紡鏂囦欢鍚嶏紙鍖呭惈涓氬姟ID鍜屾椂闂存埑锛岄伩鍏嶅啿绐侊級
-            String originalFilename = tempFile.getOriginalName();
-            String fileExtension = FilenameUtils.getExtension(originalFilename);
-            String formalFilename = businessId + "_" +
-                    System.currentTimeMillis() + "_" +
-                    UUID.randomUUID().toString().substring(0, 8) +
-                    (com.ruoyi.common.utils.StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
-
-            Path formalFilePath = formalDirPath.resolve(formalFilename);
-
-            try {
-                // 鎵ц鏂囦欢杩佺Щ锛堜娇鐢ㄥ師瀛愭搷浣滅‘淇濆畨鍏ㄦ�э級
-//                Files.move(
-//                        Paths.get(tempFile.getTempPath()),
-//                        formalFilePath,
-//                        StandardCopyOption.REPLACE_EXISTING,
-//                        StandardCopyOption.ATOMIC_MOVE
-//                );
-                // 鍘熷瓙绉诲姩澶辫触锛屼娇鐢ㄥ鍒�+鍒犻櫎
-                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
-                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-
-                // 鏇存柊鏂囦欢璁板綍锛堝叧鑱斿埌涓氬姟ID锛�
-                CommonFile fileRecord = new CommonFile();
-                fileRecord.setCommonId(businessId);
-                fileRecord.setName(originalFilename);
-                fileRecord.setUrl(formalFilePath.toString());
-                fileRecord.setCreateTime(LocalDateTime.now());
-                fileRecord.setType(tempFile.getType());
-                commonFileMapper.insert(fileRecord);
-
-                log.info("鏂囦欢杩佺Щ鎴愬姛: {} -> {}", tempFile.getTempPath(), formalFilePath);
-            } catch (IOException e) {
-                log.error("鏂囦欢杩佺Щ澶辫触: {}", tempFile.getTempPath(), e);
-                // 鍙�夋嫨鍥炴粴浜嬪姟鎴栬褰曞け璐ユ枃浠�
-                throw new IOException("鏂囦欢杩佺Щ寮傚父", e);
-            }
-        }
     }
 }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java
index d89119f..d18a51a 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java
@@ -14,48 +14,37 @@
 import com.ruoyi.sales.mapper.*;
 import com.ruoyi.sales.pojo.*;
 import com.ruoyi.sales.service.InvoiceLedgerService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ObjectUtils;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.YearMonth;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
 @Service
+@RequiredArgsConstructor
 public class InvoiceLedgerServiceImpl extends ServiceImpl<InvoiceLedgerMapper, InvoiceLedger> implements InvoiceLedgerService {
 
     @Value("${ruoyi.profile}")
     private String uploadFile;
 
-    @Autowired
-    private InvoiceLedgerMapper invoiceLedgerMapper;
-
-    @Autowired
-    private InvoiceLedgerFileMapper invoiceLedgerFileMapper;
-
-    @Autowired
-    private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-
-    @Autowired
-    private ReceiptPaymentMapper receiptPaymentMapper;
-
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-    @Autowired
-    private CommonFileMapper commonFileMapper;
+    private final InvoiceLedgerMapper invoiceLedgerMapper;
+    private final InvoiceLedgerFileMapper invoiceLedgerFileMapper;
+    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
+    private final ReceiptPaymentMapper receiptPaymentMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
 
     /**
      * 寮�绁ㄥ彴璐︽柊澧�
diff --git a/src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
index b2b5ad3..fefe144 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java
@@ -21,32 +21,29 @@
 import com.ruoyi.sales.pojo.InvoiceRegistrationProduct;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.service.InvoiceRegistrationService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ObjectUtils;
 
-import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.stream.Collectors;
 
 @Service
+@RequiredArgsConstructor
 public class InvoiceRegistrationServiceImpl extends ServiceImpl<InvoiceRegistrationMapper, InvoiceRegistration> implements InvoiceRegistrationService {
 
-    @Autowired
-    private InvoiceRegistrationMapper invoiceRegistrationMapper;
+    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
 
-    @Autowired
-    private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
+    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
 
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
 
-    @Autowired
-    private InvoiceLedgerMapper invoiceLedgerMapper;
+    private final InvoiceLedgerMapper invoiceLedgerMapper;
 
     /**
      * 寮�绁ㄧ櫥璁拌褰曟柊澧�
diff --git a/src/main/java/com/ruoyi/sales/service/impl/MetricStatisticsServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/MetricStatisticsServiceImpl.java
index 010dec0..1ff7fa1 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/MetricStatisticsServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/MetricStatisticsServiceImpl.java
@@ -11,8 +11,8 @@
 import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.ShippingInfo;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -25,16 +25,12 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class MetricStatisticsServiceImpl {
 
-    @Autowired
-    private SalesLedgerMapper salesLedgerMapper;
-
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-
-    @Autowired
-    private ShippingInfoMapper shippingInfoMapper;
+    private final SalesLedgerMapper salesLedgerMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final ShippingInfoMapper shippingInfoMapper;
 
     public AjaxResult total() {
         List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(null);
diff --git a/src/main/java/com/ruoyi/sales/service/impl/PaymentShippingServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/PaymentShippingServiceImpl.java
index 067022a..f4504aa 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/PaymentShippingServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/PaymentShippingServiceImpl.java
@@ -6,8 +6,8 @@
 import com.ruoyi.sales.mapper.PaymentShippingMapper;
 import com.ruoyi.sales.pojo.PaymentShipping;
 import com.ruoyi.sales.service.PaymentShippingService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -16,10 +16,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class PaymentShippingServiceImpl extends ServiceImpl<PaymentShippingMapper, PaymentShipping> implements PaymentShippingService {
 
-    @Autowired
-    private PaymentShippingMapper paymentShippingMapper;
+    private final PaymentShippingMapper paymentShippingMapper;
 
     @Override
     public IPage<PaymentShipping> listPage(Page page, PaymentShipping paymentShipping) {
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java
index b667be2..677249a 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java
@@ -8,48 +8,37 @@
 import com.ruoyi.account.service.AccountIncomeService;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.sales.dto.CustomerInteractionDto;
 import com.ruoyi.sales.dto.InvoiceLedgerDto;
 import com.ruoyi.sales.dto.ReceiptPaymentDto;
 import com.ruoyi.sales.dto.ReceiptPaymentExeclDto;
-import com.ruoyi.sales.mapper.InvoiceLedgerMapper;
 import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
 import com.ruoyi.sales.mapper.SalesLedgerMapper;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.InvoiceLedger;
 import com.ruoyi.sales.pojo.ReceiptPayment;
 import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.service.ReceiptPaymentService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
 
-import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.YearMonth;
 import java.util.*;
-import java.util.stream.Collectors;
 
 @Service
+@RequiredArgsConstructor
 public class ReceiptPaymentServiceImpl extends ServiceImpl<ReceiptPaymentMapper,ReceiptPayment> implements ReceiptPaymentService {
 
-    @Autowired
-    private ReceiptPaymentMapper receiptPaymentMapper;
-
-    @Autowired
-    private SalesLedgerMapper salesLedgerMapper;
-
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-    @Autowired
-    private InvoiceLedgerMapper invoiceLedgerMapper;
-
-    @Autowired
-    private AccountIncomeService accountIncomeService;
+    private final ReceiptPaymentMapper receiptPaymentMapper;
+    private final SalesLedgerMapper salesLedgerMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final AccountIncomeService accountIncomeService;
 
     /**
      * 鍥炴鐧昏鏂板
@@ -82,9 +71,9 @@
                 accountIncome.setIncomeType("3");
                 accountIncome.setCustomerName(salesLedger.getCustomerName());
                 accountIncome.setIncomeMoney(receiptPayment.getReceiptPaymentAmount());
-                accountIncome.setIncomeMethod("0");
+                accountIncome.setIncomeMethod(receiptPayment.getReceiptPaymentType());
                 accountIncome.setInputTime(new Date());
-                accountIncome.setInputUser(salesLedger.getEntryPerson());
+                accountIncome.setInputUser(SecurityUtils.getLoginUser().getNickName());
                 accountIncome.setIncomeDescribed("鍥炴鏀跺叆");
                 accountIncome.setBusinessId(Long.parseLong(receiptPayment.getId().toString()));
                 accountIncome.setBusinessType(1);
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
index 68b52cb..37e06bb 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -6,18 +6,14 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.procurementrecord.utils.StockUtils;
-import com.ruoyi.production.dto.ProductStructureDto;
 import com.ruoyi.production.mapper.*;
-import com.ruoyi.production.pojo.*;
-import com.ruoyi.production.service.impl.ProductOrderServiceImpl;
+import com.ruoyi.production.pojo.ProductionPlan;
+import com.ruoyi.production.service.ProductionOrderService;
 import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.sales.dto.InvoiceRegistrationProductDto;
 import com.ruoyi.sales.dto.SalesLedgerProductDto;
 import com.ruoyi.sales.mapper.InvoiceRegistrationProductMapper;
@@ -30,7 +26,10 @@
 import com.ruoyi.sales.service.ISalesLedgerProductService;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
 import com.ruoyi.stock.pojo.StockInventory;
-import lombok.AllArgsConstructor;
+import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo;
+import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingMapper;
+import com.ruoyi.technology.pojo.TechnologyRouting;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -42,7 +41,10 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -53,45 +55,44 @@
  * @date 2025-05-08
  */
 @Service
-@AllArgsConstructor
 public class SalesLedgerProductServiceImpl extends ServiceImpl<SalesLedgerProductMapper, SalesLedgerProduct> implements ISalesLedgerProductService {
 
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-    private SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-
-    private SalesLedgerMapper salesLedgerMapper;
-
-    private PurchaseLedgerMapper purchaseLedgerMapper;
-
-    private ProductOrderMapper productOrderMapper;
-
-    private ProcessRouteItemMapper processRouteItemMapper;
-
-    private ProductProcessRouteItemMapper productProcessRouteItemMapper;
-
-    private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-
-    private ProcessRouteMapper processRouteMapper;
-    private ProductProcessRouteMapper productProcessRouteMapper;
-
-    private ProductWorkOrderMapper productWorkOrderMapper;
-    private ProductionProductMainMapper productionProductMainMapper;
-    private ProductionProductOutputMapper productionProductOutputMapper;
-    private ProductionProductInputMapper productionProductInputMapper;
-    private QualityInspectMapper qualityInspectMapper;
-    private ShippingInfoMapper shippingInfoMapper;
-    private ShippingInfoServiceImpl shippingInfoService;
-
-    private StockUtils stockUtils;
-
-
-
     @Autowired
-    private ProductStructureMapper productStructureMapper;
+    private SalesLedgerProductMapper salesLedgerProductMapper;
+    @Autowired
+    private ProductionAccountMapper productionAccountMapper;
+    @Autowired
+    private SalesLedgerMapper salesLedgerMapper;
+    @Autowired
+    private PurchaseLedgerMapper purchaseLedgerMapper;
+    @Autowired
+    private ProductionPlanMapper productionPlanMapper;
+    @Autowired
+    private ProductionOperationTaskMapper productionOperationTaskMapper;
+    @Autowired
+    private ProductionOrderService productionOrderService;
+    @Autowired
+    private TechnologyRoutingMapper technologyRoutingMapper;
+    @Autowired
+    private TechnologyBomStructureMapper technologyBomStructureMapper;
+    @Autowired
+    private InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
+    @Autowired
+    private ProductionProductMainMapper productionProductMainMapper;
+    @Autowired
+    private ProductionProductOutputMapper productionProductOutputMapper;
+    @Autowired
+    private ProductionProductInputMapper productionProductInputMapper;
+    @Autowired
+    private QualityInspectMapper qualityInspectMapper;
+    @Autowired
+    private ShippingInfoMapper shippingInfoMapper;
+    @Autowired
+    private ShippingInfoServiceImpl shippingInfoService;
+    @Autowired
+    private StockUtils stockUtils;
     @Autowired
     private StockInventoryMapper stockInventoryMapper;
-    @Autowired
-    private ProductOrderServiceImpl productOrderServiceImpl;
 
     @Override
     public SalesLedgerProduct selectSalesLedgerProductById(Long id) {
@@ -114,7 +115,6 @@
                 if(shippingInfo != null){
                     item.setShippingDate(shippingInfo.getShippingDate());
                     item.setShippingCarNumber(shippingInfo.getShippingCarNumber());
-                    item.setShippingStatus(shippingInfo.getStatus());
                     item.setExpressCompany(shippingInfo.getExpressCompany());
                     item.setExpressNumber(shippingInfo.getExpressNumber());
                 }
@@ -227,7 +227,6 @@
             result = salesLedgerProductMapper.updateById(salesLedgerProduct);
             /*鍒犻櫎瀵瑰簲鐨勭敓浜ф暟鎹苟閲嶆柊鏂板*/
             deleteProductionData(Arrays.asList(salesLedgerProduct.getId()));
-            // 鍒犻櫎鐢熶骇鏍哥畻鏁版嵁
 
             addProductionData(salesLedgerProduct);
         }
@@ -266,164 +265,41 @@
      * 鏂板鐢熶骇鏁版嵁
      */
     public void addProductionData(SalesLedgerProduct salesLedgerProduct) {
-        ProductOrder productOrder = new ProductOrder();
-        productOrder.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
-        productOrder.setProductModelId(salesLedgerProduct.getProductModelId());
-        productOrder.setSaleLedgerProductId(salesLedgerProduct.getId());
-        String string = productOrderServiceImpl.generateNextOrderNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
-        productOrder.setNpsNo(string);
-        productOrder.setQuantity(salesLedgerProduct.getQuantity());//闇�姹傛暟閲�
-        productOrder.setCompleteQuantity(BigDecimal.ZERO);//瀹屾垚鏁伴噺
-        productOrderMapper.insert(productOrder);
-
-        List<ProcessRoute> processRoutes = processRouteMapper.selectList(new QueryWrapper<ProcessRoute>().lambda()
-                .eq(ProcessRoute::getProductModelId, salesLedgerProduct.getProductModelId())
-                .orderByDesc(ProcessRoute::getCreateTime));
-        if (processRoutes.size()>0){
-            ProcessRoute processRoute = processRoutes.get(0);
-            //鏂板鐢熶骇璁㈠崟宸ヨ壓璺嚎涓昏〃
-            ProductProcessRoute productProcessRoute = new ProductProcessRoute();
-            productProcessRoute.setProductModelId(processRoute.getProductModelId());
-            productProcessRoute.setProcessRouteCode(processRoute.getProcessRouteCode());
-            productProcessRoute.setProductOrderId(productOrder.getId());
-            productProcessRoute.setBomId(processRoute.getBomId());
-            productProcessRouteMapper.insert(productProcessRoute);
-            //鏂板鐢熶骇璁㈠崟宸ヨ壓璺嚎瀛愯〃
-            List<ProcessRouteItem> processRouteItems = processRouteItemMapper.selectList(new QueryWrapper<ProcessRouteItem>().lambda().eq(ProcessRouteItem::getRouteId, processRoute.getId()));
-            // 鐢熸垚褰撳墠鏃ユ湡鐨勫墠缂�锛氬勾鏈堟棩
-            String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
-            for (ProcessRouteItem processRouteItem : processRouteItems) {
-                ProductProcessRouteItem productProcessRouteItem = new ProductProcessRouteItem();
-                productProcessRouteItem.setProductModelId(processRouteItem.getProductModelId());
-                productProcessRouteItem.setProcessId(processRouteItem.getProcessId());
-                productProcessRouteItem.setProductOrderId(productOrder.getId());
-                productProcessRouteItem.setProductRouteId(productProcessRoute.getId());
-                productProcessRouteItem.setDragSort(processRouteItem.getDragSort());
-                int insert = productProcessRouteItemMapper.insert(productProcessRouteItem);
-                if (insert > 0) {
-                    // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶у伐鍗曞彿
-                    ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectMax(datePrefix);
-                    int sequenceNumber = 1; // 榛樿搴忓彿
-                    if (lastWorkOrder != null && lastWorkOrder.getWorkOrderNo() != null) {
-                        String lastNo = lastWorkOrder.getWorkOrderNo().toString();
-                        if (lastNo.startsWith(datePrefix)) {
-                            String seqStr = lastNo.substring(datePrefix.length());
-                            try {
-                                sequenceNumber = Integer.parseInt(seqStr) + 1;
-                            } catch (NumberFormatException e) {
-                                sequenceNumber = 1;
-                            }
-                        }
-                    }
-                    // 鐢熸垚瀹屾暣鐨勫伐鍗曞彿
-                    String workOrderNoStr ="GD"+ String.format("%s%03d", datePrefix, sequenceNumber);
-                    ProductWorkOrder productWorkOrder = new ProductWorkOrder();
-                    productWorkOrder.setProductProcessRouteItemId(productProcessRouteItem.getId());
-                    productWorkOrder.setProductOrderId(productOrder.getId());
-                    productWorkOrder.setPlanQuantity(salesLedgerProduct.getQuantity());
-                    productWorkOrder.setWorkOrderNo(workOrderNoStr);
-                    productWorkOrder.setStatus(1);
-
-                    productWorkOrderMapper.insert(productWorkOrder);
-                }
-
-            }
-            productOrder.setRouteId(processRoute.getId());
-            productOrderMapper.updateById(productOrder);
+        //鍏堝垽鏂浜у搧鏄惁闇�瑕佺敓浜�
+        if (!salesLedgerProduct.getIsProduction()) {
+            return;
         }
+        SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerProduct.getSalesLedgerId());
+        ProductionPlan productionPlan = new ProductionPlan();
+        productionPlan.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
+        productionPlan.setSalesLedgerProductId(salesLedgerProduct.getId());
+        productionPlan.setMpsNo(generateNextPlanNo(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))));
+        productionPlan.setProductModelId(salesLedgerProduct.getProductModelId());
+        productionPlan.setQtyRequired(salesLedgerProduct.getQuantity());
+        productionPlan.setSource("閿�鍞�");
+        productionPlan.setStatus(0);
+        productionPlan.setRequiredDate(salesLedger.getDeliveryDate());//闇�姹傛棩鏈�=浜よ揣鏃ユ湡
+        productionPlan.setPromisedDeliveryDate(salesLedger.getDeliveryDate());//鎵胯鏃ユ湡=浜よ揣鏃ユ湡
+        productionPlanMapper.insert(productionPlan);
+
     }
 
     /**
-     * 鍒犻櫎鐢熶骇鏁版嵁
+     * 鍒犻櫎鐢熶骇璁″垝
      */
     public void deleteProductionData(List<Long> productIds) {
-        //鎵归噺鏌ヨproductOrder
-        List<ProductOrder> productOrders = productOrderMapper.selectList(
-                new LambdaQueryWrapper<ProductOrder>()
-                        .in(ProductOrder::getSaleLedgerProductId, productIds)
-        );
-        if (!org.springframework.util.CollectionUtils.isEmpty(productOrders)) {
-            List<Long> orderIds = productOrders.stream()
-                    .map(ProductOrder::getId)
-                    .collect(Collectors.toList());
-
-            // 鎵归噺鏌ヨprocessRouteItems
-            List<ProductProcessRouteItem> allRouteItems = productProcessRouteItemMapper.selectList(
-                    new LambdaQueryWrapper<ProductProcessRouteItem>()
-                            .in(ProductProcessRouteItem::getProductOrderId, orderIds)
-            );
-
-            if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(allRouteItems)) {
-                // 鑾峰彇瑕佸垹闄ょ殑宸ュ簭椤笽D
-                List<Long> routeItemIds = allRouteItems.stream()
-                        .map(ProductProcessRouteItem::getId)
-                        .collect(Collectors.toList());
-
-                // 鏌ヨ鍏宠仈鐨勫伐鍗旾D
-                List<ProductWorkOrder> workOrders = productWorkOrderMapper.selectList(
-                        new LambdaQueryWrapper<ProductWorkOrder>()
-                                .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds)
-                );
-                if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(workOrders)) {
-                    List<Long> workOrderIds = workOrders.stream()
-                            .map(ProductWorkOrder::getId)
-                            .collect(Collectors.toList());
-
-                    // 鏌ヨ鍏宠仈鐨勭敓浜т富琛↖D
-                    List<ProductionProductMain> productMains = productionProductMainMapper.selectList(
-                            new LambdaQueryWrapper<ProductionProductMain>()
-                                    .in(ProductionProductMain::getWorkOrderId, workOrderIds)
-                    );
-                    List<Long> productMainIds = productMains.stream()
-                            .map(ProductionProductMain::getId)
-                            .collect(Collectors.toList());
-
-                    // 鍒犻櫎浜у嚭琛ㄣ�佹姇鍏ヨ〃鏁版嵁
-                    if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(productMainIds)) {
-                        productionProductOutputMapper.deleteByProductMainIds(productMainIds);
-                        productionProductInputMapper.deleteByProductMainIds(productMainIds);
-                        List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(
-                                new LambdaQueryWrapper<QualityInspect>()
-                                        .in(QualityInspect::getProductMainId, productMainIds)
-                        );
-                        //鍒犻櫎鍑哄簱璁板綍
-                        for (Long productMainId : productMainIds) {
-                            //鍒犻櫎鐢熶骇鍑哄簱璁板綍
-                            stockUtils.deleteStockOutRecord(productMainId, StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
-                            //鍒犻櫎鎶ュ簾鐨勫叆搴撹褰�
-                            stockUtils.deleteStockInRecord(productMainId, StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
-                        }
-                        qualityInspects.forEach(qualityInspect -> {
-                            //inspectState=1 宸叉彁浜� 涓嶈兘鍒犻櫎
-                            if (qualityInspect.getInspectState() == 1) {
-                                throw new RuntimeException("宸叉彁浜ょ殑妫�楠屽崟涓嶈兘鍒犻櫎");
-                            }
-                        });
-                        qualityInspectMapper.deleteByProductMainIds(productMainIds);
-                        salesLedgerProductionAccountingMapper.delete(new LambdaQueryWrapper<SalesLedgerProductionAccounting>()
-                                .in(SalesLedgerProductionAccounting::getProductMainId, productMainIds));
-                    }
-
-                    // 鍒犻櫎鐢熶骇涓昏〃鏁版嵁
-                    productionProductMainMapper.deleteByWorkOrderIds(workOrderIds);
-
-                    // 鍒犻櫎宸ュ崟鏁版嵁
-                    productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>()
-                            .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds));
-                }
-            }
-            // 鎵归噺鍒犻櫎processRouteItem
-            productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>()
-                    .in(ProductProcessRouteItem::getProductOrderId, orderIds));
-
-            // 鎵归噺鍒犻櫎productProcessRoute
-            productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>()
-                    .in(ProductProcessRoute::getProductOrderId, orderIds));
-
-            // 鎵归噺鍒犻櫎productOrder
-            productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>()
-                    .in(ProductOrder::getSaleLedgerProductId, productIds));
+        List<ProductionPlan> productionPlans = productionPlanMapper.selectList(
+                new LambdaQueryWrapper<ProductionPlan>()
+                        .in(ProductionPlan::getSalesLedgerProductId, productIds.stream().map(Long::intValue).collect(Collectors.toList())));
+        if (CollectionUtils.isEmpty(productionPlans)) {
+            return;
         }
+        //濡傛灉鐢熶骇璁″垝宸蹭笅鍙戝垯涓嶈兘鍒犻櫎
+        if (productionPlans.stream().anyMatch(productionPlan -> productionPlan.getStatus() != 0)) {
+            throw new RuntimeException("鐢熶骇璁″垝宸蹭笅鍙戯紝涓嶈兘鍒犻櫎璇ラ攢鍞骇鍝�");
+        }
+        List<Long> ids = productionPlans.stream().map(ProductionPlan::getId).collect(Collectors.toList());
+        productionPlanMapper.deleteByIds(ids);
     }
 
     @Override
@@ -490,37 +366,67 @@
     }
     @Override
     public R judgmentInventory(SalesLedgerProduct salesLedgerProduct) {
-        //鑾峰彇浜у搧鏈�鏂扮殑宸ヨ壓璺嚎
-        ProcessRoute processRoute = processRouteMapper.selectOne(new QueryWrapper<ProcessRoute>().lambda().eq(ProcessRoute::getProductModelId, salesLedgerProduct.getProductModelId()).orderByDesc(ProcessRoute::getCreateTime).last("LIMIT 1"));
-        if (processRoute == null) {
+        TechnologyRouting routing = technologyRoutingMapper.selectOne(
+                new QueryWrapper<TechnologyRouting>().lambda()
+                        .eq(TechnologyRouting::getProductModelId, salesLedgerProduct.getProductModelId())
+                        .orderByDesc(TechnologyRouting::getCreateTime)
+                        .last("LIMIT 1"));
+        if (routing == null) {
             return R.fail("璇峰厛璁剧疆宸ヨ壓璺嚎");
         }
-        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomId(processRoute.getBomId());
-        if (productStructureDtos.isEmpty()) {
+        List<TechnologyBomStructureVo> structureList = technologyBomStructureMapper.listByBomId(routing.getBomId().longValue());
+        if (structureList == null || structureList.isEmpty()) {
             return R.fail("璇峰厛璁剧疆浜у搧缁撴瀯");
         }
         int count = 0;
         StringBuilder stringBuffer = new StringBuilder();
-        for (ProductStructureDto productStructureDto : productStructureDtos) {
-            StockInventory stockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, productStructureDto.getProductModelId()));
-
-            //鎵�闇�鏁伴噺
-            BigDecimal multiply = salesLedgerProduct.getQuantity().multiply(productStructureDto.getUnitQuantity());
-            BigDecimal subtract =stockInventory.getQualitity().subtract(stockInventory.getLockedQuantity()).subtract(multiply).divide(BigDecimal.ONE, 2, RoundingMode.CEILING);
-            if (subtract.compareTo(BigDecimal.ZERO) <= 0) {
+        for (TechnologyBomStructureVo structure : structureList) {
+            if (structure.getParentId() == null) {
+                continue;
+            }
+            StockInventory stockInventory = stockInventoryMapper.selectOne(
+                    new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, structure.getProductModelId()));
+            if (stockInventory == null) {
                 count++;
-                stringBuffer.append(productStructureDto.getProductName())
+                stringBuffer.append(structure.getProductName()).append("-").append(structure.getModel()).append("搴撳瓨涓嶈冻").append(System.lineSeparator());
+                continue;
+            }
+            BigDecimal required = salesLedgerProduct.getQuantity().multiply(structure.getUnitQuantity() == null ? BigDecimal.ZERO : structure.getUnitQuantity());
+            BigDecimal remain = stockInventory.getQualitity()
+                    .subtract(stockInventory.getLockedQuantity())
+                    .subtract(required)
+                    .divide(BigDecimal.ONE, 2, RoundingMode.CEILING);
+            if (remain.compareTo(BigDecimal.ZERO) < 0) {
+                count++;
+                stringBuffer.append(structure.getProductName())
                         .append("-")
-                        .append(productStructureDto.getModel())
+                        .append(structure.getModel())
                         .append("搴撳瓨涓嶈冻锛屽皯")
-                        .append(subtract)
+                        .append(remain.abs())
                         .append(System.lineSeparator());
             }
         }
-        if (count>0) {
+        if (count > 0) {
             return R.fail(stringBuffer.toString());
-        }else {
-            return R.ok();
         }
+        return R.ok();
+    }
+
+    private String generateNextPlanNo(String datePrefix) {
+        QueryWrapper<ProductionPlan> queryWrapper = new QueryWrapper<>();
+        queryWrapper.likeRight("mps_no", "JH" + datePrefix);
+        queryWrapper.orderByDesc("mps_no");
+        queryWrapper.last("LIMIT 1");
+        ProductionPlan latestPlan = productionPlanMapper.selectOne(queryWrapper);
+        int sequence = 1;
+        if (latestPlan != null && latestPlan.getMpsNo() != null && !latestPlan.getMpsNo().isEmpty()) {
+            String sequenceStr = latestPlan.getMpsNo().substring(("JH" + datePrefix).length());
+            try {
+                sequence = Integer.parseInt(sequenceStr) + 1;
+            } catch (NumberFormatException e) {
+                sequence = 1;
+            }
+        }
+        return "JH" + datePrefix + String.format("%04d", sequence);
     }
 }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index 8f13c5e..9803611 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -9,7 +9,6 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.account.service.AccountIncomeService;
-import com.ruoyi.aftersalesservice.pojo.AfterSalesService;
 import com.ruoyi.basic.mapper.CustomerMapper;
 import com.ruoyi.basic.mapper.ProductMapper;
 import com.ruoyi.basic.mapper.ProductModelMapper;
@@ -27,23 +26,23 @@
 import com.ruoyi.other.mapper.TempFileMapper;
 import com.ruoyi.other.pojo.TempFile;
 import com.ruoyi.production.mapper.*;
-import com.ruoyi.production.pojo.*;
 import com.ruoyi.production.service.ProductionProductMainService;
-import com.ruoyi.production.service.impl.ProductionProductMainServiceImpl;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrderProductsMapper;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
-import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.sales.dto.*;
 import com.ruoyi.sales.mapper.*;
 import com.ruoyi.sales.pojo.*;
-import com.ruoyi.sales.service.ISalesLedgerProductService;
 import com.ruoyi.sales.service.ISalesLedgerService;
+import com.ruoyi.sales.vo.SalesLedgerVo;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
+import org.jetbrains.annotations.Nullable;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -81,91 +80,81 @@
 @RequiredArgsConstructor
 @Slf4j
 public class SalesLedgerServiceImpl extends ServiceImpl<SalesLedgerMapper, SalesLedger> implements ISalesLedgerService {
-    private final AccountIncomeService accountIncomeService;
-
-    private final SalesLedgerMapper salesLedgerMapper;
-
-    private final CustomerMapper customerMapper;
-
-    private final SalesLedgerProductMapper salesLedgerProductMapper;
-    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
-
-    private final CommonFileMapper commonFileMapper;
-
-    private final TempFileMapper tempFileMapper;
-
-    private final ReceiptPaymentMapper receiptPaymentMapper;
-
-    private final ShippingInfoServiceImpl shippingInfoServiceImpl;
-
-    private final CommonFileServiceImpl commonFileService;
-
-    private final ShippingInfoMapper shippingInfoMapper;
-
-    private final InvoiceLedgerMapper invoiceLedgerMapper;
-
-    private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper;
-
-    private final SalesLedgerWorkMapper salesLedgerWorkMapper;
-
-    private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper;
-
-    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-
-    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
-
-    private final ProductOrderMapper productOrderMapper;
-
-    private final ProcessRouteMapper processRouteMapper;
-    private final ProductProcessRouteMapper productProcessRouteMapper;
-
-    private final ProcessRouteItemMapper processRouteItemMapper;
-
-    private final ProductProcessRouteItemMapper productProcessRouteItemMapper;
-
-    private final ProductWorkOrderMapper productWorkOrderMapper;
-
-    private final ProductionProductMainMapper productionProductMainMapper;
-
-    private final ProductionProductOutputMapper productionProductOutputMapper;
-
-    private final ProductionProductInputMapper productionProductInputMapper;
-
-    private final QualityInspectMapper qualityInspectMapper;
-
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
-
-    @Value("${file.upload-dir}")
-    private String uploadDir;
-
     private static final String LOCK_PREFIX = "contract_no_lock:";
     private static final long LOCK_WAIT_TIMEOUT = 10; // 閿佺瓑寰呰秴鏃舵椂闂达紙绉掞級
     private static final long LOCK_EXPIRE_TIME = 30;  // 閿佽嚜鍔ㄨ繃鏈熸椂闂达紙绉掞級
-
+    private final AccountIncomeService accountIncomeService;
+    private final SalesLedgerMapper salesLedgerMapper;
+    private final CustomerMapper customerMapper;
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl;
+    private final CommonFileMapper commonFileMapper;
+    private final TempFileMapper tempFileMapper;
+    private final ReceiptPaymentMapper receiptPaymentMapper;
+    private final ShippingInfoServiceImpl shippingInfoServiceImpl;
+    private final CommonFileServiceImpl commonFileService;
+    private final ShippingInfoMapper shippingInfoMapper;
+    private final InvoiceLedgerMapper invoiceLedgerMapper;
+    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
+    private final InvoiceRegistrationMapper invoiceRegistrationMapper;
+    private final ProductionProductMainMapper productionProductMainMapper;
+    private final ProductionProductOutputMapper productionProductOutputMapper;
+    private final ProductionProductInputMapper productionProductInputMapper;
+    private final QualityInspectMapper qualityInspectMapper;
     private final RedisTemplate<String, String> redisTemplate;
+    @Autowired
+    private SysDeptMapper sysDeptMapper;
+    @Value("${file.upload-dir}")
+    private String uploadDir;
     @Autowired
     private ProductModelMapper productModelMapper;
 
     @Autowired
     private ProductMapper productMapper;
     @Autowired
-    private ProductStructureMapper productStructureMapper;
-    @Autowired
     private ProductionProductMainService productionProductMainService;
+    @Autowired
+    private PurchaseReturnOrderProductsMapper purchaseReturnOrderProductsMapper;
     ;
+    @Autowired
+    private SysUserMapper sysUserMapper;
 
     @Override
     public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
         return salesLedgerMapper.selectSalesLedgerList(salesLedgerDto);
     }
 
-
-    public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type){
+    public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type) {
         LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
         productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, relateId);
         productWrapper.eq(SalesLedgerProduct::getType, type.getCode());
         return salesLedgerProductMapper.selectList(productWrapper);
+    }
+
+    @Override
+    public List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, SaleEnum type) {
+        if (CollectionUtils.isEmpty(relateIds)) {
+            return Collections.emptyList();
+        }
+        LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
+        productWrapper.in(SalesLedgerProduct::getId, relateIds);
+        productWrapper.eq(SalesLedgerProduct::getType, type.getCode());
+        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(productWrapper);
+        if (type.equals(SaleEnum.PURCHASE)) {
+            // 鏌ヨ閫�璐т俊鎭�
+            List<Long> productIds = salesLedgerProducts.stream().map(SalesLedgerProduct::getId).collect(Collectors.toList());
+            List<SimpleReturnOrderGroupDto> groupListByProductIds = new ArrayList<>();
+            if(CollectionUtils.isNotEmpty(productIds)){
+                groupListByProductIds = purchaseReturnOrderProductsMapper.getReturnOrderGroupListByProductIds(productIds);
+            }
+            Map<Long, BigDecimal> returnOrderGroupDtoMap = groupListByProductIds.stream().collect(Collectors.toMap(SimpleReturnOrderGroupDto::getSalesLedgerProductId, SimpleReturnOrderGroupDto::getSumReturnQuantity));
+            salesLedgerProducts.forEach(item -> {
+                BigDecimal returnQuality = returnOrderGroupDtoMap.getOrDefault(item.getId(), BigDecimal.ZERO);
+                item.setReturnQuality(returnQuality);
+                item.setAvailableQuality(item.getQuantity().subtract(returnQuality));
+            });
+        }
+        return salesLedgerProducts;
     }
 
     @Override
@@ -335,12 +324,9 @@
     }
 
     @Override
-    public IPage<SalesLedger> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto) {
+    public IPage<SalesLedgerVo> selectSalesLedgerListPage(Page page, SalesLedgerDto salesLedgerDto) {
         return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto);
     }
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -465,7 +451,7 @@
 
     @Override
     public IPage<SalesLedgerDto> listSalesLedger(SalesLedgerDto salesLedgerDto, Page page) {
-        IPage<SalesLedgerDto> salesLedgerDtoIPage = salesLedgerMapper.listSalesLedger(page, salesLedgerDto);
+        IPage<SalesLedgerDto> salesLedgerDtoIPage = salesLedgerMapper.listSalesLedgerAndShipped(page, salesLedgerDto);
         for (SalesLedgerDto salesLedger : salesLedgerDtoIPage.getRecords()) {
             LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
             productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId());
@@ -483,49 +469,22 @@
                         .eq(ShippingInfo::getSalesLedgerProductId, product.getId())
                         .orderByDesc(ShippingInfo::getCreateTime)
                         .last("limit 1"));
+                product.setShippingCarNumber(shippingInfo.getShippingCarNumber());
+                product.setShippingDate(shippingInfo.getShippingDate());
                 if (shippingInfo != null) {
                     product.setShippingStatus(shippingInfo.getStatus());
-
                 }
             }
+            // 杩囨护鍙繚鐣欏彂璐ц褰�
+            products = products.stream().filter(product -> "宸插彂璐�".equals(product.getShippingStatus())).collect(Collectors.toList());
             if (!products.isEmpty()) {
                 salesLedger.setHasChildren(true);
                 salesLedger.setProductData(products);
             }
         }
 
+
         return salesLedgerDtoIPage;
-    }
-
-
-    // 鍐呴儴绫荤敤浜庡瓨鍌ㄨ仛鍚堢粨鏋�
-    private static class GroupedCustomer {
-        private final Long customerId;
-        private final String customerName;
-        private BigDecimal totalAmount = BigDecimal.ZERO;
-
-        public GroupedCustomer(Long customerId, String customerName) {
-            this.customerId = customerId;
-            this.customerName = customerName;
-        }
-
-        public void addAmount(BigDecimal amount) {
-            if (amount != null) {
-                this.totalAmount = this.totalAmount.add(amount);
-            }
-        }
-
-        public Long getCustomerId() {
-            return customerId;
-        }
-
-        public String getCustomerName() {
-            return customerName;
-        }
-
-        public BigDecimal getTotalAmount() {
-            return totalAmount;
-        }
     }
 
     /**
@@ -646,7 +605,7 @@
             // 4. 澶勭悊瀛愯〃鏁版嵁
             List<SalesLedgerProduct> productList = salesLedgerDto.getProductData();
             if (productList != null && !productList.isEmpty()) {
-                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class,salesLedgerDto.getType()));
+                handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType()));
                 updateMainContractAmount(
                         salesLedger.getId(),
                         productList,
@@ -665,8 +624,6 @@
             throw new BaseException("鏂囦欢杩佺Щ澶辫触: " + e.getMessage());
         }
     }
-
-    // 鏂囦欢杩佺Щ鏂规硶
 
     /**
      * 灏嗕复鏃舵枃浠惰縼绉诲埌姝e紡鐩綍
@@ -743,6 +700,7 @@
         }
     }
 
+    // 鏂囦欢杩佺Щ鏂规硶
 
     @Override
     public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) {
@@ -884,4 +842,34 @@
             throw new RuntimeException("鍔ㄦ�佹洿鏂颁富琛ㄩ噾棰濆け璐�", e);
         }
     }
+
+    // 鍐呴儴绫荤敤浜庡瓨鍌ㄨ仛鍚堢粨鏋�
+    private static class GroupedCustomer {
+        private final Long customerId;
+        private final String customerName;
+        private BigDecimal totalAmount = BigDecimal.ZERO;
+
+        public GroupedCustomer(Long customerId, String customerName) {
+            this.customerId = customerId;
+            this.customerName = customerName;
+        }
+
+        public void addAmount(BigDecimal amount) {
+            if (amount != null) {
+                this.totalAmount = this.totalAmount.add(amount);
+            }
+        }
+
+        public Long getCustomerId() {
+            return customerId;
+        }
+
+        public String getCustomerName() {
+            return customerName;
+        }
+
+        public BigDecimal getTotalAmount() {
+            return totalAmount;
+        }
+    }
 }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
index 8e18058..1ec6a8d 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java
@@ -4,17 +4,18 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-
 import com.ruoyi.approve.pojo.ApproveProcess;
-import com.ruoyi.approve.service.IApproveProcessService;
 import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
-import com.ruoyi.approve.vo.ApproveGetAndUpdateVo;
-import com.ruoyi.approve.vo.ApproveProcessVO;
+import com.ruoyi.approve.bean.vo.ApproveGetAndUpdateVo;
+import com.ruoyi.approve.bean.vo.ApproveProcessVO;
+import com.ruoyi.basic.mapper.CustomerMapper;
+import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
-import com.ruoyi.common.utils.uuid.UUID;
 import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.sales.dto.SalesQuotationDto;
 import com.ruoyi.sales.mapper.SalesQuotationMapper;
@@ -23,8 +24,7 @@
 import com.ruoyi.sales.pojo.SalesQuotationProduct;
 import com.ruoyi.sales.service.SalesQuotationProductService;
 import com.ruoyi.sales.service.SalesQuotationService;
-import org.springframework.beans.factory.annotation.Autowired;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -35,16 +35,15 @@
 
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class SalesQuotationServiceImpl extends ServiceImpl<SalesQuotationMapper, SalesQuotation> implements SalesQuotationService {
-    @Autowired
-    private SalesQuotationMapper salesQuotationMapper;
-    @Autowired
-    private SalesQuotationProductMapper salesQuotationProductMapper;
-    @Autowired
-    private SalesQuotationProductService salesQuotationProductService;
+    private final SalesQuotationProductMapper salesQuotationProductMapper;
+    private final SalesQuotationMapper salesQuotationMapper;
+    private final SalesQuotationProductService salesQuotationProductService;
 
-    @Autowired
-    private ApproveProcessServiceImpl approveProcessService;
+    private final ApproveProcessServiceImpl approveProcessService;
+    private final CustomerMapper customerMapper;
+
     @Override
     public IPage<SalesQuotationDto> listPage(Page page, SalesQuotationDto salesQuotationDto) {
         IPage<SalesQuotationDto> salesQuotationDtoIPage = salesQuotationMapper.listPage(page, salesQuotationDto);
@@ -62,8 +61,11 @@
     public boolean add(SalesQuotationDto salesQuotationDto) {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SalesQuotation salesQuotation = new SalesQuotation();
-        BeanUtils.copyProperties(salesQuotationDto, salesQuotation);
-        String quotationNo = OrderUtils.countTodayByCreateTime(salesQuotationMapper, "QT");
+        Customer customer = customerMapper.selectById(Long.valueOf(salesQuotationDto.getCustomerId()));
+        if (ObjectUtils.isNotEmpty(customer))  {
+            salesQuotation.setCustomer(customer.getCustomerName());
+        }
+        String quotationNo = OrderUtils.countTodayByCreateTime(salesQuotationMapper, "QT","quotation_no");
         salesQuotation.setQuotationNo(quotationNo);
         salesQuotation.setStatus("寰呭鎵�");
         salesQuotationMapper.insert(salesQuotation);
@@ -90,7 +92,7 @@
             approveProcessService.addApprove(approveProcessVO);
         }catch (Exception e){
             log.error("SalesQuotationServiceImpl error:{}", e);
-            throw new RuntimeException("瀹℃壒澶辫触");
+            throw                                new RuntimeException("瀹℃壒澶辫触");
         }
         return true;
     }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalespersonManagementServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalespersonManagementServiceImpl.java
index 0afd2bb..1966ebf 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalespersonManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalespersonManagementServiceImpl.java
@@ -7,8 +7,8 @@
 import com.ruoyi.sales.mapper.SalespersonManagementMapper;
 import com.ruoyi.sales.pojo.SalespersonManagement;
 import com.ruoyi.sales.service.SalespersonManagementService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.Arrays;
@@ -19,10 +19,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class SalespersonManagementServiceImpl extends ServiceImpl<SalespersonManagementMapper, SalespersonManagement> implements SalespersonManagementService {
 
-    @Autowired
-    private SalespersonManagementMapper salespersonManagementMapper;
+    private final SalespersonManagementMapper salespersonManagementMapper;
 
     @Override
     public IPage<SalespersonManagement> listPage(Page page, SalespersonManagement salespersonManagement) {
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShipmentApprovalServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShipmentApprovalServiceImpl.java
index 0df4c34..9c358e7 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShipmentApprovalServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShipmentApprovalServiceImpl.java
@@ -4,13 +4,10 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.sales.mapper.ShipmentApprovalMapper;
-import com.ruoyi.sales.mapper.ShippingInfoMapper;
 import com.ruoyi.sales.pojo.ShipmentApproval;
-import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.ShipmentApprovalService;
-import com.ruoyi.sales.service.ShippingInfoService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -19,10 +16,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class ShipmentApprovalServiceImpl extends ServiceImpl<ShipmentApprovalMapper, ShipmentApproval> implements ShipmentApprovalService {
 
-    @Autowired
-    private ShipmentApprovalMapper shipmentApprovalMapper;
+    private final ShipmentApprovalMapper shipmentApprovalMapper;
 
     @Override
     public IPage<ShipmentApproval> listPage(Page page, ShipmentApproval req) {
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
index c9651a7..545ac7d 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -6,24 +6,26 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
+import com.ruoyi.basic.enums.ApplicationTypeEnum;
+import com.ruoyi.basic.enums.RecordTypeEnum;
+import com.ruoyi.basic.utils.FileUtil;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
-import com.ruoyi.other.service.impl.TempFileServiceImpl;
 import com.ruoyi.procurementrecord.utils.StockUtils;
 import com.ruoyi.sales.dto.SalesLedgerProductDto;
 import com.ruoyi.sales.dto.ShippingInfoDto;
+import com.ruoyi.sales.dto.ShippingProductDetailDto;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.mapper.ShippingInfoMapper;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.mapper.ShippingProductDetailMapper;
 import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
 import com.ruoyi.sales.service.ShippingInfoService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.io.IOException;
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -32,42 +34,48 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class ShippingInfoServiceImpl extends ServiceImpl<ShippingInfoMapper, ShippingInfo> implements ShippingInfoService {
 
-    @Autowired
-    private ShippingInfoMapper shippingInfoMapper;
 
-    @Autowired
-    private TempFileServiceImpl tempFileService;
-    @Autowired
-    private SalesLedgerProductMapper salesLedgerProductMapper;
-    @Autowired
-    private StockUtils stockUtils;
-    @Autowired
-    private CommonFileServiceImpl commonFileService;
+    private final ShippingInfoMapper shippingInfoMapper;
 
-    @Autowired
-    private ApproveProcessServiceImpl approveProcessService;
+
+    private final SalesLedgerProductMapper salesLedgerProductMapper;
+
+    private final StockUtils stockUtils;
+
+    private final CommonFileServiceImpl commonFileService;
+
+    private final ApproveProcessServiceImpl approveProcessService;
+    private final FileUtil fileUtil;
+    private final ShippingProductDetailMapper shippingProductDetailMapper;
 
     @Override
     public IPage<ShippingInfoDto> listPage(Page page, ShippingInfo req) {
         IPage<ShippingInfoDto> listPage = shippingInfoMapper.listPage(page, req);
         listPage.getRecords().forEach(item ->{
-            item.setCommonFileList(commonFileService.getFileListByBusinessId(item.getId(), FileNameType.SHIP.getValue()));
+            item.setStorageBlobVOs(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.IMAGE, RecordTypeEnum.SHIPPING_INFO, item.getId()));
         });
         return listPage;
     }
 
     @Override
-    public boolean deductStock(ShippingInfoDto req) throws IOException {
+    public boolean deductStock(ShippingInfoDto req) {
         ShippingInfo byId = this.getById(req.getId());
         if (byId == null) {
             throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
         }
         //鎵e噺搴撳瓨
         if(!"宸插彂璐�".equals(byId.getStatus())){
-            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
-            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+//            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
+            List<ShippingProductDetail> shippingProductDetails = shippingProductDetailMapper.selectList(new LambdaQueryWrapper<ShippingProductDetail>().eq(ShippingProductDetail::getShippingInfoId, req.getId()));
+            if (CollectionUtils.isEmpty(shippingProductDetails)) {
+                throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
+            }
+            for (ShippingProductDetail shippingProductDetail : shippingProductDetails) {
+                stockUtils.substractStock(shippingProductDetail.getProductModelId(), shippingProductDetail.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(), shippingProductDetail.getBatchNo());
+            }
         }
         byId.setExpressNumber(req.getExpressNumber());
         byId.setExpressCompany(req.getExpressCompany());
@@ -75,10 +83,8 @@
         byId.setShippingCarNumber(req.getShippingCarNumber());
         byId.setShippingDate(req.getShippingDate());
         boolean update = this.updateById(byId);
-        // 杩佺Щ鏂囦欢
-        if(CollectionUtils.isNotEmpty(req.getTempFileIds())){
-            tempFileService.migrateTempFilesToFormal(req.getId(), req.getTempFileIds(), FileNameType.SHIP.getValue());
-        }
+        // 淇濆瓨鏂囦欢
+        fileUtil.saveStorageAttachment(ApplicationTypeEnum.IMAGE, RecordTypeEnum.SHIPPING_INFO, req.getId(), req.getStorageBlobDTOs());
         return update ;
     }
 
@@ -98,15 +104,18 @@
         // 鍒犻櫎鍙戣揣瀹℃壒
         if(CollectionUtils.isNotEmpty(shippingInfos)){
             for (ShippingInfo shippingInfo : shippingInfos){
-                ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>()
+                List<ApproveProcess> one = approveProcessService.list(new LambdaQueryWrapper<ApproveProcess>()
                         .like(ApproveProcess::getApproveReason, shippingInfo.getShippingNo()));
                 if(one != null){
-                    approveProcessService.delByIds(Collections.singletonList(one.getId()));
+                    List<Long> list = one.stream().map(ApproveProcess::getId).toList();
+                    approveProcessService.delByIds(list);
                 }
             }
         }
+        //鍒犻櫎鍙戣揣鏄庣粏
+        shippingProductDetailMapper.delete(new LambdaQueryWrapper<ShippingProductDetail>().in(ShippingProductDetail::getShippingInfoId, ids));
 
-        return this.removeBatchByIds(ids);
+        return this.removeByIds(ids);
     }
 
     @Override
@@ -119,4 +128,17 @@
     public List<ShippingInfo> getShippingInfoByCustomerName(String customerName) {
         return shippingInfoMapper.getShippingInfoByCustomerName(customerName);
     }
+
+    @Override
+    public boolean add(ShippingInfoDto req) {
+        this.save( req);
+        req.getBatchNoDetailList().forEach(item -> item.setShippingInfoId(req.getId()));
+        shippingProductDetailMapper.insert(req.getBatchNoDetailList());
+        return true;
+    }
+
+    @Override
+    public List<ShippingProductDetailDto> getDetail(Long id) {
+        return shippingProductDetailMapper.getDetail(id);
+    }
 }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java
new file mode 100644
index 0000000..9b31881
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingProductDetailServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.sales.service.impl;
+
+import com.ruoyi.sales.pojo.ShippingProductDetail;
+import com.ruoyi.sales.mapper.ShippingProductDetailMapper;
+import com.ruoyi.sales.service.ShippingProductDetailService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鍙戣揣鍙拌处璇︽儏琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-05-06 10:02:10
+ */
+@Service
+public class ShippingProductDetailServiceImpl extends ServiceImpl<ShippingProductDetailMapper, ShippingProductDetail> implements ShippingProductDetailService {
+
+}
diff --git a/src/main/java/com/ruoyi/sales/vo/SalesLedgerVo.java b/src/main/java/com/ruoyi/sales/vo/SalesLedgerVo.java
new file mode 100644
index 0000000..fb932f8
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/vo/SalesLedgerVo.java
@@ -0,0 +1,13 @@
+package com.ruoyi.sales.vo;
+
+import com.ruoyi.basic.dto.StorageBlobVO;
+import com.ruoyi.sales.pojo.SalesLedger;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SalesLedgerVo extends SalesLedger {
+
+    private List<StorageBlobVO> storageBlobVOs;
+}
diff --git a/src/main/java/com/ruoyi/staff/controller/AnalyticsController.java b/src/main/java/com/ruoyi/staff/controller/AnalyticsController.java
index cfa802c..2522550 100644
--- a/src/main/java/com/ruoyi/staff/controller/AnalyticsController.java
+++ b/src/main/java/com/ruoyi/staff/controller/AnalyticsController.java
@@ -6,7 +6,7 @@
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 
 @RestController
 @RequestMapping("/staff/analytics")
diff --git a/src/main/java/com/ruoyi/staff/controller/BankController.java b/src/main/java/com/ruoyi/staff/controller/BankController.java
index 5d3a9fc..1e9aa1f 100644
--- a/src/main/java/com/ruoyi/staff/controller/BankController.java
+++ b/src/main/java/com/ruoyi/staff/controller/BankController.java
@@ -5,9 +5,9 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.staff.pojo.Bank;
 import com.ruoyi.staff.service.BankService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -21,12 +21,12 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-03-06 03:40:54
  */
-@Api(tags = "閾惰绠$悊琛�")
+@Tag(name = "閾惰绠$悊琛�")
 @RestController
 @RequestMapping("/bank")
+@AllArgsConstructor
 public class BankController {
 
-    @Autowired
     private BankService bankService;
 
     @GetMapping("/list")
@@ -35,7 +35,7 @@
     }
 
     @PostMapping("/add")
-    @ApiOperation("鏂板閾惰绠$悊琛�")
+    @Operation(summary = "鏂板閾惰绠$悊琛�")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "閾惰绠$悊琛�", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody Bank bank) {
@@ -43,7 +43,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("鏇存柊閾惰绠$悊琛�")
+    @Operation(summary = "鏇存柊閾惰绠$悊琛�")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "閾惰绠$悊琛�", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody Bank bank) {
@@ -51,7 +51,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎閾惰绠$悊琛�")
+    @Operation(summary = "鍒犻櫎閾惰绠$悊琛�")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "閾惰绠$悊琛�", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
diff --git a/src/main/java/com/ruoyi/staff/controller/HolidayApplicationController.java b/src/main/java/com/ruoyi/staff/controller/HolidayApplicationController.java
index 66f1710..6498ef9 100644
--- a/src/main/java/com/ruoyi/staff/controller/HolidayApplicationController.java
+++ b/src/main/java/com/ruoyi/staff/controller/HolidayApplicationController.java
@@ -4,13 +4,14 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.staff.pojo.HolidayApplication;
 import com.ruoyi.staff.service.HolidayApplicationService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 @RestController
 @RequestMapping("/staff/holidayApplication")
+@AllArgsConstructor
 public class HolidayApplicationController {
-    @Autowired
+
     private HolidayApplicationService holidayApplicationService;
     /**
      * 璇峰亣鐢宠鍒嗛〉鏌ヨ
diff --git a/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceLocationConfigController.java b/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceLocationConfigController.java
index 5adf10f..7b4ba61 100644
--- a/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceLocationConfigController.java
+++ b/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceLocationConfigController.java
@@ -1,16 +1,12 @@
 package com.ruoyi.staff.controller;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.framework.web.domain.R;
-import com.ruoyi.staff.dto.PersonalAttendanceRecordsDto;
 import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig;
-import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
 import com.ruoyi.staff.service.PersonalAttendanceLocationConfigService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -25,32 +21,32 @@
  */
 @RestController
 @RequestMapping("/personalAttendanceLocationConfig")
-@Api(tags = "浜哄憳鎵撳崱瑙勫垯閰嶇疆")
+@Tag(name = "浜哄憳鎵撳崱瑙勫垯閰嶇疆")
+@RequiredArgsConstructor
 public class PersonalAttendanceLocationConfigController {
 
-    @Autowired
-    private PersonalAttendanceLocationConfigService personalAttendanceLocationConfigService;
+    private final PersonalAttendanceLocationConfigService personalAttendanceLocationConfigService;
 
-    @ApiOperation("鏂板/淇敼浜哄憳鎵撳崱瑙勫垯閰嶇疆")
+    @Operation(summary = "鏂板/淇敼浜哄憳鎵撳崱瑙勫垯閰嶇疆")
     @PostMapping("/add")
     public R add(@RequestBody PersonalAttendanceLocationConfig personalAttendanceLocationConfig){
 
 
         // 鐝闇�瑕佷笉鑳藉閲嶅
-        if (personalAttendanceLocationConfigService.lambdaQuery().eq(PersonalAttendanceLocationConfig::getShift, personalAttendanceLocationConfig.getShift()).one() != null) {
+        if (personalAttendanceLocationConfig.getId() == null && personalAttendanceLocationConfigService.lambdaQuery().eq(PersonalAttendanceLocationConfig::getShift, personalAttendanceLocationConfig.getShift()).one() != null) {
             return R.fail("鐝涓嶈兘閲嶅");
         }
         return R.ok(personalAttendanceLocationConfigService.saveOrUpdate(personalAttendanceLocationConfig));
     }
 
-    @ApiOperation("鍒嗛〉鏌ヨ浜哄憳鎵撳崱瑙勫垯閰嶇疆")
+    @Operation(summary = "鍒嗛〉鏌ヨ浜哄憳鎵撳崱瑙勫垯閰嶇疆")
     @GetMapping("/listPage")
     public R listPage(Page page){
         return R.ok(personalAttendanceLocationConfigService.page(page));
     }
 
 
-    @ApiOperation("鍒犻櫎浜哄憳鎵撳崱瑙勫垯閰嶇疆")
+    @Operation(summary = "鍒犻櫎浜哄憳鎵撳崱瑙勫垯閰嶇疆")
     @DeleteMapping("/del")
     public R del(@RequestBody List<Integer> ids) {
         return R.ok(personalAttendanceLocationConfigService.removeBatchByIds(ids));
diff --git a/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java b/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java
index d6a8ce3..37902fa 100644
--- a/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java
+++ b/src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java
@@ -5,12 +5,12 @@
 import com.ruoyi.staff.dto.PersonalAttendanceRecordsDto;
 import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
 import com.ruoyi.staff.service.PersonalAttendanceRecordsService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * <p>
@@ -22,30 +22,30 @@
  */
 @RestController
 @RequestMapping("/personalAttendanceRecords")
-@Api(tags = "浜哄憳鎵撳崱绛惧埌")
+@Tag(name = "浜哄憳鎵撳崱绛惧埌")
 public class PersonalAttendanceRecordsController {
     @Resource
     private PersonalAttendanceRecordsService personalAttendanceRecordsService;
 
-    @ApiOperation("鏂板鎵撳崱绛惧埌")
+    @Operation(summary = "鏂板鎵撳崱绛惧埌")
     @PostMapping("")
     public AjaxResult add(@RequestBody PersonalAttendanceRecordsDto personalAttendanceRecordsDto){
         return AjaxResult.success(personalAttendanceRecordsService.add(personalAttendanceRecordsDto));
     }
 
-    @ApiOperation("鍒嗛〉鏌ヨ鎵撳崱绛惧埌")
+    @Operation(summary = "鍒嗛〉鏌ヨ鎵撳崱绛惧埌")
     @GetMapping("/listPage")
     public AjaxResult listPage(Page page, PersonalAttendanceRecordsDto personalAttendanceRecordsDto){
         return AjaxResult.success(personalAttendanceRecordsService.listPage(page, personalAttendanceRecordsDto));
     }
 
-    @ApiOperation("鑾峰彇褰撳墠浜虹殑鑰冨嫟鐩稿叧鏁版嵁")
+    @Operation(summary = "鑾峰彇褰撳墠浜虹殑鑰冨嫟鐩稿叧鏁版嵁")
     @GetMapping("/today")
     public AjaxResult todayInfo(PersonalAttendanceRecordsDto personalAttendanceRecordsDto){
         return AjaxResult.success(personalAttendanceRecordsService.todayInfo(personalAttendanceRecordsDto));
     }
 
-    @ApiOperation("瀵煎嚭鎵撳崱绛惧埌")
+    @Operation(summary = "瀵煎嚭鎵撳崱绛惧埌")
     @PostMapping("/export")
     public void export(HttpServletResponse response, PersonalAttendanceRecordsDto personalAttendanceRecordsDto) {
         personalAttendanceRecordsService.export(response, personalAttendanceRecordsDto);
diff --git a/src/main/java/com/ruoyi/staff/controller/PersonalShiftController.java b/src/main/java/com/ruoyi/staff/controller/PersonalShiftController.java
index 85ff013..2f1496b 100644
--- a/src/main/java/com/ruoyi/staff/controller/PersonalShiftController.java
+++ b/src/main/java/com/ruoyi/staff/controller/PersonalShiftController.java
@@ -12,13 +12,15 @@
 import com.ruoyi.staff.service.PersonalShiftService;
 import com.ruoyi.staff.utils.StyleMonthUtils;
 import com.ruoyi.staff.utils.StyleYearUtils;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.constraints.NotNull;
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotNull;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -33,65 +35,76 @@
  */
 @RestController
 @RequestMapping("/personalShift")
-@Api(tags = "浜哄憳鎺掔彮")
+@Tag(name = "浜哄憳鎺掔彮")
+@AllArgsConstructor
 public class PersonalShiftController {
 
-    @Autowired
     private PersonalShiftService personalShiftService;
 
-    @ApiOperation("浜哄憳鎺掔彮")
+    @Operation(summary = "浜哄憳鎺掔彮")
     @PostMapping("/add")
     public R add(@RequestBody PerformanceShiftAddDto performanceShiftAddDto){
         return R.ok(personalShiftService.performanceShiftAdd(performanceShiftAddDto));
     }
 
-    @ApiOperation(value = "鏈堜唤鍒嗛〉鏌ヨ")
+    @Operation(summary = "鏈堜唤鍒嗛〉鏌ヨ")
     @GetMapping("page")
     public R performanceShiftPage(Integer size, Integer current, String time, String userName, Integer sysDeptId) {
         return R.ok(personalShiftService.performanceShiftPage(new Page<>(current, size), time, userName, sysDeptId));
     }
 
-    @ApiOperation(value = "骞翠唤鍒嗛〉鏌ヨ")
+    @Operation(summary = "骞翠唤鍒嗛〉鏌ヨ")
     @GetMapping("pageYear")
     public R performanceShiftPageYear(Integer size, Integer current, String time, String userName, Integer sysDeptId) {
         return R.ok(personalShiftService.performanceShiftPageYear(new Page<>(current, size), time, userName, sysDeptId));
     }
 
-    @ApiOperation(value = "鐝鐘舵�佷慨鏀�")
+    @Operation(summary = "鐝鐘舵�佷慨鏀�")
     @PostMapping("update")
     public R performanceShiftUpdate(@RequestBody PersonalShift personalShift) {
         personalShiftService.performanceShiftUpdate(personalShift);
         return R.ok();
     }
 
-    @ApiOperation(value = "瀵煎嚭")
+    @Operation(summary = "瀵煎嚭")
     @GetMapping("export")
     public void exportToExcel(@NotNull(message = "鏃堕棿涓嶈兘涓虹┖锛�") String time, String userName, Integer sysDeptId, Boolean isMonth, HttpServletResponse response) throws Exception {
-        Map<Object, Object> data;
+        ServletOutputStream out = response.getOutputStream();
         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-        response.setHeader("requestType","excel");
-        response.setHeader("Access-Control-Expose-Headers", "requestType");
+        response.setCharacterEncoding("utf-8");
+        response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + time + ".xlsx");
+
         if (!isMonth) {
-            data = personalShiftService.exportToYearExcel(time, userName, sysDeptId);
-            // 璁剧疆鍗曞厓鏍兼牱寮�
-            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(StyleYearUtils.getHeadStyle(), StyleYearUtils.getContentStyle());
-            // 淇濆瓨鍒扮涓�涓猻heet涓�
-            EasyExcel.write(response.getOutputStream())
+            Map<Object, Object> data = personalShiftService.exportToYearExcel(time, userName, sysDeptId);
+
+            HorizontalCellStyleStrategy style = new HorizontalCellStyleStrategy(
+                    StyleYearUtils.getHeadStyle(),
+                    StyleYearUtils.getContentStyle()
+            );
+
+            EasyExcel.write(out)
                     .head((List<List<String>>) data.get("header"))
-                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 鑷�傚簲鍒楀
-                    .registerWriteHandler(horizontalCellStyleStrategy)
+                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+                    .registerWriteHandler(style)
                     .sheet("骞村害")
                     .doWrite((Collection<?>) data.get("data"));
+
         } else {
-            data = personalShiftService.exportToMonthExcel(time, userName, sysDeptId);
-            // 璁剧疆鍗曞厓鏍兼牱寮�
-            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(StyleMonthUtils.getHeadStyle(), StyleMonthUtils.getContentStyle());
-            EasyExcel.write(response.getOutputStream())
+            Map<Object, Object> data = personalShiftService.exportToMonthExcel(time, userName, sysDeptId);
+
+            HorizontalCellStyleStrategy style = new HorizontalCellStyleStrategy(
+                    StyleMonthUtils.getHeadStyle(),
+                    StyleMonthUtils.getContentStyle()
+            );
+
+            EasyExcel.write(out)
                     .head((List<List<String>>) data.get("header"))
-                    .registerWriteHandler(horizontalCellStyleStrategy)
+                    .registerWriteHandler(style)
                     .sheet("鏈堝害")
                     .doWrite((Collection<?>) data.get("data"));
         }
+
+        out.flush();
     }
 
 
diff --git a/src/main/java/com/ruoyi/staff/controller/SchemeApplicableStaffController.java b/src/main/java/com/ruoyi/staff/controller/SchemeApplicableStaffController.java
index 39f1ef0..fd97213 100644
--- a/src/main/java/com/ruoyi/staff/controller/SchemeApplicableStaffController.java
+++ b/src/main/java/com/ruoyi/staff/controller/SchemeApplicableStaffController.java
@@ -1,16 +1,15 @@
 package com.ruoyi.staff.controller;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.staff.pojo.SchemeApplicableStaff;
 import com.ruoyi.staff.service.SchemeApplicableStaffService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -24,24 +23,23 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-03-05 11:50:17
  */
-@Api(tags = "绀句繚鏂规閫傜敤浜哄憳琛�")
+@Tag(name = "绀句繚鏂规閫傜敤浜哄憳琛�")
 @RestController
 @RequestMapping("/schemeApplicableStaff")
+@AllArgsConstructor
 public class SchemeApplicableStaffController extends BaseController {
 
-
-    @Autowired
     private SchemeApplicableStaffService schemeApplicableStaffService;
 
 
     @GetMapping("/listPage")
-    @ApiOperation(value = "鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, SchemeApplicableStaff schemeApplicableStaff) {
         return schemeApplicableStaffService.listPage(page,schemeApplicableStaff);
     }
 
     @PostMapping("/add")
-    @ApiOperation(value = "娣诲姞")
+    @Operation(summary = "娣诲姞")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "绀句繚鏂规閫傜敤浜哄憳琛�", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody SchemeApplicableStaff schemeApplicableStaff) {
@@ -49,7 +47,7 @@
     }
 
     @PostMapping("/updateSchemeApplicableStaff")
-    @ApiOperation(value = "淇敼")
+    @Operation(summary = "淇敼")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "绀句繚鏂规閫傜敤浜哄憳琛�", businessType = BusinessType.UPDATE)
     public AjaxResult updateSchemeApplicableStaff(@RequestBody SchemeApplicableStaff schemeApplicableStaff) {
@@ -57,7 +55,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation(value = "鍒犻櫎")
+    @Operation(summary = "鍒犻櫎")
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "绀句繚鏂规閫傜敤浜哄憳琛�", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffContractController.java b/src/main/java/com/ruoyi/staff/controller/StaffContractController.java
index af4c90c..17cdaf6 100644
--- a/src/main/java/com/ruoyi/staff/controller/StaffContractController.java
+++ b/src/main/java/com/ruoyi/staff/controller/StaffContractController.java
@@ -4,17 +4,17 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.staff.pojo.StaffContract;
 import com.ruoyi.staff.service.StaffContractService;
-import io.swagger.annotations.Api;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 
 /**
  * 鍛樺伐鍙拌处/鍚堝悓绠$悊
  */
 @RestController
 @RequestMapping("/staff/staffContract")
-@Api(tags = "鍛樺伐鍙拌处/鍚堝悓绠$悊")
+@Tag(name = "鍛樺伐鍙拌处/鍚堝悓绠$悊")
 public class StaffContractController {
 
     @Resource
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffLeaveController.java b/src/main/java/com/ruoyi/staff/controller/StaffLeaveController.java
index c018008..64a35d9 100644
--- a/src/main/java/com/ruoyi/staff/controller/StaffLeaveController.java
+++ b/src/main/java/com/ruoyi/staff/controller/StaffLeaveController.java
@@ -4,12 +4,12 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.staff.dto.StaffLeaveDto;
 import com.ruoyi.staff.service.StaffLeaveService;
-import io.swagger.annotations.Api;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -17,7 +17,7 @@
  */
 @RestController
 @RequestMapping("/staff/staffLeave")
-@Api(tags = "鍛樺伐绂昏亴")
+@Tag(name = "鍛樺伐绂昏亴")
 public class StaffLeaveController {
     @Resource
     private StaffLeaveService staffLeaveService;
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java b/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java
index 8e3d6b6..3378f80 100644
--- a/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java
+++ b/src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java
@@ -1,6 +1,7 @@
 package com.ruoyi.staff.controller;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.domain.AjaxResult;
@@ -8,15 +9,16 @@
 import com.ruoyi.staff.pojo.StaffContract;
 import com.ruoyi.staff.pojo.StaffOnJob;
 import com.ruoyi.staff.service.IStaffOnJobService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.staff.dto.StaffOnJobExcelDto;
 
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
 import java.util.List;
 
 /**
@@ -24,7 +26,7 @@
  */
 @RestController
 @RequestMapping("/staff/staffOnJob")
-@Api(tags = "鍛樺伐鍙拌处")
+@Tag(name = "鍛樺伐鍙拌处")
 public class StaffOnJobController {
 
     @Resource
@@ -105,6 +107,13 @@
         return AjaxResult.success(staffOnJobService.renewContract(id, staffContract));
     }
 
+    @Operation(summary = "涓嬭浇妯℃澘")
+    @PostMapping("/downloadTemplate")
+    public void downloadTemplate(HttpServletResponse response) {
+        ExcelUtil<StaffOnJobExcelDto> util = new ExcelUtil<>(StaffOnJobExcelDto.class);
+        util.importTemplateExcel(response, "鍦ㄨ亴鍛樺伐妯℃澘");
+    }
+
     /**
      * 鍦ㄨ亴鍛樺伐瀵煎叆
      */
@@ -134,7 +143,7 @@
      * @param staffOnJob
      */
     @PostMapping("/exportCopy")
-    @ApiOperation("word妯℃澘鍚堝悓鍦ㄨ亴鍛樺伐瀵煎嚭")
+    @Operation(summary = "word妯℃澘鍚堝悓鍦ㄨ亴鍛樺伐瀵煎嚭")
     public AjaxResult exportCopy(HttpServletResponse response,@RequestBody StaffOnJob staffOnJob) throws Exception{
        return AjaxResult.success(staffOnJobService.exportCopy(response, staffOnJob));
     }
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java b/src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java
index ad43b6c..569ca1c 100644
--- a/src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java
+++ b/src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java
@@ -7,10 +7,9 @@
 import com.ruoyi.staff.dto.CalculateSalaryDto;
 import com.ruoyi.staff.pojo.StaffSalaryMain;
 import com.ruoyi.staff.service.StaffSalaryMainService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.aspectj.weaver.loadtime.Aj;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -24,28 +23,28 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-03-06 01:22:05
  */
-@Api(tags = "鍛樺伐宸ヨ祫涓昏〃")
+@Tag(name = "鍛樺伐宸ヨ祫涓昏〃")
 @RestController
 @RequestMapping("/staffSalaryMain")
+@AllArgsConstructor
 public class StaffSalaryMainController {
 
-    @Autowired
     private StaffSalaryMainService staffSalaryMainService;
 
     @GetMapping("/listPage")
-    @ApiOperation("鍛樺伐宸ヨ祫涓昏〃鍒嗛〉鏌ヨ")
+    @Operation(summary = "鍛樺伐宸ヨ祫涓昏〃鍒嗛〉鏌ヨ")
     public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) {
         return staffSalaryMainService.listPage(page, staffSalaryMain);
     }
 
-    @ApiOperation("閫氳繃閮ㄩ棬ids鑾峰彇鐢ㄦ埛淇℃伅璁$畻姣忎釜鍛樺伐鐨勫伐璧�")
+    @Operation(summary = "閫氳繃閮ㄩ棬ids鑾峰彇鐢ㄦ埛淇℃伅璁$畻姣忎釜鍛樺伐鐨勫伐璧�")
     @PostMapping("/calculateSalary")
     public AjaxResult calculateSalary(@RequestBody CalculateSalaryDto calculateSalaryDto) {
         return staffSalaryMainService.calculateSalary(calculateSalaryDto);
     }
 
     @PostMapping("/add")
-    @ApiOperation("鏂板缓宸ヨ祫琛�")
+    @Operation(summary = "鏂板缓宸ヨ祫琛�")
     @Log(title = "鏂板缓宸ヨ祫琛�", businessType = BusinessType.INSERT)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult add(@RequestBody StaffSalaryMain staffSalaryMain) {
@@ -53,7 +52,7 @@
     }
 
     @PostMapping("/update")
-    @ApiOperation("淇敼宸ヨ祫琛�")
+    @Operation(summary = "淇敼宸ヨ祫琛�")
     @Log(title = "淇敼宸ヨ祫琛�", businessType = BusinessType.UPDATE)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult updateStaffSalaryMain(@RequestBody StaffSalaryMain staffSalaryMain) {
@@ -61,7 +60,7 @@
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("鍒犻櫎宸ヨ祫琛�")
+    @Operation(summary = "鍒犻櫎宸ヨ祫琛�")
     @Log(title = "鍒犻櫎宸ヨ祫琛�", businessType = BusinessType.DELETE)
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult delete(@RequestBody List<Long> ids) {
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffSchedulingController.java b/src/main/java/com/ruoyi/staff/controller/StaffSchedulingController.java
index a54096a..d195e9c 100644
--- a/src/main/java/com/ruoyi/staff/controller/StaffSchedulingController.java
+++ b/src/main/java/com/ruoyi/staff/controller/StaffSchedulingController.java
@@ -14,7 +14,7 @@
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/staff/dto/PerformanceShiftAddDto.java b/src/main/java/com/ruoyi/staff/dto/PerformanceShiftAddDto.java
index d7aff73..c5cda4e 100644
--- a/src/main/java/com/ruoyi/staff/dto/PerformanceShiftAddDto.java
+++ b/src/main/java/com/ruoyi/staff/dto/PerformanceShiftAddDto.java
@@ -1,32 +1,32 @@
 package com.ruoyi.staff.dto;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 
 @Data
 public class PerformanceShiftAddDto {
 
     @NotNull(message = "璇烽�夋嫨鐝")
-    @ApiModelProperty("鐝")
+    @Schema(description = "鐝")
     private Integer personalAttendanceLocationConfigId;
 
     @NotNull(message = "璇烽�夋嫨鍛樺伐")
-    @ApiModelProperty("鍛樺伐id")
+    @Schema(description = "鍛樺伐id")
     private String staffOnJobId;
 
     @NotNull(message = "璇烽�夋嫨鍛ㄦ")
-    @ApiModelProperty("寮�濮嬪懆娆�")
+    @Schema(description = "寮�濮嬪懆娆�")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime startWeek;
 
     @NotNull(message = "璇烽�夋嫨鍛ㄦ")
-    @ApiModelProperty("缁撴潫鍛ㄦ")
+    @Schema(description = "缁撴潫鍛ㄦ")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime endWeek;
diff --git a/src/main/java/com/ruoyi/staff/dto/PersonalAttendanceRecordsDto.java b/src/main/java/com/ruoyi/staff/dto/PersonalAttendanceRecordsDto.java
index ccb9da4..dba3ca4 100644
--- a/src/main/java/com/ruoyi/staff/dto/PersonalAttendanceRecordsDto.java
+++ b/src/main/java/com/ruoyi/staff/dto/PersonalAttendanceRecordsDto.java
@@ -4,7 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
diff --git a/src/main/java/com/ruoyi/staff/dto/SaveStaffSchedulingDto.java b/src/main/java/com/ruoyi/staff/dto/SaveStaffSchedulingDto.java
index 7e57745..860a4dd 100644
--- a/src/main/java/com/ruoyi/staff/dto/SaveStaffSchedulingDto.java
+++ b/src/main/java/com/ruoyi/staff/dto/SaveStaffSchedulingDto.java
@@ -6,7 +6,7 @@
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
 import java.io.Serializable;
 import java.time.LocalDateTime;
 import java.util.Date;
diff --git a/src/main/java/com/ruoyi/staff/dto/StaffOnJobExcelDto.java b/src/main/java/com/ruoyi/staff/dto/StaffOnJobExcelDto.java
new file mode 100644
index 0000000..285c4f2
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/dto/StaffOnJobExcelDto.java
@@ -0,0 +1,87 @@
+package com.ruoyi.staff.dto;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import com.ruoyi.staff.pojo.StaffEducation;
+import com.ruoyi.staff.pojo.StaffEmergencyContact;
+import com.ruoyi.staff.pojo.StaffWorkExperience;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class StaffOnJobExcelDto {
+
+    /**
+     * 鐘舵��(0:绂昏亴;1:鍦ㄨ亴)
+     */
+    private Integer staffState = 1;
+
+
+    /**
+     * 鍛樺伐缂栧彿
+     */
+    @Excel(name = "鍛樺伐缂栧彿", cellType = Excel.ColumnType.STRING, sort = 2,prompt = "鐢ㄦ埛鐧诲綍鍚�")
+    private String staffNo;
+
+    /**
+     * 鍛樺伐濮撳悕
+     */
+    @Excel(name = "鍛樺伐濮撳悕", sort = 3,prompt = "鐢ㄦ埛鏄电О")
+    private String staffName;
+
+    /**
+     * 鎬у埆
+     */
+    @Excel(name = "鎬у埆", sort = 4)
+    private String sex;
+
+    /**
+     * 閮ㄩ棬鍚嶇О
+     */
+    @Excel(name = "閮ㄩ棬鍚嶇О", sort = 5,prompt = "璇峰墠寰�绯荤粺鏌ョ湅鏈夊摢浜涢儴闂ㄥ彲浠ョ粦瀹氾紝涓ユ牸鎸夌収閮ㄩ棬鍚嶇О缁戝畾")
+    private String sysDeptName;
+
+    /**
+     * 瑙掕壊
+     */
+    @Excel(name = "瑙掕壊", sort = 6,prompt = "璇峰墠寰�绯荤粺鏌ョ湅鏈夊摢浜涜鑹插彲浠ョ粦瀹氾紝涓ユ牸鎸夌収瑙掕壊鍚嶇О缁戝畾")
+    private String roleName;
+
+
+    /**
+     * 鎵嬫満
+     */
+    @Excel(name = "鎵嬫満", sort = 13)
+    private String phone;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Schema(description = "鍚堝悓寮�濮嬫椂闂�")
+    @Excel(name = "鍚堝悓寮�濮嬫棩鏈�", width = 30, dateFormat = "yyyy-MM-dd", sort = 15)
+    private Date contractStartTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Schema(description = "鍚堝悓缁撴潫鏃堕棿")
+    @Excel(name = "鍚堝悓缁撴潫鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd", sort = 16)
+    private Date contractEndTime;
+
+    @Schema(description = "鍚堝悓鏈熼檺")
+    @Excel(name = "鍚堝悓鏈熼檺", sort = 17)
+    private String contractTerm;
+
+
+    @Schema(description = "鍑虹敓鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鍑虹敓鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd", sort = 18)
+    private Date birthDate;
+}
diff --git a/src/main/java/com/ruoyi/staff/pojo/Bank.java b/src/main/java/com/ruoyi/staff/pojo/Bank.java
index 482703b..70e20a3 100644
--- a/src/main/java/com/ruoyi/staff/pojo/Bank.java
+++ b/src/main/java/com/ruoyi/staff/pojo/Bank.java
@@ -1,11 +1,12 @@
 package com.ruoyi.staff.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -20,7 +21,7 @@
 @Getter
 @Setter
 @TableName("bank")
-@ApiModel(value = "Bank瀵硅薄", description = "閾惰绠$悊琛�")
+@Schema(name = "Bank瀵硅薄", description = "閾惰绠$悊琛�")
 public class Bank implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -28,6 +29,13 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("閾惰鍚嶇О")
+    @Schema(description = "閾惰鍚嶇О")
     private String bankName;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/HolidayApplication.java b/src/main/java/com/ruoyi/staff/pojo/HolidayApplication.java
index b76893e..9a5b54b 100644
--- a/src/main/java/com/ruoyi/staff/pojo/HolidayApplication.java
+++ b/src/main/java/com/ruoyi/staff/pojo/HolidayApplication.java
@@ -1,5 +1,6 @@
 package com.ruoyi.staff.pojo;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
@@ -55,4 +56,11 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceLocationConfig.java b/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceLocationConfig.java
index 647359e..13e0ca5 100644
--- a/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceLocationConfig.java
+++ b/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceLocationConfig.java
@@ -1,5 +1,7 @@
 package com.ruoyi.staff.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -8,8 +10,7 @@
 import java.time.LocalTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -25,7 +26,7 @@
 @Getter
 @Setter
 @TableName("personal_attendance_location_config")
-@ApiModel(value = "PersonalAttendanceLocationConfig瀵硅薄", description = "浜哄憳鎵撳崱瑙勫垯閰嶇疆")
+@Schema(name = "PersonalAttendanceLocationConfig瀵硅薄", description = "浜哄憳鎵撳崱瑙勫垯閰嶇疆")
 public class PersonalAttendanceLocationConfig implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -33,31 +34,38 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty("閮ㄩ棬id")
+    @Schema(description = "閮ㄩ棬id")
     private Integer sysDeptId;
 
-    @ApiModelProperty("鍦扮偣鍚嶇О")
+    @Schema(description = "鍦扮偣鍚嶇О")
     private String locationName;
 
-    @ApiModelProperty("缁忓害")
+    @Schema(description = "缁忓害")
     private Double longitude;
 
-    @ApiModelProperty("绾害")
+    @Schema(description = "绾害")
     private Double latitude;
 
-    @ApiModelProperty("鎵撳崱鑼冨洿")
+    @Schema(description = "鎵撳崱鑼冨洿")
     private Double radius;
 
-    @ApiModelProperty("涓婄彮鏃堕棿")
+    @Schema(description = "涓婄彮鏃堕棿")
     @JsonFormat(pattern = "HH:mm")
     @DateTimeFormat(pattern = "HH:mm")
     private LocalTime startAt;
 
-    @ApiModelProperty("涓嬬彮鏃堕棿")
+    @Schema(description = "涓嬬彮鏃堕棿")
     @JsonFormat(pattern = "HH:mm")
     @DateTimeFormat(pattern = "HH:mm")
     private LocalTime  endAt;
 
-    @ApiModelProperty("鐝")
+    @Schema(description = "鐝")
     private String shift;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceRecords.java b/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceRecords.java
index 8e64e0c..ac8177f 100644
--- a/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceRecords.java
+++ b/src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceRecords.java
@@ -12,8 +12,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -29,7 +28,7 @@
 @Getter
 @Setter
 @TableName("personal_attendance_records")
-@ApiModel(value = "PersonalAttendanceRecords瀵硅薄", description = "")
+@Schema(name = "PersonalAttendanceRecords瀵硅薄", description = "")
 public class PersonalAttendanceRecords implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -37,48 +36,55 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍛樺伐鍦ㄨ亴id")
+    @Schema(description = "鍛樺伐鍦ㄨ亴id")
     private Long staffOnJobId;
 
-    @ApiModelProperty("鏃ユ湡")
+    @Schema(description = "鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @Excel(name = "鏃ユ湡", sort = 1, dateFormat = "yyyy-MM-dd")
     private LocalDate date;
 
-    @ApiModelProperty("宸ヤ綔寮�濮嬫椂闂�")
+    @Schema(description = "宸ヤ綔寮�濮嬫椂闂�")
     @JsonFormat(pattern = "HH:mm")
     @DateTimeFormat(pattern = "HH:mm")
     @Excel(name = "涓婄彮鏃堕棿", sort = 5, dateFormat = "HH:mm")
     private LocalDateTime workStartAt;
 
-    @ApiModelProperty("宸ヤ綔缁撴潫鏃堕棿")
+    @Schema(description = "宸ヤ綔缁撴潫鏃堕棿")
     @JsonFormat(pattern = "HH:mm")
     @DateTimeFormat(pattern = "HH:mm")
     @Excel(name = "涓嬬彮鏃堕棿", sort = 6, dateFormat = "HH:mm")
     private LocalDateTime workEndAt;
 
-    @ApiModelProperty("宸ヤ綔鏃堕暱")
+    @Schema(description = "宸ヤ綔鏃堕暱")
     @Excel(name = "宸ユ椂(灏忔椂)", sort = 7)
     private BigDecimal workHours;
 
-    @ApiModelProperty("鐘舵�� 0姝e父 1杩熷埌 2鏃╅�� 3杩熷埌鏃╅�� 4缂哄嫟")
+    @Schema(description = "鐘舵�� 0姝e父 1杩熷埌 2鏃╅�� 3杩熷埌鏃╅�� 4缂哄嫟")
     @Excel(name = "鐘舵��", sort = 8,readConverterExp = "0=姝e父,1=杩熷埌,2=鏃╅��,3=杩熷埌銆佹棭閫�,4=缂哄嫟")
     private Integer status;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     @Excel(name = "澶囨敞", sort = 9)
     private String remark;
 
-    @ApiModelProperty("绉熸埛id")
+    @Schema(description = "绉熸埛id")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty("褰曞叆鏃堕棿")
+    @Schema(description = "褰曞叆鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/PersonalShift.java b/src/main/java/com/ruoyi/staff/pojo/PersonalShift.java
index 337ab96..67bcf7d 100644
--- a/src/main/java/com/ruoyi/staff/pojo/PersonalShift.java
+++ b/src/main/java/com/ruoyi/staff/pojo/PersonalShift.java
@@ -9,8 +9,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -26,7 +25,7 @@
 @Getter
 @Setter
 @TableName("personal_shift")
-@ApiModel(value = "PersonalShift瀵硅薄", description = "")
+@Schema(name = "PersonalShift瀵硅薄", description = "")
 public class PersonalShift implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -34,26 +33,33 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鐝(鎵撳崱瑙勫垯id)")
+    @Schema(description = "鐝(鎵撳崱瑙勫垯id)")
     private Integer personalAttendanceLocationConfigId;
 
-    @ApiModelProperty("鍛樺伐鍦ㄨ亴id")
+    @Schema(description = "鍛樺伐鍦ㄨ亴id")
     private Long staffOnJobId;
 
-    @ApiModelProperty("褰曞叆鏃堕棿")
+    @Schema(description = "褰曞叆鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鎺掔彮鏃ユ湡")
+    @Schema(description = "鎺掔彮鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime workTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/SchemeApplicableStaff.java b/src/main/java/com/ruoyi/staff/pojo/SchemeApplicableStaff.java
index e61df92..acc0e62 100644
--- a/src/main/java/com/ruoyi/staff/pojo/SchemeApplicableStaff.java
+++ b/src/main/java/com/ruoyi/staff/pojo/SchemeApplicableStaff.java
@@ -10,8 +10,7 @@
 import java.util.List;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -26,59 +25,62 @@
 @Getter
 @Setter
 @TableName("scheme_applicable_staff")
-@ApiModel(value = "SchemeApplicableStaff瀵硅薄", description = "绀句繚鏂规閫傜敤浜哄憳琛�")
+@Schema(name = "SchemeApplicableStaff瀵硅薄", description = "绀句繚鏂规閫傜敤浜哄憳琛�")
 public class SchemeApplicableStaff implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("绀句繚鏂规淇濋櫓绂忓埄鏄庣粏")
+    @Schema(description = "绀句繚鏂规淇濋櫓绂忓埄鏄庣粏")
     @TableField(exist = false)
     private List<SchemeInsuranceDetail> schemeInsuranceDetailList;
 
-    @ApiModelProperty("涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鏍囬")
+    @Schema(description = "鏍囬")
     private String title;
 
-    @ApiModelProperty("閮ㄩ棬ids,澶氫釜浣跨敤,闅斿紑")
+    @Schema(description = "閮ㄩ棬ids,澶氫釜浣跨敤,闅斿紑")
     private String deptIds;
 
-    @ApiModelProperty("閮ㄩ棬鍚嶇О,澶氫釜浣跨敤,闅斿紑")
+    @Schema(description = "閮ㄩ棬鍚嶇О,澶氫釜浣跨敤,闅斿紑")
     @TableField(exist = false)
     private String deptNames;
 
-    @ApiModelProperty("浜哄憳鍚嶇О,澶氫釜浣跨敤,闅斿紑")
+    @Schema(description = "浜哄憳鍚嶇О,澶氫釜浣跨敤,闅斿紑")
     private String staffNames;
 
-    @ApiModelProperty("浜哄憳id,澶氫釜浣跨敤,闅斿紑")
+    @Schema(description = "浜哄憳id,澶氫釜浣跨敤,闅斿紑")
     private String staffIds;
 
-    @ApiModelProperty("淇濋櫓绫诲瀷鍚嶇О澶氫釜浣跨敤,闅斿紑")
+    @Schema(description = "淇濋櫓绫诲瀷鍚嶇О澶氫釜浣跨敤,闅斿紑")
     private String insuranceTypes;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
     @TableField(exist = false)
-    @ApiModelProperty("鍒涘缓浜哄悕绉�")
+    @Schema(description = "鍒涘缓浜哄悕绉�")
     private String createUserName;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8", shape = JsonFormat.Shape.STRING)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/SchemeInsuranceDetail.java b/src/main/java/com/ruoyi/staff/pojo/SchemeInsuranceDetail.java
index 9facc7b..b9ce10d 100644
--- a/src/main/java/com/ruoyi/staff/pojo/SchemeInsuranceDetail.java
+++ b/src/main/java/com/ruoyi/staff/pojo/SchemeInsuranceDetail.java
@@ -8,8 +8,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -24,46 +23,49 @@
 @Getter
 @Setter
 @TableName("scheme_insurance_detail")
-@ApiModel(value = "SchemeInsuranceDetail瀵硅薄", description = "绀句繚鏂规淇濋櫓绂忓埄鏄庣粏琛�")
+@Schema(name = "SchemeInsuranceDetail瀵硅薄", description = "绀句繚鏂规淇濋櫓绂忓埄鏄庣粏琛�")
 public class SchemeInsuranceDetail implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("鏄庣粏ID锛堜富閿級")
+    @Schema(description = "鏄庣粏ID锛堜富閿級")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍏宠仈鐨勭ぞ淇濇柟妗圛D")
+    @Schema(description = "鍏宠仈鐨勭ぞ淇濇柟妗圛D")
     private Long schemeId;
 
-    @ApiModelProperty("淇濋櫓绫诲瀷锛堝鍖荤枟淇濋櫓銆佸吇鑰佷繚闄╃瓑锛�")
+    @Schema(description = "淇濋櫓绫诲瀷锛堝鍖荤枟淇濋櫓銆佸吇鑰佷繚闄╃瓑锛�")
     private String insuranceType;
 
-    @ApiModelProperty("缂磋垂鍩烘暟")
+    @Schema(description = "缂磋垂鍩烘暟")
     private BigDecimal paymentBase;
 
-    @ApiModelProperty("鏄惁璋冪敤鍩烘湰宸ヨ祫锛�1-鍚︼紝2-鏄�")
+    @Schema(description = "鏄惁璋冪敤鍩烘湰宸ヨ祫锛�1-鍚︼紝2-鏄�")
     private Integer useBasicSalary;
 
-    @ApiModelProperty("涓汉缂磋垂姣斾緥锛�%锛�")
+    @Schema(description = "涓汉缂磋垂姣斾緥锛�%锛�")
     private BigDecimal personalRatio;
 
-    @ApiModelProperty("涓汉鍥哄畾缂磋垂閲戦")
+    @Schema(description = "涓汉鍥哄畾缂磋垂閲戦")
     private BigDecimal personalFixed;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffContract.java b/src/main/java/com/ruoyi/staff/pojo/StaffContract.java
index 9b2afee..d5ea86b 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffContract.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffContract.java
@@ -5,7 +5,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -16,34 +16,41 @@
 @Data
 public class StaffContract {
 
-    @ApiModelProperty(value = "搴忓彿")
+    @Schema(description = "搴忓彿")
     private Long id;
 
-    @ApiModelProperty(value = "鍦ㄨ亴鍛樺伐ID")
+    @Schema(description = "鍦ㄨ亴鍛樺伐ID")
     private Long staffOnJobId;
 
-    @ApiModelProperty(value = "鍚堝悓鏈熼檺")
+    @Schema(description = "鍚堝悓鏈熼檺")
     private String contractTerm;
 
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "鍚堝悓寮�濮嬫椂闂�")
+    @Schema(description = "鍚堝悓寮�濮嬫椂闂�")
     private Date contractStartTime;
 
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
-    @ApiModelProperty(value = "鍚堝悓缁撴潫鏃堕棿")
+    @Schema(description = "鍚堝悓缁撴潫鏃堕棿")
     private Date contractEndTime;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.UPDATE)
     private LocalDateTime updateTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffEducation.java b/src/main/java/com/ruoyi/staff/pojo/StaffEducation.java
index 8f7a35e..5bfd039 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffEducation.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffEducation.java
@@ -10,8 +10,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -27,53 +26,56 @@
 @Getter
 @Setter
 @TableName("staff_education")
-@ApiModel(value = "StaffEducation瀵硅薄", description = "鍛樺伐鏁欒偛缁忓巻琛�")
+@Schema(name = "StaffEducation瀵硅薄", description = "鍛樺伐鏁欒偛缁忓巻琛�")
 public class StaffEducation implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍏宠仈staff_on_job琛ㄤ富閿甀D")
+    @Schema(description = "鍏宠仈staff_on_job琛ㄤ富閿甀D")
     private Long staffOnJobId;
 
-    @ApiModelProperty("瀛﹀巻")
+    @Schema(description = "瀛﹀巻")
     private String education;
 
-    @ApiModelProperty("姣曚笟闄㈡牎")
+    @Schema(description = "姣曚笟闄㈡牎")
     private String schoolName;
 
-    @ApiModelProperty("鍏ュ鏃堕棿")
+    @Schema(description = "鍏ュ鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate enrollTime;
 
-    @ApiModelProperty("姣曚笟鏃堕棿")
+    @Schema(description = "姣曚笟鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate graduateTime;
 
-    @ApiModelProperty("涓撲笟")
+    @Schema(description = "涓撲笟")
     private String major;
 
-    @ApiModelProperty("瀛︿綅")
+    @Schema(description = "瀛︿綅")
     private String degree;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffEmergencyContact.java b/src/main/java/com/ruoyi/staff/pojo/StaffEmergencyContact.java
index 1fdeefa..183c9be 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffEmergencyContact.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffEmergencyContact.java
@@ -7,8 +7,7 @@
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,43 +22,46 @@
 @Getter
 @Setter
 @TableName("staff_emergency_contact")
-@ApiModel(value = "StaffEmergencyContact瀵硅薄", description = "鍛樺伐绱ф�ヨ仈绯讳汉琛�")
+@Schema(name = "StaffEmergencyContact瀵硅薄", description = "鍛樺伐绱ф�ヨ仈绯讳汉琛�")
 public class StaffEmergencyContact implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍏宠仈staff_on_job琛ㄤ富閿甀D")
+    @Schema(description = "鍏宠仈staff_on_job琛ㄤ富閿甀D")
     private Long staffOnJobId;
 
-    @ApiModelProperty("绱ф�ヨ仈绯讳汉濮撳悕")
+    @Schema(description = "绱ф�ヨ仈绯讳汉濮撳悕")
     private String contactName;
 
-    @ApiModelProperty("绱ф�ヨ仈绯讳汉鍏崇郴")
+    @Schema(description = "绱ф�ヨ仈绯讳汉鍏崇郴")
     private String contactRelation;
 
-    @ApiModelProperty("绱ф�ヨ仈绯讳汉鎵嬫満")
+    @Schema(description = "绱ф�ヨ仈绯讳汉鎵嬫満")
     private String contactPhone;
 
-    @ApiModelProperty("绱ф�ヨ仈绯讳汉浣忓潃")
+    @Schema(description = "绱ф�ヨ仈绯讳汉浣忓潃")
     private String contactAddress;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffLeave.java b/src/main/java/com/ruoyi/staff/pojo/StaffLeave.java
index 188081b..6de265c 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffLeave.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffLeave.java
@@ -4,7 +4,7 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -16,32 +16,39 @@
 @Data
 public class StaffLeave {
 
-    @ApiModelProperty(value = "搴忓彿")
+    @Schema(description = "搴忓彿")
     private Long id;
 
-    @ApiModelProperty(value = "鍦ㄨ亴鍛樺伐ID")
+    @Schema(description = "鍦ㄨ亴鍛樺伐ID")
     private Long staffOnJobId;
 
-    @ApiModelProperty(value = "绂昏亴鍘熷洜")
+    @Schema(description = "绂昏亴鍘熷洜")
     private String reason;
 
-    @ApiModelProperty(value = "绂昏亴澶囨敞")
+    @Schema(description = "绂昏亴澶囨敞")
     private String remark;
 
-    @ApiModelProperty(value = "绂昏亴鏃ユ湡")
+    @Schema(description = "绂昏亴鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8",shape = JsonFormat.Shape.STRING)
     private LocalDate leaveDate;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",shape = JsonFormat.Shape.STRING)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.UPDATE)
     private LocalDateTime updateTime;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffOnJob.java b/src/main/java/com/ruoyi/staff/pojo/StaffOnJob.java
index cca0284..bff864a 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffOnJob.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffOnJob.java
@@ -4,7 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -185,66 +185,69 @@
     private String remark;
 
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
-    @ApiModelProperty(value = "鍒悕")
+    @Schema(description = "鍒悕")
     private String alias;
 
-    @ApiModelProperty(value = "鍑虹敓鏃ユ湡")
+    @Schema(description = "鍑虹敓鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date birthDate;
 
-    @ApiModelProperty(value = "姘戞棌")
+    @Schema(description = "姘戞棌")
     private String nation;
 
-    @ApiModelProperty(value = "濠氬Щ鐘跺喌")
+    @Schema(description = "濠氬Щ鐘跺喌")
     private String maritalStatus;
 
-    @ApiModelProperty(value = "璇曠敤鏈燂紙鏈堬級")
+    @Schema(description = "璇曠敤鏈燂紙鏈堬級")
     private Integer proTerm;
 
-    @ApiModelProperty(value = "杞鏃ユ湡")
+    @Schema(description = "杞鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date positiveDate;
 
-    @ApiModelProperty(value = "鍩烘湰宸ヨ祫")
+    @Schema(description = "鍩烘湰宸ヨ祫")
     private BigDecimal basicSalary;
 
-    @ApiModelProperty(value = "鍛樺伐鏁欒偛缁忓巻闆嗗悎")
+    @Schema(description = "鍛樺伐鏁欒偛缁忓巻闆嗗悎")
     @TableField(exist = false)
     private List<StaffEducation> staffEducationList;
 
-    @ApiModelProperty(value = "鍛樺伐宸ヤ綔缁忓巻闆嗗悎")
+    @Schema(description = "鍛樺伐宸ヤ綔缁忓巻闆嗗悎")
     @TableField(exist = false)
     private List<StaffWorkExperience> staffWorkExperienceList;
 
-    @ApiModelProperty(value = "鍛樺伐绱ф�ヨ仈绯讳汉闆嗗悎")
+    @Schema(description = "鍛樺伐绱ф�ヨ仈绯讳汉闆嗗悎")
     @TableField(exist = false)
     private List<StaffEmergencyContact> staffEmergencyContactList;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java
index 1ab10ab..6cbe396 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java
@@ -8,8 +8,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -24,79 +23,82 @@
 @Getter
 @Setter
 @TableName("staff_salary_detail")
-@ApiModel(value = "StaffSalaryDetail瀵硅薄", description = "鍛樺伐宸ヨ祫鏄庣粏琛�")
+@Schema(name = "StaffSalaryDetail瀵硅薄", description = "鍛樺伐宸ヨ祫鏄庣粏琛�")
 public class StaffSalaryDetail implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍏宠仈宸ヨ祫涓昏〃ID")
+    @Schema(description = "鍏宠仈宸ヨ祫涓昏〃ID")
     private Long mainId;
 
-    @ApiModelProperty("鍏宠仈staff_on_job琛ㄤ富閿甀D")
+    @Schema(description = "鍏宠仈staff_on_job琛ㄤ富閿甀D")
     private Long staffOnJobId;
 
-    @ApiModelProperty("鍛樺伐濮撳悕")
+    @Schema(description = "鍛樺伐濮撳悕")
     private String staffName;
 
-    @ApiModelProperty("鑱屼綅鍚嶇О")
+    @Schema(description = "鑱屼綅鍚嶇О")
     private String postName;
 
-    @ApiModelProperty("閮ㄩ棬鍚嶇О")
+    @Schema(description = "閮ㄩ棬鍚嶇О")
     private String deptName;
 
-    @ApiModelProperty("鍩烘湰宸ヨ祫")
+    @Schema(description = "鍩烘湰宸ヨ祫")
     private BigDecimal basicSalary;
 
-    @ApiModelProperty("璁′欢宸ヨ祫")
+    @Schema(description = "璁′欢宸ヨ祫")
     private BigDecimal pieceSalary;
 
-    @ApiModelProperty("璁℃椂宸ヨ祫")
+    @Schema(description = "璁℃椂宸ヨ祫")
     private BigDecimal hourlySalary;
 
-    @ApiModelProperty("鍏朵粬鏀跺叆")
+    @Schema(description = "鍏朵粬鏀跺叆")
     private BigDecimal otherIncome;
 
-    @ApiModelProperty("绀句繚涓汉")
+    @Schema(description = "绀句繚涓汉")
     private BigDecimal socialPersonal;
 
-    @ApiModelProperty("鍏Н閲戜釜浜�")
+    @Schema(description = "鍏Н閲戜釜浜�")
     private BigDecimal fundPersonal;
 
-    @ApiModelProperty("鍏朵粬鏀嚭")
+    @Schema(description = "鍏朵粬鏀嚭")
     private BigDecimal otherDeduct;
 
-    @ApiModelProperty("宸ヨ祫涓◣")
+    @Schema(description = "宸ヨ祫涓◣")
     private BigDecimal salaryTax;
 
-    @ApiModelProperty("搴斿彂宸ヨ祫")
+    @Schema(description = "搴斿彂宸ヨ祫")
     private BigDecimal grossSalary;
 
-    @ApiModelProperty("搴旀墸宸ヨ祫")
+    @Schema(description = "搴旀墸宸ヨ祫")
     private BigDecimal deductSalary;
 
-    @ApiModelProperty("瀹炲彂宸ヨ祫")
+    @Schema(description = "瀹炲彂宸ヨ祫")
     private BigDecimal netSalary;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java
index 191406b..c85c61c 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java
@@ -11,8 +11,7 @@
 import java.util.List;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -27,7 +26,7 @@
 @Getter
 @Setter
 @TableName("staff_salary_main")
-@ApiModel(value = "StaffSalaryMain瀵硅薄", description = "鍛樺伐宸ヨ祫涓昏〃")
+@Schema(name = "StaffSalaryMain瀵硅薄", description = "鍛樺伐宸ヨ祫涓昏〃")
 public class StaffSalaryMain implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -35,59 +34,62 @@
     @TableField(exist = false)
     private List<StaffSalaryDetail> staffSalaryDetailList;
 
-    @ApiModelProperty("涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("瀹℃牳浜篒d")
+    @Schema(description = "瀹℃牳浜篒d")
     private Long auditUserId;
 
-    @ApiModelProperty("瀹℃牳浜哄悕绉�")
+    @Schema(description = "瀹℃牳浜哄悕绉�")
     private String auditUserName;
 
-    @ApiModelProperty("宸ヨ祫涓婚")
+    @Schema(description = "宸ヨ祫涓婚")
     private String salaryTitle;
 
-    @ApiModelProperty("鍏宠仈閮ㄩ棬ID锛屽涓敤閫楀彿鍒嗛殧")
+    @Schema(description = "鍏宠仈閮ㄩ棬ID锛屽涓敤閫楀彿鍒嗛殧")
     private String deptIds;
 
-    @ApiModelProperty("宸ヨ祫鏈堜唤锛屾牸寮忥細yyyy-MM")
+    @Schema(description = "宸ヨ祫鏈堜唤锛屾牸寮忥細yyyy-MM")
     private String salaryMonth;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("鐘舵�侊細1-鑽夌 2-瀹℃牳鏈�氳繃 3-寰呭鏍� 4-寰呭彂鏀� 5-宸插彂鏀�")
+    @Schema(description = "鐘舵�侊細1-鑽夌 2-瀹℃牳鏈�氳繃 3-寰呭鏍� 4-寰呭彂鏀� 5-宸插彂鏀�")
     private Integer status;
 
-    @ApiModelProperty("宸ヨ祫鎬婚")
+    @Schema(description = "宸ヨ祫鎬婚")
     private BigDecimal totalSalary;
 
-    @ApiModelProperty("鏀粯閾惰")
+    @Schema(description = "鏀粯閾惰")
     private String payBank;
 
     @TableField(exist = false)
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     private String createUserName;
 
-    @ApiModelProperty("鍙戞斁鏃堕棿")
+    @Schema(description = "鍙戞斁鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",shape = JsonFormat.Shape.STRING)
     private LocalDateTime payTime;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",shape = JsonFormat.Shape.STRING)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffScheduling.java b/src/main/java/com/ruoyi/staff/pojo/StaffScheduling.java
index a00040c..f1e3d47 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffScheduling.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffScheduling.java
@@ -116,4 +116,7 @@
      */
     @TableField(value = "tenant_id",fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffWorkExperience.java b/src/main/java/com/ruoyi/staff/pojo/StaffWorkExperience.java
index 6d59f83..684e7e1 100644
--- a/src/main/java/com/ruoyi/staff/pojo/StaffWorkExperience.java
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffWorkExperience.java
@@ -10,8 +10,7 @@
 import java.time.LocalDateTime;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -27,53 +26,56 @@
 @Getter
 @Setter
 @TableName("staff_work_experience")
-@ApiModel(value = "StaffWorkExperience瀵硅薄", description = "鍛樺伐宸ヤ綔缁忓巻琛�")
+@Schema(name = "StaffWorkExperience瀵硅薄", description = "鍛樺伐宸ヤ綔缁忓巻琛�")
 public class StaffWorkExperience implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("涓婚敭ID")
+    @Schema(description = "涓婚敭ID")
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍏宠仈staff_on_job琛ㄤ富閿甀D")
+    @Schema(description = "鍏宠仈staff_on_job琛ㄤ富閿甀D")
     private Long staffOnJobId;
 
-    @ApiModelProperty("鍓嶅叕鍙�")
+    @Schema(description = "鍓嶅叕鍙�")
     private String formerCompany;
 
-    @ApiModelProperty("鍓嶅叕鍙搁儴闂�")
+    @Schema(description = "鍓嶅叕鍙搁儴闂�")
     private String formerDept;
 
-    @ApiModelProperty("鍓嶅叕鍙歌亴浣�")
+    @Schema(description = "鍓嶅叕鍙歌亴浣�")
     private String formerPosition;
 
-    @ApiModelProperty("寮�濮嬫棩鏈�")
+    @Schema(description = "寮�濮嬫棩鏈�")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate startDate;
 
-    @ApiModelProperty("缁撴潫鏃ユ湡")
+    @Schema(description = "缁撴潫鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate endDate;
 
-    @ApiModelProperty("宸ヤ綔鎻忚堪")
+    @Schema(description = "宸ヤ綔鎻忚堪")
     private String workDesc;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Long createUser;
 
-    @ApiModelProperty("淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Long updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java b/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java
index 1e60ffe..a859d14 100644
--- a/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java
+++ b/src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java
@@ -8,7 +8,7 @@
 import com.ruoyi.staff.pojo.StaffOnJob;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 public interface IStaffOnJobService extends IService<StaffOnJob> {
diff --git a/src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java b/src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java
index 7b8cd58..2cf8c5f 100644
--- a/src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java
+++ b/src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java
@@ -8,7 +8,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.staff.pojo.StaffOnJob;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * <p>
diff --git a/src/main/java/com/ruoyi/staff/service/StaffLeaveService.java b/src/main/java/com/ruoyi/staff/service/StaffLeaveService.java
index 9fab5a1..24d2261 100644
--- a/src/main/java/com/ruoyi/staff/service/StaffLeaveService.java
+++ b/src/main/java/com/ruoyi/staff/service/StaffLeaveService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.staff.dto.StaffLeaveDto;
 import com.ruoyi.staff.pojo.StaffLeave;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 public interface StaffLeaveService extends IService<StaffLeave> {
diff --git a/src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java
index ff74b0f..2705b4d 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/AnalyticsServiceImpl.java
@@ -9,8 +9,7 @@
 import com.ruoyi.staff.service.AnalyticsService;
 import com.ruoyi.staff.vo.MonthlyTurnoverRateVo;
 import com.ruoyi.staff.vo.TotalTurnoverRateVo;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDate;
@@ -20,14 +19,12 @@
 import java.util.List;
 import java.util.Map;
 
-@AllArgsConstructor
 @Service
+@RequiredArgsConstructor
 public class AnalyticsServiceImpl extends ServiceImpl<StaffLeaveMapper, StaffLeave> implements AnalyticsService {
-    @Autowired
-    private StaffLeaveMapper staffLeaveMapper;
 
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
+    private final StaffLeaveMapper staffLeaveMapper;
+    private final StaffOnJobMapper staffOnJobMapper;
 
     @Override
     public List<StaffLeaveDto> staffLeaveReasonAnalytics() {
diff --git a/src/main/java/com/ruoyi/staff/service/impl/HolidayApplicationServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/HolidayApplicationServiceImpl.java
index 8decb71..e02fceb 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/HolidayApplicationServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/HolidayApplicationServiceImpl.java
@@ -7,13 +7,13 @@
 import com.ruoyi.staff.mapper.HolidayApplicationMapper;
 import com.ruoyi.staff.pojo.HolidayApplication;
 import com.ruoyi.staff.service.HolidayApplicationService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 @Service
+@RequiredArgsConstructor
 public class HolidayApplicationServiceImpl extends ServiceImpl<HolidayApplicationMapper, HolidayApplication> implements HolidayApplicationService {
-    @Autowired
-    private HolidayApplicationMapper holidayApplicationMapper;
+    private final HolidayApplicationMapper holidayApplicationMapper;
 
     @Override
     public IPage listPage(Page page, HolidayApplication holidayApplication) {
diff --git a/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
index 9d5e688..48c6745 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
@@ -5,39 +5,35 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
-import com.ruoyi.project.system.service.ISysDictDataService;
 import com.ruoyi.staff.dto.PersonalAttendanceRecordsDto;
-import com.ruoyi.staff.dto.StaffOnJobDto;
 import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper;
+import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper;
 import com.ruoyi.staff.mapper.PersonalShiftMapper;
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig;
 import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
-import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper;
 import com.ruoyi.staff.pojo.PersonalShift;
 import com.ruoyi.staff.pojo.StaffOnJob;
 import com.ruoyi.staff.service.PersonalAttendanceRecordsService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.staff.task.PersonalAttendanceRecordsTask;
 import com.ruoyi.staff.utils.LocationUtils;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.time.format.DateTimeFormatter;
 import java.util.List;
 
 /**
@@ -50,24 +46,14 @@
  */
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class PersonalAttendanceRecordsServiceImpl extends ServiceImpl<PersonalAttendanceRecordsMapper, PersonalAttendanceRecords> implements PersonalAttendanceRecordsService {
-    @Autowired
-    private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
 
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
-
-    @Autowired
-    private PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
-
-    @Autowired
-    private ISysDictDataService dictDataService;
-
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
-
-    @Autowired
-    private PersonalShiftMapper personalShiftMapper;
+    private final PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
+    private final StaffOnJobMapper staffOnJobMapper;
+    private final PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
+    private final SysDeptMapper sysDeptMapper;
+    private final PersonalShiftMapper personalShiftMapper;
 
     @Override
     public int add(PersonalAttendanceRecordsDto personalAttendanceRecordsDto) {
diff --git a/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
index 420bb71..81a3545 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/PersonalShiftServiceImpl.java
@@ -2,26 +2,22 @@
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.project.system.domain.SysDictData;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.staff.dto.PerformanceShiftAddDto;
 import com.ruoyi.staff.dto.PerformanceShiftMapDto;
 import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper;
+import com.ruoyi.staff.mapper.PersonalShiftMapper;
 import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig;
 import com.ruoyi.staff.pojo.PersonalShift;
-import com.ruoyi.staff.mapper.PersonalShiftMapper;
-import com.ruoyi.staff.service.PersonalAttendanceLocationConfigService;
 import com.ruoyi.staff.service.PersonalShiftService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.staff.utils.JackSonUtil;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
-import cn.hutool.core.date.DateUtil;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ObjectUtils;
 
@@ -29,7 +25,6 @@
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.YearMonth;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAdjusters;
@@ -46,10 +41,10 @@
  */
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class PersonalShiftServiceImpl extends ServiceImpl<PersonalShiftMapper, PersonalShift> implements PersonalShiftService {
 
-    @Autowired
-    private PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
+    private final PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
 
     @Override
     public int performanceShiftAdd(PerformanceShiftAddDto performanceShiftAddDto) {
@@ -228,6 +223,9 @@
             for (String shiftTime : shiftTimes) {
                 Map<String, Object> hashMap = new HashMap<>();
                 String[] shiftTimeAndShift = shiftTime.split("锛�");
+                if(shiftTimeAndShift.length != 3){
+                    continue;
+                }
                 for (PersonalAttendanceLocationConfig personalAttendanceLocationConfig : personalAttendanceLocationConfigs) {
                     if (!i.getMonthlyAttendance().containsKey(personalAttendanceLocationConfig.getShift())) {
                         i.getMonthlyAttendance().put(personalAttendanceLocationConfig.getShift(), 0);
@@ -258,6 +256,16 @@
         LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
         map.put("header", getMonthHeader(localDateTime));
         List<List<Object>> lists = dataRequiredForProcessingIntoExcelMonth(mapIPage, personalAttendanceLocationConfigs);
+        int maxSize = lists.stream()
+                .mapToInt(List::size)
+                .max()
+                .orElse(0);
+
+        for (List<Object> row : lists) {
+            while (row.size() < maxSize) {
+                row.add("-");
+            }
+        }
         map.put("data", lists);
         return map;
     }
diff --git a/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
index 7d59c26..bd61ca3 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
@@ -2,35 +2,33 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.production.dto.UserAccountDto;
-import com.ruoyi.production.dto.UserProductionAccountingDto;
+import com.ruoyi.production.bean.dto.UserAccountDto;
+import com.ruoyi.production.bean.dto.UserProductionAccountingDto;
 import com.ruoyi.production.service.SalesLedgerProductionAccountingService;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.domain.SysUserDept;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
-import com.ruoyi.project.system.mapper.SysUserDeptMapper;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.staff.controller.TaxCalculator;
-import com.ruoyi.staff.dto.StaffOnJobDto;
+import com.ruoyi.staff.mapper.SchemeApplicableStaffMapper;
 import com.ruoyi.staff.mapper.SchemeInsuranceDetailMapper;
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.SchemeApplicableStaff;
-import com.ruoyi.staff.mapper.SchemeApplicableStaffMapper;
 import com.ruoyi.staff.pojo.SchemeInsuranceDetail;
 import com.ruoyi.staff.pojo.StaffOnJob;
-import com.ruoyi.staff.service.IStaffOnJobService;
 import com.ruoyi.staff.service.SchemeApplicableStaffService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.*;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
@@ -42,28 +40,15 @@
  * @since 2026-03-05 11:50:17
  */
 @Service
+@RequiredArgsConstructor
 public class SchemeApplicableStaffServiceImpl extends ServiceImpl<SchemeApplicableStaffMapper, SchemeApplicableStaff> implements SchemeApplicableStaffService {
 
-    @Autowired
-    private SchemeApplicableStaffMapper schemeApplicableStaffMapper;
-
-    @Autowired
-    private SchemeInsuranceDetailMapper schemeInsuranceDetailMapper;
-
-    @Autowired
-    private SysUserDeptMapper sysUserDeptMapper;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private SysDeptMapper sysDeptMapper;
-
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
-
-    @Autowired
-    private SalesLedgerProductionAccountingService salesLedgerProductionAccountingService;
+    private final SchemeApplicableStaffMapper schemeApplicableStaffMapper;
+    private final SchemeInsuranceDetailMapper schemeInsuranceDetailMapper;
+    private final SysUserMapper sysUserMapper;
+    private final SysDeptMapper sysDeptMapper;
+    private final StaffOnJobMapper staffOnJobMapper;
+    private final SalesLedgerProductionAccountingService salesLedgerProductionAccountingService;
 
 
     @Override
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
index b7e64ed..548323d 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -13,36 +13,28 @@
 import com.ruoyi.staff.mapper.StaffLeaveMapper;
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
+import com.ruoyi.staff.pojo.StaffLeave;
 import com.ruoyi.staff.pojo.StaffOnJob;
 import com.ruoyi.staff.service.StaffLeaveService;
-import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
-import com.ruoyi.staff.pojo.StaffLeave;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.stream.Collectors;
 
 import static com.ruoyi.common.enums.StaffLeaveReason.StaffLeaveReasonOther;
 
-@AllArgsConstructor
+@RequiredArgsConstructor
 @Service
 public class StaffLeaveServiceImpl extends ServiceImpl<StaffLeaveMapper, StaffLeave> implements StaffLeaveService {
-    @Autowired
-    private StaffLeaveMapper staffLeaveMapper;
 
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
+    private final StaffLeaveMapper staffLeaveMapper;
+    private final StaffOnJobMapper staffOnJobMapper;
+    private final SysUserMapper sysUserMapper;
+    private final PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
 
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
-
-    //鏂板绂昏亴鍒楄〃鍒嗛〉鏌ヨ
     @Override
     public IPage<StaffLeaveDto> staffLeaveListPage(Page page, StaffLeaveDto staffLeaveDto) {
         return staffLeaveMapper.staffLeaveListPage(page,staffLeaveDto);
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
index 073733b..7c11041 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
@@ -6,33 +6,37 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.exception.base.BaseException;
-import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.dto.WordDateDto;
+import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.domain.SysPost;
+import com.ruoyi.project.system.domain.SysRole;
 import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.mapper.SysPostMapper;
+import com.ruoyi.project.system.mapper.SysRoleMapper;
 import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.project.system.service.impl.SysUserServiceImpl;
 import com.ruoyi.staff.dto.StaffOnJobDto;
+import com.ruoyi.staff.dto.StaffOnJobExcelDto;
 import com.ruoyi.staff.mapper.*;
 import com.ruoyi.staff.pojo.*;
 import com.ruoyi.staff.service.IStaffOnJobService;
 import freemarker.template.Configuration;
 import freemarker.template.Template;
-import lombok.AllArgsConstructor;
-
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.ListUtils;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 import java.time.LocalDate;
@@ -40,46 +44,25 @@
 import java.util.*;
 import java.util.stream.Collectors;
 
-@AllArgsConstructor
+@RequiredArgsConstructor
 @Service
 public class StaffOnJobServiceImpl extends ServiceImpl<StaffOnJobMapper, StaffOnJob>  implements IStaffOnJobService {
 
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
-    @Autowired
-    private SysPostMapper sysPostMapper;
-
-    @Autowired
-    private StaffContractMapper staffContractMapper;
-    @Autowired
-    private StaffLeaveMapper staffLeaveMapper;
-
-    @Autowired
-    private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
-
-    @Autowired
-    private SysUserServiceImpl sysUserService;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private StaffEducationServiceImpl staffEducationService;
-
-    @Autowired
-    private StaffEducationMapper staffEducationMapper;
-
-    @Autowired
-    private StaffWorkExperienceMapper staffWorkExperienceMapper;
-
-    @Autowired
-    private StaffWorkExperienceServiceImpl staffWorkExperienceServiceImpl;
-
-    @Autowired
-    private StaffEmergencyContactMapper staffEmergencyContactMapper;
-
-    @Autowired
-    private StaffEmergencyContactServiceImpl staffEmergencyContactServiceImpl;
+    private final StaffOnJobMapper staffOnJobMapper;
+    private final SysDeptMapper sysDeptMapper;
+    private final SysRoleMapper sysRoleMapper;
+    private final SysPostMapper sysPostMapper;
+    private final StaffContractMapper staffContractMapper;
+    private final StaffLeaveMapper staffLeaveMapper;
+    private final PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
+    private final SysUserServiceImpl sysUserService;
+    private final SysUserMapper sysUserMapper;
+    private final StaffEducationServiceImpl staffEducationService;
+    private final StaffEducationMapper staffEducationMapper;
+    private final StaffWorkExperienceMapper staffWorkExperienceMapper;
+    private final StaffWorkExperienceServiceImpl staffWorkExperienceServiceImpl;
+    private final StaffEmergencyContactMapper staffEmergencyContactMapper;
+    private final StaffEmergencyContactServiceImpl staffEmergencyContactServiceImpl;
 
 
     //鍦ㄨ亴鍛樺伐鍙拌处鍒嗛〉鏌ヨ
@@ -310,11 +293,38 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Boolean importData(MultipartFile file) {
         try {
-            ExcelUtil<StaffOnJob> util = new ExcelUtil<>(StaffOnJob.class);
-            List<StaffOnJob> staffOnJobs = util.importExcel(file.getInputStream());
-            return saveOrUpdateBatch(staffOnJobs);
+            ExcelUtil<StaffOnJobExcelDto> util = new ExcelUtil<>(StaffOnJobExcelDto.class);
+            List<StaffOnJobExcelDto> staffOnJobs = util.importExcel(file.getInputStream());
+            if (CollectionUtils.isEmpty(staffOnJobs)){
+                return false;
+            }
+            // 鑾峰彇鎵�鏈夐儴闂ㄦ暟鎹�
+            List<SysDept> sysDepts = sysDeptMapper.selectList(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDelFlag, 0));
+            // 鑾峰彇鎵�鏈夎鑹叉暟鎹�
+            List<SysRole> sysRoles = sysRoleMapper.selectRoleAll();
+            staffOnJobs.forEach(staffOnJob -> {
+                StaffOnJobDto staffOnJobDto = new StaffOnJobDto();
+                BeanUtils.copyProperties(staffOnJob, staffOnJobDto);
+                // 閫氳繃鍚嶇О鑾峰彇閮ㄩ棬id
+                staffOnJobDto.setSysDeptId(// ... existing code ...
+                        sysDepts.stream()
+                            .filter(dept -> dept.getDeptName() != null && dept.getDeptName().equals(staffOnJob.getSysDeptName()))
+                            .findFirst()
+                            .map(SysDept::getDeptId)
+                            .orElse(null)
+                        );
+                // 閫氳繃鍚嶇О鑾峰彇瑙掕壊id
+                staffOnJobDto.setRoleId(sysRoles.stream()
+                        .filter(role -> role.getRoleName() != null && role.getRoleName().equals(staffOnJob.getRoleName()))
+                        .findFirst()
+                        .map(SysRole::getRoleId)
+                        .orElse( null));
+                add(staffOnJobDto);
+            });
+            return true;
         } catch (Exception e) {
             e.printStackTrace();
             return false;
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
index 26a34c1..a6d4500 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
@@ -2,31 +2,30 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.account.mapper.AccountExpenseMapper;
 import com.ruoyi.account.pojo.AccountExpense;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.project.system.domain.SysUser;
-import com.ruoyi.project.system.domain.SysUserDept;
 import com.ruoyi.project.system.mapper.SysUserDeptMapper;
-import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.staff.dto.CalculateSalaryDto;
 import com.ruoyi.staff.mapper.StaffLeaveMapper;
-import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.mapper.StaffSalaryDetailMapper;
-import com.ruoyi.staff.pojo.*;
 import com.ruoyi.staff.mapper.StaffSalaryMainMapper;
+import com.ruoyi.staff.pojo.StaffLeave;
+import com.ruoyi.staff.pojo.StaffSalaryDetail;
+import com.ruoyi.staff.pojo.StaffSalaryMain;
 import com.ruoyi.staff.service.StaffSalaryDetailService;
 import com.ruoyi.staff.service.StaffSalaryMainService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import java.math.BigDecimal;
-import java.util.*;
-import java.util.stream.Collectors;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -37,34 +36,16 @@
  * @since 2026-03-06 01:22:05
  */
 @Service
+@RequiredArgsConstructor
 public class StaffSalaryMainServiceImpl extends ServiceImpl<StaffSalaryMainMapper, StaffSalaryMain> implements StaffSalaryMainService {
 
-    @Autowired
-    private StaffSalaryMainMapper staffSalaryMainMapper;
-
-    @Autowired
-    private StaffSalaryDetailService staffSalaryDetailService;
-
-    @Autowired
-    private StaffSalaryDetailMapper staffSalaryDetailMapper;
-
-    @Autowired
-    private SchemeApplicableStaffServiceImpl schemeApplicableStaffService;
-
-    @Autowired
-    private SysUserDeptMapper sysUserDeptMapper;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
-
-    @Autowired
-    private StaffLeaveMapper staffLeaveMapper;
-
-    @Autowired
-    private AccountExpenseMapper accountExpenseMapper;
+    private final StaffSalaryMainMapper staffSalaryMainMapper;
+    private final StaffSalaryDetailService staffSalaryDetailService;
+    private final StaffSalaryDetailMapper staffSalaryDetailMapper;
+    private final SchemeApplicableStaffServiceImpl schemeApplicableStaffService;
+    private final SysUserDeptMapper sysUserDeptMapper;
+    private final StaffLeaveMapper staffLeaveMapper;
+    private final AccountExpenseMapper accountExpenseMapper;
 
     @Override
     public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) {
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffSchedulingServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffSchedulingServiceImpl.java
index b05fc92..4e1ca14 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffSchedulingServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffSchedulingServiceImpl.java
@@ -17,7 +17,7 @@
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.math.BigDecimal;
 import java.time.Duration;
 
diff --git a/src/main/java/com/ruoyi/staff/task/PersonalAttendanceRecordsTask.java b/src/main/java/com/ruoyi/staff/task/PersonalAttendanceRecordsTask.java
index a791300..404dae7 100644
--- a/src/main/java/com/ruoyi/staff/task/PersonalAttendanceRecordsTask.java
+++ b/src/main/java/com/ruoyi/staff/task/PersonalAttendanceRecordsTask.java
@@ -4,20 +4,18 @@
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.staff.dto.PerformanceShiftAddDto;
 import com.ruoyi.staff.mapper.PersonalAttendanceLocationConfigMapper;
-import com.ruoyi.staff.mapper.PersonalShiftMapper;
+import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper;
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.PersonalAttendanceLocationConfig;
 import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
 import com.ruoyi.staff.pojo.StaffOnJob;
 import com.ruoyi.staff.service.PersonalAttendanceRecordsService;
-import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper;
 import com.ruoyi.staff.service.PersonalShiftService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
-import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -26,7 +24,6 @@
 import java.time.temporal.WeekFields;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -37,22 +34,14 @@
  */
 @Slf4j
 @Component
+@RequiredArgsConstructor
 public class PersonalAttendanceRecordsTask {
 
-    @Autowired
-    private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
-
-    @Autowired
-    private PersonalAttendanceRecordsService personalAttendanceRecordsService;
-
-    @Autowired
-    private PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
-
-    @Autowired
-    private StaffOnJobMapper staffOnJobMapper;
-
-    @Autowired
-    private PersonalShiftService personalShiftService;
+    private final PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
+    private final PersonalAttendanceRecordsService personalAttendanceRecordsService;
+    private final PersonalAttendanceLocationConfigMapper personalAttendanceLocationConfigMapper;
+    private final StaffOnJobMapper staffOnJobMapper;
+    private final PersonalShiftService personalShiftService;
 
     /**
      * 姣忓ぉ鍑屾櫒鐢熸垚鏄ㄦ棩鐨勭己鍕よ褰�
diff --git a/src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java b/src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java
index 90f9c69..82da034 100644
--- a/src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java
+++ b/src/main/java/com/ruoyi/staff/vo/MonthlyTurnoverRateVo.java
@@ -1,6 +1,6 @@
 package com.ruoyi.staff.vo;
 
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDate;
@@ -10,30 +10,30 @@
  */
 @Data
 public class MonthlyTurnoverRateVo {
-    @ApiModelProperty("鏈堜唤")
+    @Schema(description = "鏈堜唤")
     private String month;
 
-    @ApiModelProperty("鏈堝垵鍛樺伐鏁�")
+    @Schema(description = "鏈堝垵鍛樺伐鏁�")
     private Integer beginMonthStaffCount;
 
-    @ApiModelProperty("鏈堟湯鍛樺伐鏁�")
+    @Schema(description = "鏈堟湯鍛樺伐鏁�")
     private Integer endMonthStaffCount;
 
-    @ApiModelProperty("鏈堝害鍏ヨ亴鍛樺伐鏁�")
+    @Schema(description = "鏈堝害鍏ヨ亴鍛樺伐鏁�")
     private Integer newHireCount;
 
-    @ApiModelProperty("鏈堝害绂昏亴鍛樺伐鏁�")
+    @Schema(description = "鏈堝害绂昏亴鍛樺伐鏁�")
     private Integer leaveCount;
 
-    @ApiModelProperty("娴佸け鐜�(%)")
+    @Schema(description = "娴佸け鐜�(%)")
     private Double turnoverRate;
 
-    @ApiModelProperty("娴佸姩鐜�(%)")
+    @Schema(description = "娴佸姩鐜�(%)")
     private Double flowRate;
 
-    @ApiModelProperty("鏈堜唤寮�濮嬫棩鏈�")
+    @Schema(description = "鏈堜唤寮�濮嬫棩鏈�")
     private LocalDate monthStartDate;
 
-    @ApiModelProperty("鏈堜唤缁撴潫鏃ユ湡")
+    @Schema(description = "鏈堜唤缁撴潫鏃ユ湡")
     private LocalDate monthEndDate;
 }
diff --git a/src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java b/src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java
index 49d2f42..7a1e88b 100644
--- a/src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java
+++ b/src/main/java/com/ruoyi/staff/vo/TotalTurnoverRateVo.java
@@ -1,6 +1,6 @@
 package com.ruoyi.staff.vo;
 
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -8,12 +8,12 @@
  */
 @Data
 public class TotalTurnoverRateVo {
-    @ApiModelProperty("鎬绘祦鍔ㄧ巼(%)")
+    @Schema(description = "鎬绘祦鍔ㄧ巼(%)")
     private Double totalFlowRate;
 
-    @ApiModelProperty("鎬绘祦澶辩巼(%)")
+    @Schema(description = "鎬绘祦澶辩巼(%)")
     private Double totalTurnoverRate;
 
-    @ApiModelProperty("褰撳墠鍦ㄨ亴鍛樺伐鏁�")
+    @Schema(description = "褰撳墠鍦ㄨ亴鍛樺伐鏁�")
     private Integer currentOnJobCount;
 }
diff --git a/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java b/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
index b12fc67..1887b27 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
@@ -7,25 +7,26 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.service.StockInRecordService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @RestController
-@Api(tags = "鍏ュ簱")
+@Tag(name = "鍏ュ簱")
 @RequestMapping("/stockInRecord")
+@RequiredArgsConstructor
 public class StockInRecordController {
-    @Autowired
-    private StockInRecordService stockInRecordService;
+
+    private final StockInRecordService stockInRecordService;
 
     @GetMapping("/listPage")
     @Log(title = "鐢熶骇鍏ュ簱-鍏ュ簱绠$悊-鍒楄〃", businessType = BusinessType.OTHER)
-    @ApiOperation(value = "鍏ュ簱绠$悊鍒楄〃")
+    @Operation(summary = "鍏ュ簱绠$悊鍒楄〃")
     public AjaxResult listPage(Page page, StockInRecordDto stockInRecordDto) {
         IPage<StockInRecordDto> result = stockInRecordService.listPage(page, stockInRecordDto);
         return AjaxResult.success(result);
@@ -42,10 +43,31 @@
         return AjaxResult.success(stockInRecordService.batchDelete(ids));
     }
 
+    @DeleteMapping("/pending")
+    @Log(title = "鍏ュ簱绠$悊-鍒犻櫎寰呭鎵瑰叆搴�", businessType = BusinessType.DELETE)
+    @Operation(summary = "鍒犻櫎寰呭鎵圭殑鍏ュ簱璁板綍")
+    public AjaxResult deletePending(@RequestBody List<Long> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        return AjaxResult.success(stockInRecordService.batchDeletePending(ids));
+    }
+
     @PostMapping("/exportStockInRecord")
-    @ApiOperation("瀵煎嚭鍏ュ簱璁板綍")
+    @Operation(summary = "瀵煎嚭鍏ュ簱璁板綍")
     public void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto) {
         stockInRecordService.exportStockInRecord(response,stockInRecordDto);
     }
 
+    @PostMapping("/approve")
+    @Log(title = "鍏ュ簱绠$悊-瀹℃壒鍏ュ簱", businessType = BusinessType.UPDATE)
+    @Operation(summary = "鎵归噺瀹℃壒鍏ュ簱璁板綍")
+    public AjaxResult approve(@RequestBody StockInRecordDto approveDto) {
+        if(CollectionUtils.isEmpty(approveDto.getIds())){
+            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        stockInRecordService.batchApprove(approveDto.getIds(), approveDto.getApprovalStatus());
+        return AjaxResult.success();
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
index 70f638e..44fe885 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
@@ -11,13 +11,13 @@
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.execl.StockInventoryExportData;
 import com.ruoyi.stock.service.StockInventoryService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -31,21 +31,28 @@
  */
 @RestController
 @RequestMapping("/stockInventory")
-@Api(tags = "搴撳瓨琛�")
+@Tag(name = "搴撳瓨琛�")
+@AllArgsConstructor
 public class StockInventoryController {
 
-    @Autowired
     private StockInventoryService stockInventoryService;
 
     @GetMapping("/pagestockInventory")
-    @ApiOperation("鍒嗛〉鏌ヨ搴撳瓨")
+    @Operation(summary = "鍒嗛〉鏌ヨ搴撳瓨")
     public R pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
         IPage<StockInventoryDto> stockInventoryDtoIPage = stockInventoryService.pagestockInventory(page, stockInventoryDto);
         return R.ok(stockInventoryDtoIPage);
     }
 
+    @GetMapping("/pageListCombinedStockInventory")
+    @Operation(summary = "鍒嗛〉鏌ヨ鑱斿悎搴撳瓨鍒楄〃")
+    public R pageListCombinedStockInventory(Page page, StockInventoryDto stockInventoryDto) {
+        IPage<StockInventoryDto> stockInventoryDtoIPage = stockInventoryService.pageListCombinedStockInventory(page, stockInventoryDto);
+        return R.ok(stockInventoryDtoIPage);
+    }
+
     @PostMapping("/addstockInventory")
-    @ApiOperation("鏂板搴撳瓨")
+    @Operation(summary = "鏂板搴撳瓨")
     public R addstockInventory(@RequestBody StockInventoryDto stockInventoryDto) {
         stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode()));
         stockInventoryDto.setRecordId(0L);
@@ -54,16 +61,32 @@
 
 
     @PostMapping("/subtractStockInventory")
-    @ApiOperation("鎵e噺搴撳瓨")
+    @Operation(summary = "鎵e噺搴撳瓨")
     public R subtractStockInventory(@RequestBody StockInventoryDto stockInventoryDto) {
         stockInventoryDto.setRecordType(String.valueOf(StockOutQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_OUT.getCode()));
         stockInventoryDto.setRecordId(0L);
         return R.ok(stockInventoryService.subtractStockInventory(stockInventoryDto));
     }
 
+    @PostMapping("/addStockInRecordOnly")
+    @Operation(summary = "鏂板鍏ュ簱璁板綍锛堜粎鍒涘缓璁板綍锛屼笉璋冩暣搴撳瓨锛�")
+    public R addStockInRecordOnly(@RequestBody StockInventoryDto stockInventoryDto) {
+        stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode()));
+        stockInventoryDto.setRecordId(0L);
+        return R.ok(stockInventoryService.addStockInRecordOnly(stockInventoryDto));
+    }
+
+    @PostMapping("/addStockOutRecordOnly")
+    @Operation(summary = "鏂板鍑哄簱璁板綍锛堜粎鍒涘缓璁板綍锛屼笉璋冩暣搴撳瓨锛�")
+    public R addStockOutRecordOnly(@RequestBody StockInventoryDto stockInventoryDto) {
+        stockInventoryDto.setRecordType(String.valueOf(StockOutQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_OUT.getCode()));
+        stockInventoryDto.setRecordId(0L);
+        return R.ok(stockInventoryService.addStockOutRecordOnly(stockInventoryDto));
+    }
+
 
     @PostMapping("importStockInventory")
-    @ApiOperation("瀵煎叆搴撳瓨")
+    @Operation(summary = "瀵煎叆搴撳瓨")
     public R importStockInventory(MultipartFile file) {
         return stockInventoryService.importStockInventory(file);
     }
@@ -77,32 +100,39 @@
     }
 
     @PostMapping("/exportStockInventory")
-    @ApiOperation("瀵煎嚭搴撳瓨")
+    @Operation(summary = "瀵煎嚭搴撳瓨")
     public void exportStockInventory(HttpServletResponse response, StockInventoryDto stockInventoryDto) {
         stockInventoryService.exportStockInventory(response, stockInventoryDto);
     }
 
     @GetMapping("stockInventoryPage")
-    @ApiOperation("搴撳瓨鎶ヨ〃鏌ヨ")
+    @Operation(summary = "搴撳瓨鎶ヨ〃鏌ヨ")
     public R stockInventoryPage(Page page, StockInventoryDto stockInventoryDto) {
         return R.ok(stockInventoryService.stockInventoryPage(stockInventoryDto,page));
     }
 
     @GetMapping("stockInAndOutRecord")
-    @ApiOperation("缁熻鍚勪釜浜у搧鐨勫叆搴撳拰鍑哄簱璁板綍")
+    @Operation(summary = "缁熻鍚勪釜浜у搧鐨勫叆搴撳拰鍑哄簱璁板綍")
     public R stockInAndOutRecord(StockInventoryDto stockInventoryDto,Page page) {
         return R.ok(stockInventoryService.stockInAndOutRecord(stockInventoryDto,page));
     }
 
     @PostMapping("/frozenStock")
-    @ApiOperation("鍐荤粨搴撳瓨")
+    @Operation(summary = "鍐荤粨搴撳瓨")
     public R frozenStock(@RequestBody StockInventoryDto stockInventoryDto) {
         return R.ok(stockInventoryService.frozenStock(stockInventoryDto));
     }
 
     @PostMapping("/thawStock")
-    @ApiOperation("瑙e喕搴撳瓨")
+    @Operation(summary = "瑙e喕搴撳瓨")
     public R thawStock(@RequestBody StockInventoryDto stockInventoryDto) {
         return R.ok(stockInventoryService.thawStock(stockInventoryDto));
     }
+
+
+    @GetMapping("/getByModelId")
+    @Operation(summary = "鏍规嵁浜у搧瑙勬牸ID鑾峰彇鍏ュ簱璁板綍")
+    public R getByModelId(Long productModelId) {
+        return R.ok(stockInventoryService.getByModelId(productModelId));
+    }
 }
diff --git a/src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java b/src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java
index bd98859..7351890 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockOutRecordController.java
@@ -7,13 +7,13 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.stock.dto.StockOutRecordDto;
 import com.ruoyi.stock.service.StockOutRecordService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -24,16 +24,16 @@
  * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
  * @since 2026-01-21 05:27:04
  */
-@Api(tags = "鍑哄簱")
+@Tag(name = "鍑哄簱")
 @RestController
 @RequestMapping("/stockOutRecord")
+@AllArgsConstructor
 public class StockOutRecordController {
-    @Autowired
     private StockOutRecordService stockOutRecordService;
 
     @GetMapping("/listPage")
     @Log(title = "鐢熶骇鍑哄簱-鍑哄簱绠$悊-鍒楄〃", businessType = BusinessType.OTHER)
-    @ApiOperation(value = "鍑哄簱绠$悊鍒楄〃")
+    @Operation(summary = "鍑哄簱绠$悊鍒楄〃")
     public AjaxResult listPage(Page page, StockOutRecordDto stockOutRecordDto) {
         IPage<StockOutRecordDto> result = stockOutRecordService.listPage(page, stockOutRecordDto);
         return AjaxResult.success(result);
@@ -60,10 +60,31 @@
         return AjaxResult.success(stockOutRecordService.batchDelete(ids));
     }
 
+    @DeleteMapping("/pending")
+    @Log(title = "鍑哄簱绠$悊-鍒犻櫎寰呭鎵瑰嚭搴�", businessType = BusinessType.DELETE)
+    @Operation(summary = "鍒犻櫎寰呭鎵圭殑鍑哄簱璁板綍")
+    public AjaxResult deletePending(@RequestBody List<Long> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        return AjaxResult.success(stockOutRecordService.batchDeletePending(ids));
+    }
+
     @PostMapping("/exportStockOutRecord")
-    @ApiOperation("瀵煎嚭鍑哄簱璁板綍")
+    @Operation(summary = "瀵煎嚭鍑哄簱璁板綍")
     public void exportStockOutRecord(HttpServletResponse response, StockOutRecordDto stockOutRecordDto) {
         stockOutRecordService.exportStockOutRecord(response,stockOutRecordDto);
     }
 
+    @PostMapping("/approve")
+    @Log(title = "鍑哄簱绠$悊-瀹℃壒鍑哄簱", businessType = BusinessType.UPDATE)
+    @Operation(summary = "鎵归噺瀹℃壒鍑哄簱璁板綍")
+    public AjaxResult approve(@RequestBody StockOutRecordDto approveDto) {
+        if(CollectionUtils.isEmpty(approveDto.getIds())){
+            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        stockOutRecordService.batchApprove(approveDto.getIds(), approveDto.getApprovalStatus());
+        return AjaxResult.success();
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java b/src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java
index 39401c4..477a68d 100644
--- a/src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java
+++ b/src/main/java/com/ruoyi/stock/controller/StockUninventoryController.java
@@ -8,11 +8,10 @@
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.dto.StockUninventoryDto;
 import com.ruoyi.stock.service.StockUninventoryService;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
-
-import javax.servlet.http.HttpServletResponse;
 
 /**
  * <p>
@@ -24,19 +23,19 @@
  */
 @RestController
 @RequestMapping("/stockUninventory")
+@AllArgsConstructor
 public class StockUninventoryController {
-    @Autowired
     private StockUninventoryService stockUninventoryService;
 
     @GetMapping("/pagestockUninventory")
-    @ApiOperation("鍒嗛〉鏌ヨ搴撳瓨")
+    @Operation(summary = "鍒嗛〉鏌ヨ搴撳瓨")
     public R pagestockUninventory(Page page, StockUninventoryDto stockUninventoryDto) {
         IPage<StockUninventoryDto> stockUninventoryDtoIPage = stockUninventoryService.pageStockUninventory(page, stockUninventoryDto);
         return R.ok(stockUninventoryDtoIPage);
     }
 
     @PostMapping("/addstockUninventory")
-    @ApiOperation("鏂板搴撳瓨")
+    @Operation(summary = "鏂板搴撳瓨")
     public R addstockUninventory(@RequestBody StockUninventoryDto stockUninventoryDto) {
         stockUninventoryDto.setRecordType(String.valueOf(StockInUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_IN.getCode()));
         stockUninventoryDto.setRecordId(0L);
@@ -45,28 +44,44 @@
 
 
     @PostMapping("/subtractstockUninventory")
-    @ApiOperation("鎵e噺搴撳瓨")
+    @Operation(summary = "鎵e噺搴撳瓨")
     public R subtractstockUninventory(@RequestBody StockUninventoryDto stockUninventoryDto) {
         stockUninventoryDto.setRecordType(String.valueOf(StockOutUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode()));
         stockUninventoryDto.setRecordId(0L);
         return R.ok(stockUninventoryService.subtractStockUninventory(stockUninventoryDto));
     }
 
+    @PostMapping("/addStockInRecordOnly")
+    @Operation(summary = "鏂板鍏ュ簱璁板綍锛堜粎鍒涘缓璁板綍锛屼笉璋冩暣搴撳瓨锛�")
+    public R addStockInRecordOnly(@RequestBody StockUninventoryDto stockUninventoryDto) {
+        stockUninventoryDto.setRecordType(String.valueOf(StockInUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_IN.getCode()));
+        stockUninventoryDto.setRecordId(0L);
+        return R.ok(stockUninventoryService.addStockInRecordOnly(stockUninventoryDto));
+    }
+
+    @PostMapping("/addStockOutRecordOnly")
+    @Operation(summary = "鏂板鍑哄簱璁板綍锛堜粎鍒涘缓璁板綍锛屼笉璋冩暣搴撳瓨锛�")
+    public R addStockOutRecordOnly(@RequestBody StockUninventoryDto stockUninventoryDto) {
+        stockUninventoryDto.setRecordType(String.valueOf(StockOutUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode()));
+        stockUninventoryDto.setRecordId(0L);
+        return R.ok(stockUninventoryService.addStockOutRecordOnly(stockUninventoryDto));
+    }
+
     @PostMapping("/exportStockUninventory")
-    @ApiOperation("瀵煎嚭搴撳瓨")
+    @Operation(summary = "瀵煎嚭搴撳瓨")
     public void exportStockUninventory(HttpServletResponse response, StockUninventoryDto stockUninventoryDto) {
         stockUninventoryService.exportStockUninventory(response,stockUninventoryDto);
     }
 
 
     @PostMapping("/frozenStock")
-    @ApiOperation("鍐荤粨搴撳瓨")
+    @Operation(summary = "鍐荤粨搴撳瓨")
     public R frozenStock(@RequestBody StockInventoryDto stockInventoryDto) {
         return R.ok(stockUninventoryService.frozenStock(stockInventoryDto));
     }
 
     @PostMapping("/thawStock")
-    @ApiOperation("瑙e喕搴撳瓨")
+    @Operation(summary = "瑙e喕搴撳瓨")
     public R thawStock(@RequestBody StockInventoryDto stockInventoryDto) {
         return R.ok(stockUninventoryService.thawStock(stockInventoryDto));
     }
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java b/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
index 9f47fd6..56ad762 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
@@ -1,7 +1,10 @@
 package com.ruoyi.stock.dto;
 
 import com.ruoyi.stock.pojo.StockInRecord;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+
+import java.util.List;
 
 
 @Data
@@ -26,4 +29,10 @@
     //鐜板瓨閲�
     private String currentStock;
 
+    @Schema(description = "椤堕儴鐖朵骇鍝乮d")
+    private Long topParentProductId;
+
+    @Schema(description = "璁板綍ID鍒楄〃")
+    private List<Long> ids;
+
 }
diff --git a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
index 125b52b..2be6512 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
@@ -2,6 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.stock.pojo.StockInventory;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -39,4 +40,40 @@
     private BigDecimal currentStock;
 
     private BigDecimal  unLockedQuantity;
+
+    @Schema(description = "椤堕儴鐖朵骇鍝乮d")
+    private Long topParentProductId;
+
+    @Schema(description = "搴撳瓨绫诲瀷锛歲ualified(鍚堟牸)銆乽nqualified(涓嶅悎鏍�)")
+    private String stockType;
+
+    @Schema(description = "鍚堟牸搴撳瓨鏁伴噺")
+    private BigDecimal qualifiedQuantity;
+
+    @Schema(description = "涓嶅悎鏍煎簱瀛樻暟閲�")
+    private BigDecimal unQualifiedQuantity;
+
+    @Schema(description = "鍚堟牸搴撳瓨鍐荤粨鏁伴噺")
+    private BigDecimal qualifiedLockedQuantity;
+
+    @Schema(description = "涓嶅悎鏍煎簱瀛樺喕缁撴暟閲�")
+    private BigDecimal unQualifiedLockedQuantity;
+
+    @Schema(description = "鍚堟牸搴撳瓨鏈喕缁撴暟閲�")
+    private BigDecimal qualifiedUnLockedQuantity;
+
+    @Schema(description = "涓嶅悎鏍煎簱瀛樻湭鍐荤粨鏁伴噺")
+    private BigDecimal unQualifiedUnLockedQuantity;
+
+    @Schema(description = "鍚堟牸搴撳瓨寰呭鏍稿嚭搴撴暟閲忥紙涓嶅崰鐢ㄥ簱瀛樹絾宸茬敵璇峰嚭搴擄級")
+    private BigDecimal qualifiedPendingOutQuantity;
+
+    @Schema(description = "涓嶅悎鏍煎簱瀛樺緟瀹℃牳鍑哄簱鏁伴噺")
+    private BigDecimal unQualifiedPendingOutQuantity;
+
+    @Schema(description = "鍚堟牸搴撳瓨ID")
+    private Long qualifiedId;
+
+    @Schema(description = "涓嶅悎鏍煎簱瀛業D")
+    private Long unQualifiedId;
 }
diff --git a/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java b/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java
index 3e3abf9..022be78 100644
--- a/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java
+++ b/src/main/java/com/ruoyi/stock/dto/StockOutRecordDto.java
@@ -1,9 +1,12 @@
 package com.ruoyi.stock.dto;
 
 import com.ruoyi.stock.pojo.StockOutRecord;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+
+import java.util.List;
 
 @Data
 @AllArgsConstructor
@@ -25,4 +28,10 @@
     private String timeStr;
 
     private String createBy;
+
+    @Schema(description = "椤堕儴鐖朵骇鍝乮d")
+    private Long topParentProductId;
+
+    @Schema(description = "璁板綍ID鍒楄〃")
+    private List<Long> ids;
 }
diff --git a/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java b/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
index 4b7553f..a5cec35 100644
--- a/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
+++ b/src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
@@ -19,14 +19,20 @@
     @Excel(name = "鍗曚綅")
     private String unit;
 
-    @Excel(name = "搴撳瓨鏁伴噺")
-    private BigDecimal qualitity;
+    @Excel(name = "鍚堟牸搴撳瓨鏁伴噺")
+    private BigDecimal qualifiedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎簱瀛樻暟閲�")
+    private BigDecimal unQualifiedQuantity;
 
     @Excel(name = "棰勮鏁伴噺")
     private BigDecimal warnNum;
 
-    @Excel(name = "鍐荤粨鏁伴噺")
-    private BigDecimal lockedQuantity;
+    @Excel(name = "鍚堟牸鍐荤粨鏁伴噺")
+    private BigDecimal qualifiedLockedQuantity;
+
+    @Excel(name = "涓嶅悎鏍煎喕缁撴暟閲�")
+    private BigDecimal unQualifiedLockedQuantity;
 
     @Excel(name = "澶囨敞")
     private String remark;
diff --git a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
index 0d345df..a31cf5b 100644
--- a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
+++ b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
@@ -29,6 +29,7 @@
 
     IPage<StockInventoryDto> pagestockInventory(Page page, @Param("ew") StockInventoryDto stockInventoryDto);
 
+    IPage<StockInventoryDto> pageListCombinedStockInventory(Page page, @Param("ew") StockInventoryDto stockInventoryDto);
 
     int updateAddStockInventory(@Param("ew") StockInventoryDto stockInventoryDto);
 
@@ -49,4 +50,10 @@
     List<Map<String, Object>> selectDailyStockOutCounts(@Param("rootCategoryId") Long rootCategoryId, @Param("startDate") String startDate, @Param("endDate") String endDate);
 
     BigDecimal selectTotalByDate(@Param("now") LocalDate now);
+
+    BigDecimal selectPendingOutQuantity(@Param("productModelId") Long productModelId, @Param("batchNo") String batchNo, @Param("type") String type);
+
+    List<StockInventory> listSelectableBatchNoByProductModelIds(@Param("productModelIds") List<Long> productModelIds);
+
+    List<StockInventory> getByModelId(@Param("productModelId") Long productModelId);
 }
diff --git a/src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java b/src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java
index 89e9b17..d6abdff 100644
--- a/src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java
+++ b/src/main/java/com/ruoyi/stock/mapper/StockUninventoryMapper.java
@@ -9,6 +9,7 @@
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -26,6 +27,8 @@
 
     int updateSubtractStockUnInventory(@Param("ew") StockUninventoryDto stockUninventoryDto);
 
+    BigDecimal selectPendingOutQuantity(@Param("productModelId") Long productModelId, @Param("batchNo") String batchNo, @Param("type") String type);
+
     int updateAddStockUnInventory(@Param("ew") StockUninventoryDto stockUninventoryDto);
 
     List<StockUnInventoryExportData> listStockInventoryExportData(@Param("ew") StockUninventoryDto stockUninventoryDto);
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
index 395d18f..6b8a807 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
@@ -2,8 +2,8 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import com.ruoyi.common.enums.ReviewStatusEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -12,7 +12,7 @@
 
 @Data
 @TableName("stock_in_record")
-@ApiModel("鍏ュ簱绠$悊")
+@Schema(name = "鍏ュ簱绠$悊")
 public class StockInRecord {
 
     private static final long serialVersionUID = 1L;
@@ -22,44 +22,53 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鍏ュ簱鎵规")
+    @Schema(description = "鍏ュ簱鎵规")
     private String inboundBatches;
 
-    @ApiModelProperty(value = "鍏ュ簱鏁伴噺")
+    @Schema(description = "鍏ュ簱鏁伴噺")
     private BigDecimal stockInNum;
 
-    @ApiModelProperty(value = "璁板綍绫诲瀷  鏋氫妇")
+    @Schema(description = "鎵瑰彿")
+    private String batchNo;
+
+    @Schema(description = "璁板綍绫诲瀷  鏋氫妇")
     private String recordType;
 
-    @ApiModelProperty(value = "璁板綍ID  ")
+    @Schema(description = "璁板綍ID  ")
     private Long recordId;
 
-    @ApiModelProperty(value = "浜у搧瑙勬牸ID")
+    @Schema(description = "浜у搧瑙勬牸ID")
     private Long productModelId;
 
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty(value = "绫诲瀷  0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
+    @Schema(description = "绫诲瀷  0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
     private String type;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
+
+    @Schema(description = "瀹℃壒鐘舵��  0-寰呭鎵� 1-閫氳繃 2-椹冲洖", implementation = ReviewStatusEnum.class)
+    private Integer approvalStatus;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockInventory.java b/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
index 36e7cf0..5652ec7 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockInventory.java
@@ -4,13 +4,12 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
@@ -26,19 +25,22 @@
 @Getter
 @Setter
 @TableName("stock_inventory")
-@ApiModel(value = "StockInventory瀵硅薄", description = "搴撳瓨琛�")
+@Schema(name = "StockInventory瀵硅薄", description = "搴撳瓨琛�")
 public class StockInventory implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("涓婚敭id")
+    @Schema(description = "涓婚敭id")
     private Long id;
 
-    @ApiModelProperty("瑙勬牸id")
+    @Schema(description = "瑙勬牸id")
     @NotBlank(message = "涓嶈兘涓虹┖")
     private Long productModelId;
 
-    @ApiModelProperty("鏁伴噺")
+    @Schema(description = "鎵瑰彿")
+    private String batchNo;
+
+    @Schema(description = "鏁伴噺")
     private BigDecimal qualitity;
 
     @TableField(fill = FieldFill.INSERT)
@@ -46,21 +48,28 @@
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鐗堟湰鍙�")
+    @Schema(description = "鐗堟湰鍙�")
     private Integer version;
 
-    @ApiModelProperty("琚鍗曢攣瀹氭暟閲�")
+    @Schema(description = "琚鍗曢攣瀹氭暟閲�")
     private BigDecimal lockedQuantity;
 
-    @ApiModelProperty("棰勮鏁伴噺")
+    @Schema(description = "棰勮鏁伴噺")
     private BigDecimal warnNum;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
index e4e3b82..20ea4a2 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
@@ -2,8 +2,8 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import com.ruoyi.common.enums.ReviewStatusEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -23,7 +23,7 @@
 @Getter
 @Setter
 @TableName("stock_out_record")
-@ApiModel(value = "StockOutRecord瀵硅薄", description = "鍑哄簱璁板綍琛�")
+@Schema(name = "StockOutRecord瀵硅薄", description = "鍑哄簱璁板綍琛�")
 public class StockOutRecord implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -31,44 +31,53 @@
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty("鍏ュ簱鎵规")
+    @Schema(description = "鍏ュ簱鎵规")
     private String outboundBatches;
 
-    @ApiModelProperty("鍏ュ簱鏁伴噺")
+    @Schema(description = "鎵瑰彿")
+    private String batchNo;
+
+    @Schema(description = "鍏ュ簱鏁伴噺")
     private BigDecimal stockOutNum;
 
-    @ApiModelProperty("鍏ュ簱鏉ユ簮id")
+    @Schema(description = "鍏ュ簱鏉ユ簮id")
     private Long recordId;
 
-    @ApiModelProperty("鍏ュ簱绫诲瀷")
+    @Schema(description = "鍏ュ簱绫诲瀷")
     private String recordType;
 
-    @ApiModelProperty("浜у搧瑙勬牸id")
+    @Schema(description = "浜у搧瑙勬牸id")
     private Long productModelId;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鍒涘缓浜�")
+    @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty("鏇存柊浜�")
+    @Schema(description = "鏇存柊浜�")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绫诲瀷  0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
+    @Schema(description = "绫诲瀷  0鍚堟牸鍏ュ簱 1涓嶅悎鏍煎叆搴�")
     private String type;
+
+    @Schema(description = "瀹℃壒鐘舵��  0-寰呭鎵� 1-閫氳繃 2-椹冲洖", implementation = ReviewStatusEnum.class)
+    private Integer approvalStatus;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java b/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
index 6ed47de..6272c2a 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
@@ -4,8 +4,7 @@
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -25,18 +24,21 @@
 @Getter
 @Setter
 @TableName("stock_uninventory")
-@ApiModel(value = "StockUninventory瀵硅薄", description = "涓嶅悎鏍煎簱瀛樿〃")
+@Schema(name = "StockUninventory瀵硅薄", description = "涓嶅悎鏍煎簱瀛樿〃")
 public class StockUninventory implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @ApiModelProperty("涓婚敭id")
+    @Schema(description = "涓婚敭id")
     private Long id;
 
-    @ApiModelProperty("瑙勬牸id")
+    @Schema(description = "瑙勬牸id")
     private Long productModelId;
 
-    @ApiModelProperty("鏁伴噺")
+    @Schema(description = "鎵瑰彿")
+    private String batchNo;
+
+    @Schema(description = "鏁伴噺")
     private BigDecimal qualitity;
 
     @TableField(fill = FieldFill.INSERT)
@@ -44,19 +46,26 @@
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;
 
-    @ApiModelProperty("鏇存柊鏃堕棿")
+    @Schema(description = "鏇存柊鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime updateTime;
 
-    @ApiModelProperty("鐗堟湰鍙�")
+    @Schema(description = "鐗堟湰鍙�")
     private Integer version;
 
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
-    @ApiModelProperty("琚鍗曢攣瀹氭暟閲�")
+    @Schema(description = "琚鍗曢攣瀹氭暟閲�")
     private BigDecimal lockedQuantity;
 
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
 }
diff --git a/src/main/java/com/ruoyi/stock/service/StockInRecordService.java b/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
index 29ba7e5..249f261 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockInRecordService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.pojo.StockInRecord;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 public interface StockInRecordService extends IService<StockInRecord> {
@@ -18,5 +18,9 @@
 
     int batchDelete(List<Long> ids);
 
+    int batchDeletePending(List<Long> ids);
+
     void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto);
+
+    int batchApprove(List<Long> ids, Integer approvalStatus);
 }
diff --git a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
index 65dcca3..d47cc4b 100644
--- a/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockInventoryService.java
@@ -7,9 +7,10 @@
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.pojo.StockInventory;
+import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import java.util.List;
 
 /**
  * <p>
@@ -23,9 +24,15 @@
 
     IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto);
 
+    IPage<StockInventoryDto> pageListCombinedStockInventory(Page page, StockInventoryDto stockInventoryDto);
+
     Boolean addstockInventory(StockInventoryDto stockInventoryDto);
 
     Boolean subtractStockInventory(StockInventoryDto stockInventoryDto);
+
+    Boolean addStockInRecordOnly(StockInventoryDto stockInventoryDto);
+
+    Boolean addStockOutRecordOnly(StockInventoryDto stockInventoryDto);
 
     R importStockInventory(MultipartFile file);
 
@@ -38,4 +45,6 @@
     Boolean frozenStock(StockInventoryDto stockInventoryDto);
 
     Boolean thawStock(StockInventoryDto stockInventoryDto);
+
+    List<StockInventory> getByModelId(Long modelId);
 }
diff --git a/src/main/java/com/ruoyi/stock/service/StockOutRecordService.java b/src/main/java/com/ruoyi/stock/service/StockOutRecordService.java
index f18d50c..bbad1f6 100644
--- a/src/main/java/com/ruoyi/stock/service/StockOutRecordService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockOutRecordService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.stock.dto.StockOutRecordDto;
 import com.ruoyi.stock.pojo.StockOutRecord;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -26,5 +26,9 @@
 
     int batchDelete(List<Long> ids);
 
+    int batchDeletePending(List<Long> ids);
+
     void exportStockOutRecord(HttpServletResponse response, StockOutRecordDto stockOutRecordDto);
+
+    int batchApprove(List<Long> ids, Integer approvalStatus);
 }
diff --git a/src/main/java/com/ruoyi/stock/service/StockUninventoryService.java b/src/main/java/com/ruoyi/stock/service/StockUninventoryService.java
index 0d6ba6d..ffc1ebe 100644
--- a/src/main/java/com/ruoyi/stock/service/StockUninventoryService.java
+++ b/src/main/java/com/ruoyi/stock/service/StockUninventoryService.java
@@ -7,7 +7,7 @@
 import com.ruoyi.stock.dto.StockUninventoryDto;
 import com.ruoyi.stock.pojo.StockUninventory;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 
 /**
  * <p>
@@ -25,6 +25,10 @@
 
     Integer subtractStockUninventory(StockUninventoryDto stockUninventoryDto);
 
+    Integer addStockInRecordOnly(StockUninventoryDto stockUninventoryDto);
+
+    Integer addStockOutRecordOnly(StockUninventoryDto stockUninventoryDto);
+
     void exportStockUninventory(HttpServletResponse response, StockUninventoryDto stockUninventoryDto);
 
     Boolean frozenStock(StockInventoryDto stockInventoryDto);
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
index 30e545f..f84a9d8 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -4,11 +4,13 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.enums.ReviewStatusEnum;
 import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.EnumUtil;
 import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.stock.dto.StockInRecordDto;
@@ -25,8 +27,9 @@
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 @Service
@@ -46,7 +49,7 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int add(StockInRecordDto stockInRecordDto) {
-        String no = OrderUtils.countTodayByCreateTime(stockInRecordMapper, "RK");
+        String no = OrderUtils.countTodayByCreateTime(stockInRecordMapper, "RK","inbound_batches");
         stockInRecordDto.setInboundBatches(no);
         StockInRecord stockInRecord = new StockInRecord();
         BeanUtils.copyProperties(stockInRecordDto, stockInRecord);
@@ -73,22 +76,38 @@
         for (Long id : ids) {
             StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
             if (stockInRecord.getType().equals("0")) {
-                StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, stockInRecord.getProductModelId()));
+                LambdaQueryWrapper<StockInventory> eq = new LambdaQueryWrapper<StockInventory>()
+                        .eq(StockInventory::getProductModelId, stockInRecord.getProductModelId());
+                if (StringUtils.isEmpty(stockInRecord.getBatchNo())) {
+                    eq.isNull(StockInventory::getBatchNo);
+                } else {
+                    eq.eq(StockInventory::getBatchNo, stockInRecord.getBatchNo());
+                }
+                StockInventory stockInventory = stockInventoryMapper.selectOne(eq);
                 if (stockInventory == null) {
                     throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
                 }else {
                     StockInventoryDto stockInRecordDto = new StockInventoryDto();
                     stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
+                    stockInRecordDto.setBatchNo(stockInventory.getBatchNo());
                     stockInRecordDto.setQualitity(stockInRecord.getStockInNum());
                     stockInventoryMapper.updateSubtractStockInventory(stockInRecordDto);
                 }
             }else if (stockInRecord.getType().equals("1")) {
-                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(new LambdaQueryWrapper<StockUninventory>().eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId()));
+                LambdaQueryWrapper<StockUninventory> eq = new LambdaQueryWrapper<StockUninventory>()
+                        .eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId());
+                if (StringUtils.isEmpty(stockInRecord.getBatchNo())) {
+                    eq.isNull(StockUninventory::getBatchNo);
+                } else {
+                    eq.eq(StockUninventory::getBatchNo, stockInRecord.getBatchNo());
+                }
+                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(eq);
                 if (stockUninventory == null) {
                     throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
                 }else {
                     StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                     stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
+                    stockUninventoryDto.setBatchNo(stockUninventory.getBatchNo());
                     stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
                     stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
                 }
@@ -110,4 +129,106 @@
         ExcelUtil<StockInRecordExportData> util = new ExcelUtil<>(StockInRecordExportData.class);
         util.exportExcel(response,list, "鍏ュ簱璁板綍淇℃伅");
     }
+
+    private StockInventory getStockInventory(Long productModelId, String batchNo) {
+        LambdaQueryWrapper<StockInventory> eq = new LambdaQueryWrapper<>();
+        eq.eq(StockInventory::getProductModelId, productModelId);
+        if (StringUtils.isEmpty(batchNo)) {
+            eq.isNull(StockInventory::getBatchNo);
+        } else {
+            eq.eq(StockInventory::getBatchNo, batchNo);
+        }
+        return stockInventoryMapper.selectOne(eq);
+    }
+
+    private StockUninventory getStockUninventory(Long productModelId, String batchNo) {
+        LambdaQueryWrapper<StockUninventory> eq = new LambdaQueryWrapper<>();
+        eq.eq(StockUninventory::getProductModelId, productModelId);
+        if (StringUtils.isEmpty(batchNo)) {
+            eq.isNull(StockUninventory::getBatchNo);
+        } else {
+            eq.eq(StockUninventory::getBatchNo, batchNo);
+        }
+        return stockUninventoryMapper.selectOne(eq);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int batchDeletePending(List<Long> ids) {
+        for (Long id : ids) {
+            StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
+            if (stockInRecord == null) {
+                throw new BaseException("鍏ュ簱璁板綍涓嶅瓨鍦�,鏃犳硶鍒犻櫎!!!");
+            }
+            if (stockInRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockInRecord.getApprovalStatus())) {
+                throw new BaseException("鍙湁寰呭鎵圭姸鎬佺殑璁板綍鎵嶈兘鍒犻櫎,鍏ュ簱鎵规:" + stockInRecord.getInboundBatches());
+            }
+        }
+        return stockInRecordMapper.deleteBatchIds(ids);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int batchApprove(List<Long> ids, Integer approvalStatus) {
+        if (CollectionUtils.isEmpty(ids)) {
+            throw new BaseException("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        if (approvalStatus == null || (!ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus) && !ReviewStatusEnum.REJECTED.getCode().equals(approvalStatus))) {
+            throw new BaseException("瀹℃壒鐘舵�佸�兼棤鏁�");
+        }
+        for (Long id : ids) {
+            StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
+            if (stockInRecord == null) {
+                throw new BaseException("鍏ュ簱璁板綍涓嶅瓨鍦�,鏃犳硶瀹℃壒!!!");
+            }
+            if (stockInRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockInRecord.getApprovalStatus())) {
+                throw new BaseException("鍙湁寰呭鎵圭姸鎬佺殑璁板綍鎵嶈兘瀹℃壒,鍏ュ簱鎵规:" + stockInRecord.getInboundBatches());
+            }
+            stockInRecord.setApprovalStatus(approvalStatus);
+            stockInRecordMapper.updateById(stockInRecord);
+            // 瀹℃壒閫氳繃鏃讹紝搴撳瓨澧炲姞
+            if (ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus)) {
+                if ("0".equals(stockInRecord.getType())) {
+                    // 鍚堟牸鍏ュ簱 -> 鍏堟煡搴撳瓨锛屽瓨鍦ㄥ垯鏇存柊锛屼笉瀛樺湪鍒欐柊澧�
+                    StockInventory stockInventory = getStockInventory(stockInRecord.getProductModelId(), stockInRecord.getBatchNo());
+                    StockInventoryDto stockInventoryDto = new StockInventoryDto();
+                    stockInventoryDto.setProductModelId(stockInRecord.getProductModelId());
+                    stockInventoryDto.setBatchNo(stockInRecord.getBatchNo());
+                    stockInventoryDto.setQualitity(stockInRecord.getStockInNum());
+                    stockInventoryDto.setRemark(stockInRecord.getRemark());
+                    if (stockInventory == null) {
+                        stockInventoryMapper.insert(new StockInventory() {{
+                            setProductModelId(stockInRecord.getProductModelId());
+                            setQualitity(stockInRecord.getStockInNum());
+                            setBatchNo(stockInRecord.getBatchNo());
+                            setRemark(stockInRecord.getRemark());
+                            setVersion(1);
+                        }});
+                    } else {
+                        stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
+                    }
+                } else if ("1".equals(stockInRecord.getType())) {
+                    // 涓嶅悎鏍煎叆搴� -> 鍏堟煡搴撳瓨锛屽瓨鍦ㄥ垯鏇存柊锛屼笉瀛樺湪鍒欐柊澧�
+                    StockUninventory stockUninventory = getStockUninventory(stockInRecord.getProductModelId(), stockInRecord.getBatchNo());
+                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
+                    stockUninventoryDto.setProductModelId(stockInRecord.getProductModelId());
+                    stockUninventoryDto.setBatchNo(stockInRecord.getBatchNo());
+                    stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
+                    stockUninventoryDto.setRemark(stockInRecord.getRemark());
+                    if (stockUninventory == null) {
+                        stockUninventoryMapper.insert(new StockUninventory() {{
+                            setProductModelId(stockInRecord.getProductModelId());
+                            setQualitity(stockInRecord.getStockInNum());
+                            setBatchNo(stockInRecord.getBatchNo());
+                            setRemark(stockInRecord.getRemark());
+                            setVersion(1);
+                        }});
+                    } else {
+                        stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
+                    }
+                }
+            }
+        }
+        return ids.size();
+    }
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
index 5cb6dda..d712518 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -1,12 +1,18 @@
 package com.ruoyi.stock.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.mapper.ProductModelMapper;
+import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
@@ -14,21 +20,28 @@
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.dto.StockOutRecordDto;
+import com.ruoyi.stock.dto.StockUninventoryDto;
 import com.ruoyi.stock.execl.StockInventoryExportData;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.pojo.StockInRecord;
 import com.ruoyi.stock.pojo.StockInventory;
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.stock.service.StockInventoryService;
 import com.ruoyi.stock.service.StockOutRecordService;
+import com.ruoyi.stock.service.StockUninventoryService;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -45,33 +58,51 @@
     private  StockInventoryMapper stockInventoryMapper;
     private StockInRecordService stockInRecordService;
     private StockOutRecordService stockOutRecordService;
+    private StockUninventoryService stockUninventoryService;
     private SalesLedgerProductMapper salesLedgerProductMapper;
+    private ProductModelMapper productModelMapper;
     @Override
     public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
         return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
+    }
+
+    @Override
+    public IPage<StockInventoryDto> pageListCombinedStockInventory(Page page, StockInventoryDto stockInventoryDto) {
+        return stockInventoryMapper.pageListCombinedStockInventory(page, stockInventoryDto);
     }
 
     //鍏ュ簱璋冪敤
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean addstockInventory(StockInventoryDto stockInventoryDto) {
+        String batchNo = StringUtils.trim(stockInventoryDto.getBatchNo());
+        if (StringUtils.isEmpty(batchNo)) {
+            batchNo = generateAutoBatchNo(stockInventoryDto.getProductModelId());
+        }
+        stockInventoryDto.setBatchNo(batchNo);
+
+        LambdaQueryWrapper<StockInventory> eq = new QueryWrapper<StockInventory>().lambda()
+                .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId());
+        eq.eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo());
         //鏂板鍏ュ簱璁板綍鍐嶆坊鍔犲簱瀛�
         StockInRecordDto stockInRecordDto = new StockInRecordDto();
         stockInRecordDto.setRecordId(stockInventoryDto.getRecordId());
         stockInRecordDto.setRecordType(stockInventoryDto.getRecordType());
         stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
+        stockInRecordDto.setBatchNo(stockInventoryDto.getBatchNo());
         stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
         stockInRecordDto.setType("0");
         stockInRecordService.add(stockInRecordDto);
         //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
         //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
-        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
+        StockInventory oldStockInventory = stockInventoryMapper.selectOne(eq);
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             StockInventory newStockInventory = new StockInventory();
             newStockInventory.setProductModelId(stockInventoryDto.getProductModelId());
             newStockInventory.setQualitity(stockInventoryDto.getQualitity());
             newStockInventory.setVersion(1);
             newStockInventory.setRemark(stockInventoryDto.getRemark());
+            newStockInventory.setBatchNo(stockInventoryDto.getBatchNo());
             newStockInventory.setLockedQuantity(stockInventoryDto.getLockedQuantity());
             newStockInventory.setWarnNum(stockInventoryDto.getWarnNum());
             stockInventoryMapper.insert(newStockInventory);
@@ -85,15 +116,26 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean subtractStockInventory(StockInventoryDto stockInventoryDto) {
+        LambdaQueryWrapper<StockInventory> eq = new QueryWrapper<StockInventory>().lambda()
+            .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId());
+        if (StringUtils.isEmpty(stockInventoryDto.getBatchNo())) {
+            eq.isNull(StockInventory::getBatchNo);
+            stockInventoryDto.setBatchNo(null);
+        } else {
+            eq.eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo());
+        }
         //  鏂板鍑哄簱璁板綍
         StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
         stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId());
         stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType());
         stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
+        stockOutRecordDto.setBatchNo(stockInventoryDto.getBatchNo());
         stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
         stockOutRecordDto.setType("0");
         stockOutRecordService.add(stockOutRecordDto);
-        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
+
+
+        StockInventory oldStockInventory = stockInventoryMapper.selectOne(eq);
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
         }
@@ -110,59 +152,239 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addStockInRecordOnly(StockInventoryDto stockInventoryDto) {
+        String batchNo = StringUtils.trim(stockInventoryDto.getBatchNo());
+        if (StringUtils.isEmpty(batchNo)) {
+            batchNo = generateAutoBatchNo(stockInventoryDto.getProductModelId());
+        }
+        stockInventoryDto.setBatchNo(batchNo);
+
+        StockInRecordDto stockInRecordDto = new StockInRecordDto();
+        stockInRecordDto.setRecordId(stockInventoryDto.getRecordId());
+        stockInRecordDto.setRecordType(stockInventoryDto.getRecordType());
+        stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
+        stockInRecordDto.setBatchNo(batchNo);
+        stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
+        stockInRecordDto.setType("0");
+        stockInRecordDto.setRemark(stockInventoryDto.getRemark());
+        stockInRecordService.add(stockInRecordDto);
+        return true;
+    }
+
+    //瑙勫垯鐢熸垚锛�20260424-浜у搧缂栧彿-001
+    private String generateAutoBatchNo(Long productModelId) {
+        if (productModelId == null) {
+            throw new ServiceException("浜у搧瑙勬牸ID涓嶈兘涓虹┖");
+        }
+        ProductModel productModel = productModelMapper.selectById(productModelId);
+        if (productModel == null) {
+            throw new ServiceException("浜у搧瑙勬牸涓嶅瓨鍦紝ID=" + productModelId);
+        }
+        String productCode = StringUtils.trim(productModel.getProductCode());
+        if (StringUtils.isEmpty(productCode)) {
+            throw new ServiceException("浜у搧瑙勬牸鏈淮鎶や骇鍝佺紪鐮侊紝ID=" + productModelId);
+        }
+
+        String dateText = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
+        String prefix = dateText + "-" + productCode + "-";
+        int maxSequence = resolveMaxSequence(prefix);
+        int sequence = maxSequence + 1;
+        while (sequence < 1_000_000) {
+            String batchNo = prefix + String.format("%03d", sequence);
+            if (!isBatchNoExists(batchNo)) {
+                return batchNo;
+            }
+            sequence++;
+        }
+        throw new ServiceException("鎵瑰彿搴忓彿瓒呭嚭鑼冨洿锛岃妫�鏌ユ壒鍙锋暟鎹�");
+    }
+
+    private int resolveMaxSequence(String prefix) {
+        int maxSequence = 0;
+        List<StockInventory> stockInventoryList = stockInventoryMapper.selectList(
+                Wrappers.<StockInventory>lambdaQuery()
+                        .select(StockInventory::getBatchNo)
+                        .likeRight(StockInventory::getBatchNo, prefix));
+        for (StockInventory stockInventory : stockInventoryList) {
+            maxSequence = Math.max(maxSequence, parseSequence(stockInventory.getBatchNo(), prefix));
+        }
+
+        List<StockInRecord> stockInRecordList = stockInRecordService.list(
+                Wrappers.<StockInRecord>lambdaQuery()
+                        .select(StockInRecord::getBatchNo)
+                        .likeRight(StockInRecord::getBatchNo, prefix));
+        for (StockInRecord stockInRecord : stockInRecordList) {
+            maxSequence = Math.max(maxSequence, parseSequence(stockInRecord.getBatchNo(), prefix));
+        }
+        return maxSequence;
+    }
+
+    private int parseSequence(String batchNo, String prefix) {
+        if (StringUtils.isEmpty(batchNo) || StringUtils.isEmpty(prefix) || !batchNo.startsWith(prefix)) {
+            return 0;
+        }
+        String sequenceText = batchNo.substring(prefix.length());
+        if (StringUtils.isEmpty(sequenceText) || !sequenceText.matches("\\d+")) {
+            return 0;
+        }
+        try {
+            return Integer.parseInt(sequenceText);
+        } catch (NumberFormatException ignored) {
+            return 0;
+        }
+    }
+
+    private boolean isBatchNoExists(String batchNo) {
+        if (StringUtils.isEmpty(batchNo)) {
+            return false;
+        }
+        Long inventoryCount = stockInventoryMapper.selectCount(
+                Wrappers.<StockInventory>lambdaQuery().eq(StockInventory::getBatchNo, batchNo));
+        if (inventoryCount != null && inventoryCount > 0) {
+            return true;
+        }
+        return stockInRecordService.count(
+                Wrappers.<StockInRecord>lambdaQuery().eq(StockInRecord::getBatchNo, batchNo)) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addStockOutRecordOnly(StockInventoryDto stockInventoryDto) {
+        LambdaQueryWrapper<StockInventory> eq = new LambdaQueryWrapper<>();
+        eq.eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId());
+        if (StringUtils.isEmpty(stockInventoryDto.getBatchNo())) {
+            eq.isNull(StockInventory::getBatchNo);
+        } else {
+            eq.eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo());
+        }
+        StockInventory stockInventory = stockInventoryMapper.selectOne(eq);
+        if (stockInventory == null) {
+            throw new ServiceException("搴撳瓨璁板綍涓嶅瓨鍦�");
+        }
+        BigDecimal lockedQty = stockInventory.getLockedQuantity();
+        if (lockedQty == null) {
+            lockedQty = BigDecimal.ZERO;
+        }
+        BigDecimal pendingOut = stockInventoryMapper.selectPendingOutQuantity(
+                stockInventoryDto.getProductModelId(),
+                stockInventoryDto.getBatchNo(),
+                "0"
+        );
+        if (pendingOut == null) {
+            pendingOut = BigDecimal.ZERO;
+        }
+        BigDecimal availableQty = stockInventory.getQualitity().subtract(lockedQty).subtract(pendingOut);
+        if (stockInventoryDto.getQualitity().compareTo(availableQty) > 0) {
+            throw new ServiceException("鐢宠鏁伴噺瓒呰繃鍙敤搴撳瓨锛屽綋鍓嶅彲鐢ㄥ簱瀛樹负锛�" + availableQty);
+        }
+        StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
+        stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId());
+        stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType());
+        stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
+        stockOutRecordDto.setBatchNo(stockInventoryDto.getBatchNo());
+        stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
+        stockOutRecordDto.setType("0");
+        stockOutRecordDto.setRemark(stockInventoryDto.getRemark());
+        stockOutRecordService.add(stockOutRecordDto);
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
     public R importStockInventory(MultipartFile file) {
         try {
-            // 鏌ヨ鎵�鏈夌殑浜у搧
+            // 鏌ヨ鎵�鏈夌殑浜у搧骞舵瀯寤烘槧灏勶紝鎻愰珮鏌ユ壘鏁堢巼
             List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectProduct();
+            Map<String, SalesLedgerProduct> productMap = new HashMap<>();
+            for (SalesLedgerProduct product : salesLedgerProducts) {
+                // 浣跨敤浜у搧绫诲埆鍜岃鏍煎瀷鍙蜂綔涓洪敭
+                String key = product.getProductCategory() + "|" + product.getSpecificationModel();
+                productMap.put(key, product);
+            }
 
             ExcelUtil<StockInventoryExportData> util = new ExcelUtil<StockInventoryExportData>(StockInventoryExportData.class);
             List<StockInventoryExportData> list = util.importExcel(file.getInputStream());
 
             // 璁板綍鏈壘鍒板尮閰嶉」鐨勬暟鎹�
             List<String> unmatchedRecords = new ArrayList<>();
+            // 璁板綍澶勭悊缁撴灉
+            int successCount = 0;
 
-            list.forEach(dto -> {
-                boolean matched = false;
-                for (SalesLedgerProduct item : salesLedgerProducts) {
-                    if (item.getProductCategory().equals(dto.getProductName()) &&
-                            item.getSpecificationModel().equals(dto.getModel())) {
+            for (StockInventoryExportData dto : list) {
+                // 鏋勫缓鏌ユ壘閿�
+                String key = dto.getProductName() + "|" + dto.getModel();
+                SalesLedgerProduct matchedProduct = productMap.get(key);
+
+                if (matchedProduct != null) {
+                    // 澶勭悊鍚堟牸搴撳瓨
+                    if (dto.getQualifiedQuantity() != null && dto.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) {
                         StockInventoryDto stockInventoryDto = new StockInventoryDto();
                         stockInventoryDto.setRecordId(0L);
                         stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode());
-                        stockInventoryDto.setQualitity(dto.getQualitity());
+                        stockInventoryDto.setQualitity(dto.getQualifiedQuantity());
                         stockInventoryDto.setRemark(dto.getRemark());
                         stockInventoryDto.setWarnNum(dto.getWarnNum());
-                        if (ObjectUtils.isNotEmpty(dto.getLockedQuantity())&&dto.getLockedQuantity().compareTo(dto.getQualitity())>0) {
-                            throw new RuntimeException("鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫簱瀛樻暟閲�");
+
+                        // 楠岃瘉鍚堟牸鍐荤粨鏁伴噺
+                        if (ObjectUtils.isNotEmpty(dto.getQualifiedLockedQuantity())) {
+                            if (dto.getQualifiedLockedQuantity().compareTo(dto.getQualifiedQuantity()) > 0) {
+                                throw new RuntimeException("鍚堟牸鍐荤粨鏁伴噺涓嶈兘瓒呰繃鏈瀵煎叆鐨勫悎鏍煎簱瀛樻暟閲�");
+                            }
+                            stockInventoryDto.setLockedQuantity(dto.getQualifiedLockedQuantity());
+                        } else {
+                            stockInventoryDto.setLockedQuantity(BigDecimal.ZERO);
                         }
-                        stockInventoryDto.setLockedQuantity(dto.getLockedQuantity());
-                        stockInventoryDto.setProductModelId(item.getProductModelId());
+
+                        stockInventoryDto.setProductModelId(matchedProduct.getProductModelId());
                         this.addstockInventory(stockInventoryDto);
-                        matched = true;
-                        break; // 鎵惧埌鍖归厤椤瑰悗璺冲嚭寰幆
+                        successCount++;
                     }
+
+                    // 澶勭悊涓嶅悎鏍煎簱瀛�
+                    if (dto.getUnQualifiedQuantity() != null && dto.getUnQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) {
+                        StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
+                        stockUninventoryDto.setRecordId(0L);
+                        stockUninventoryDto.setRecordType(StockInUnQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_IN.getCode());
+                        stockUninventoryDto.setQualitity(dto.getUnQualifiedQuantity());
+                        stockUninventoryDto.setRemark(dto.getRemark());
+
+                        // 楠岃瘉涓嶅悎鏍煎喕缁撴暟閲�
+                        if (ObjectUtils.isNotEmpty(dto.getUnQualifiedLockedQuantity())) {
+                            if (dto.getUnQualifiedLockedQuantity().compareTo(dto.getUnQualifiedQuantity()) > 0) {
+                                throw new RuntimeException("涓嶅悎鏍煎喕缁撴暟閲忎笉鑳借秴杩囨湰娆″鍏ョ殑涓嶅悎鏍煎簱瀛樻暟閲�");
+                            }
+                            stockUninventoryDto.setLockedQuantity(dto.getUnQualifiedLockedQuantity());
+                        } else {
+                            stockUninventoryDto.setLockedQuantity(BigDecimal.ZERO);
+                        }
+
+                        stockUninventoryDto.setProductModelId(matchedProduct.getProductModelId());
+                        stockUninventoryService.addStockUninventory(stockUninventoryDto);
+                        successCount++;
+                    }
+                } else {
+                    // 璁板綍鏈尮閰嶇殑浜у搧
+                    String unmatchedRecord = "浜у搧鍚嶇О锛�" + dto.getProductName() + "锛屽瀷鍙凤細" + dto.getModel();
+                    unmatchedRecords.add(unmatchedRecord);
                 }
-                if (!matched) {
-                    // 璁板綍鏈尮閰嶇殑鏁版嵁
-                    String unmatchedInfo = String.format("浜у搧鍚嶇О锛�%s锛岃鏍煎瀷鍙凤細%s",
-                            dto.getProductName(), dto.getModel());
-                    unmatchedRecords.add(unmatchedInfo);
-                }
-            });
+            }
+
             // 鏋勫缓杩斿洖淇℃伅
             StringBuilder message = new StringBuilder();
             if (!unmatchedRecords.isEmpty()) {
-                message.append("浠ヤ笅浜у搧鏈壘鍒板尮閰嶉」锛歕n");
+                message.append("瀵煎叆鎴愬姛 " + successCount + " 鏉¤褰曪紝浠ヤ笅浜у搧鏈壘鍒板尮閰嶉」锛歕n");
                 for (String record : unmatchedRecords) {
                     message.append(record).append("\n");
                 }
-                throw new RuntimeException(message.toString());
+                return R.ok(message.toString());
             }
+
+            return R.ok("瀵煎叆鎴愬姛锛屽叡澶勭悊 " + successCount + " 鏉¤褰�");
         } catch (Exception e) {
-            e.printStackTrace();
+            log.error("瀵煎叆搴撳瓨澶辫触", e);
             return R.fail("瀵煎叆澶辫触锛�" + e.getMessage());
         }
-        return R.ok("瀵煎叆鎴愬姛");
     }
 
 
@@ -207,4 +429,9 @@
         stockInventory.setLockedQuantity(stockInventory.getLockedQuantity().subtract(stockInventoryDto.getLockedQuantity()));
         return this.updateById(stockInventory);
     }
+
+    @Override
+    public List<StockInventory> getByModelId(Long modelId) {
+        return stockInventoryMapper.getByModelId(modelId);
+    }
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
index e01fe5d..cead7fc 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
@@ -4,11 +4,13 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.enums.ReviewStatusEnum;
 import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
 import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.EnumUtil;
 import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.stock.dto.StockInventoryDto;
@@ -24,9 +26,13 @@
 import com.ruoyi.stock.pojo.StockUninventory;
 import com.ruoyi.stock.service.StockOutRecordService;
 import lombok.AllArgsConstructor;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -38,11 +44,11 @@
  * @since 2026-01-21 05:27:04
  */
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 public class StockOutRecordServiceImpl extends ServiceImpl<StockOutRecordMapper, StockOutRecord> implements StockOutRecordService {
-    private StockOutRecordMapper stockOutRecordMapper;
-    private StockInventoryMapper stockInventoryMapper;
-    private StockUninventoryMapper stockUninventoryMapper;
+    private final StockOutRecordMapper stockOutRecordMapper;
+    private final StockInventoryMapper stockInventoryMapper;
+    private final StockUninventoryMapper stockUninventoryMapper;
 
     @Override
     public IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto) {
@@ -51,7 +57,7 @@
 
     @Override
     public int add(StockOutRecordDto stockOutRecordDto) {
-        String no = OrderUtils.countTodayByCreateTime(stockOutRecordMapper, "CK");
+        String no = OrderUtils.countTodayByCreateTime(stockOutRecordMapper, "CK","outbound_batches");
         stockOutRecordDto.setOutboundBatches(no);
         StockInRecord stockInRecord = new StockInRecord();
         BeanUtils.copyProperties(stockOutRecordDto, stockInRecord);
@@ -76,23 +82,39 @@
         for (Long id : ids) {
             StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
             if (stockOutRecord.getType().equals("0")) {
-                StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, stockOutRecord.getProductModelId()));
+                LambdaQueryWrapper<StockInventory> wrapper = new LambdaQueryWrapper<StockInventory>()
+                    .eq(StockInventory::getProductModelId, stockOutRecord.getProductModelId());
+                if (StringUtils.isEmpty(stockOutRecord.getBatchNo())) {
+                    wrapper.isNull(StockInventory::getBatchNo);
+                } else {
+                    wrapper.eq(StockInventory::getBatchNo, stockOutRecord.getBatchNo());
+                }
+                StockInventory stockInventory = stockInventoryMapper.selectOne(wrapper);
                 if (stockInventory == null) {
                     throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
                 }else {
                     StockInventoryDto stockInRecordDto = new StockInventoryDto();
                     stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                     stockInRecordDto.setQualitity(stockOutRecord.getStockOutNum());
+                    stockInRecordDto.setBatchNo(stockInventory.getBatchNo());
                     stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
                 }
             }else if (stockOutRecord.getType().equals("1")) {
-                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(new LambdaQueryWrapper<StockUninventory>().eq(StockUninventory::getProductModelId, stockOutRecord.getProductModelId()));
+                LambdaQueryWrapper<StockUninventory> wrapper = new LambdaQueryWrapper<StockUninventory>()
+                        .eq(StockUninventory::getProductModelId, stockOutRecord.getProductModelId());
+                if (StringUtils.isEmpty(stockOutRecord.getBatchNo())) {
+                    wrapper.isNull(StockUninventory::getBatchNo);
+                } else {
+                    wrapper.eq(StockUninventory::getBatchNo, stockOutRecord.getBatchNo());
+                }
+                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(wrapper);
                 if (stockUninventory == null) {
                     throw new BaseException("搴撳瓨璁板綍涓病鏈夊搴旂殑浜у搧,鏃犳硶鍒犻櫎!!!");
                 }else {
                     StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                     stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                     stockUninventoryDto.setQualitity(stockOutRecord.getStockOutNum());
+                    stockUninventoryDto.setBatchNo(stockUninventory.getBatchNo());
                     stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
                 }
             }
@@ -113,4 +135,90 @@
         ExcelUtil<StockOutRecordExportData> util = new ExcelUtil<>(StockOutRecordExportData.class);
         util.exportExcel(response,list, "鍑哄簱璁板綍淇℃伅");
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int batchDeletePending(List<Long> ids) {
+        for (Long id : ids) {
+            StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+            if (stockOutRecord == null) {
+                throw new BaseException("鍑哄簱璁板綍涓嶅瓨鍦�,鏃犳硶鍒犻櫎!!!");
+            }
+            if (stockOutRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockOutRecord.getApprovalStatus())) {
+                throw new BaseException("鍙湁寰呭鎵圭姸鎬佺殑璁板綍鎵嶈兘鍒犻櫎,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+            }
+        }
+        return stockOutRecordMapper.deleteBatchIds(ids);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int batchApprove(List<Long> ids, Integer approvalStatus) {
+        if (CollectionUtils.isEmpty(ids)) {
+            throw new BaseException("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        if (approvalStatus == null || (!ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus) && !ReviewStatusEnum.REJECTED.getCode().equals(approvalStatus))) {
+            throw new BaseException("瀹℃壒鐘舵�佸�兼棤鏁�");
+        }
+        for (Long id : ids) {
+            StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
+            if (stockOutRecord == null) {
+                throw new BaseException("鍑哄簱璁板綍涓嶅瓨鍦�,鏃犳硶瀹℃壒!!!");
+            }
+            if (stockOutRecord.getApprovalStatus() != null && !ReviewStatusEnum.PENDING_REVIEW.getCode().equals(stockOutRecord.getApprovalStatus())) {
+                throw new BaseException("鍙湁寰呭鎵圭姸鎬佺殑璁板綍鎵嶈兘瀹℃壒,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+            }
+            stockOutRecord.setApprovalStatus(approvalStatus);
+            stockOutRecordMapper.updateById(stockOutRecord);
+            // 瀹℃壒閫氳繃鏃讹紝鎵e噺搴撳瓨
+            if (ReviewStatusEnum.APPROVED.getCode().equals(approvalStatus)) {
+                if ("0".equals(stockOutRecord.getType())) {
+                    // 鍚堟牸鍑哄簱 -> 鍏堟煡搴撳瓨鏄惁瀛樺湪锛屽瓨鍦ㄦ墠鎵e噺
+                    StockInventory stockInventory = getStockInventory(stockOutRecord.getProductModelId(), stockOutRecord.getBatchNo());
+                    if (stockInventory == null) {
+                        throw new BaseException("鍚堟牸搴撳瓨璁板綍涓嶅瓨鍦�,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+                    }
+                    StockInventoryDto stockInventoryDto = new StockInventoryDto();
+                    stockInventoryDto.setProductModelId(stockOutRecord.getProductModelId());
+                    stockInventoryDto.setBatchNo(stockOutRecord.getBatchNo());
+                    stockInventoryDto.setQualitity(stockOutRecord.getStockOutNum());
+                    stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
+                } else if ("1".equals(stockOutRecord.getType())) {
+                    // 涓嶅悎鏍煎嚭搴� -> 鍏堟煡搴撳瓨鏄惁瀛樺湪锛屽瓨鍦ㄦ墠鎵e噺
+                    StockUninventory stockUninventory = getStockUninventory(stockOutRecord.getProductModelId(), stockOutRecord.getBatchNo());
+                    if (stockUninventory == null) {
+                        throw new BaseException("涓嶅悎鏍煎簱瀛樿褰曚笉瀛樺湪,鍑哄簱鎵规:" + stockOutRecord.getOutboundBatches());
+                    }
+                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
+                    stockUninventoryDto.setProductModelId(stockOutRecord.getProductModelId());
+                    stockUninventoryDto.setBatchNo(stockOutRecord.getBatchNo());
+                    stockUninventoryDto.setQualitity(stockOutRecord.getStockOutNum());
+                    stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
+                }
+            }
+        }
+        return ids.size();
+    }
+
+    private StockInventory getStockInventory(Long productModelId, String batchNo) {
+        LambdaQueryWrapper<StockInventory> eq = new LambdaQueryWrapper<>();
+        eq.eq(StockInventory::getProductModelId, productModelId);
+        if (StringUtils.isEmpty(batchNo)) {
+            eq.isNull(StockInventory::getBatchNo);
+        } else {
+            eq.eq(StockInventory::getBatchNo, batchNo);
+        }
+        return stockInventoryMapper.selectOne(eq);
+    }
+
+    private StockUninventory getStockUninventory(Long productModelId, String batchNo) {
+        LambdaQueryWrapper<StockUninventory> eq = new LambdaQueryWrapper<>();
+        eq.eq(StockUninventory::getProductModelId, productModelId);
+        if (StringUtils.isEmpty(batchNo)) {
+            eq.isNull(StockUninventory::getBatchNo);
+        } else {
+            eq.eq(StockUninventory::getBatchNo, batchNo);
+        }
+        return stockUninventoryMapper.selectOne(eq);
+    }
 }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
index 2d5b8f5..4835b09 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
@@ -1,10 +1,13 @@
 package com.ruoyi.stock.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.stock.dto.StockInRecordDto;
 import com.ruoyi.stock.dto.StockInventoryDto;
@@ -12,15 +15,20 @@
 import com.ruoyi.stock.dto.StockUninventoryDto;
 import com.ruoyi.stock.execl.StockUnInventoryExportData;
 import com.ruoyi.stock.mapper.StockUninventoryMapper;
+import com.ruoyi.stock.pojo.StockInventory;
 import com.ruoyi.stock.pojo.StockUninventory;
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.stock.service.StockOutRecordService;
 import com.ruoyi.stock.service.StockUninventoryService;
 import lombok.AllArgsConstructor;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -32,12 +40,13 @@
  * @since 2026-01-22 10:17:45
  */
 @Service
-@AllArgsConstructor
+@RequiredArgsConstructor
 public class StockUninventoryServiceImpl extends ServiceImpl<StockUninventoryMapper, StockUninventory> implements StockUninventoryService {
 
-    private StockUninventoryMapper stockUninventoryMapper;
-    private StockOutRecordService stockOutRecordService;
-    private StockInRecordService stockInRecordService;
+
+    private final StockUninventoryMapper stockUninventoryMapper;
+    private final StockOutRecordService stockOutRecordService;
+    private final StockInRecordService stockInRecordService;
 
     @Override
     public IPage<StockUninventoryDto> pageStockUninventory(Page page, StockUninventoryDto stockUninventoryDto) {
@@ -47,21 +56,32 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Integer addStockUninventory(StockUninventoryDto stockUninventoryDto) {
+        LambdaQueryWrapper<StockUninventory> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId());
+        if (StringUtils.isEmpty(stockUninventoryDto.getBatchNo())) {
+            stockUninventoryDto.setBatchNo(null);
+            wrapper.isNull(StockUninventory::getBatchNo);
+        } else {
+            wrapper.eq(StockUninventory::getBatchNo, stockUninventoryDto.getBatchNo());
+        }
         //鏂板鍏ュ簱璁板綍鍐嶆坊鍔犲簱瀛�
         StockInRecordDto stockInRecordDto = new StockInRecordDto();
         stockInRecordDto.setRecordId(stockUninventoryDto.getRecordId());
         stockInRecordDto.setRecordType(stockUninventoryDto.getRecordType());
         stockInRecordDto.setStockInNum(stockUninventoryDto.getQualitity());
+        stockInRecordDto.setBatchNo(stockUninventoryDto.getBatchNo());
         stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
         stockInRecordDto.setType("1");
         stockInRecordService.add(stockInRecordDto);
         //鍐嶈繘琛屾柊澧炲簱瀛樻暟閲忓簱瀛�
         //鍏堟煡璇㈠簱瀛樿〃涓殑浜у搧鏄惁瀛樺湪锛屼笉瀛樺湪鏂板锛屽瓨鍦ㄦ洿鏂�
-        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
+        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(wrapper);
         if (ObjectUtils.isEmpty(oldStockUnInventory)) {
             StockUninventory newStockUnInventory = new StockUninventory();
             newStockUnInventory.setProductModelId(stockUninventoryDto.getProductModelId());
             newStockUnInventory.setQualitity(stockUninventoryDto.getQualitity());
+            newStockUnInventory.setLockedQuantity(stockUninventoryDto.getLockedQuantity());
+            newStockUnInventory.setBatchNo(stockUninventoryDto.getBatchNo());
             newStockUnInventory.setVersion(1);
             newStockUnInventory.setRemark(stockUninventoryDto.getRemark());
             stockUninventoryMapper.insert(newStockUnInventory);
@@ -81,6 +101,7 @@
         stockOutRecordDto.setRecordType(stockUninventoryDto.getRecordType());
         stockOutRecordDto.setStockOutNum(stockUninventoryDto.getQualitity());
         stockOutRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
+        stockOutRecordDto.setBatchNo(stockUninventoryDto.getBatchNo());
         stockOutRecordDto.setType("1");
         stockOutRecordService.add(stockOutRecordDto);
         StockUninventory oldStockInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
@@ -93,6 +114,63 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Integer addStockInRecordOnly(StockUninventoryDto stockUninventoryDto) {
+        StockInRecordDto stockInRecordDto = new StockInRecordDto();
+        stockInRecordDto.setRecordId(stockUninventoryDto.getRecordId());
+        stockInRecordDto.setRecordType(stockUninventoryDto.getRecordType());
+        stockInRecordDto.setStockInNum(stockUninventoryDto.getQualitity());
+        stockInRecordDto.setBatchNo(stockUninventoryDto.getBatchNo());
+        stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
+        stockInRecordDto.setType("1");
+        stockInRecordDto.setRemark(stockUninventoryDto.getRemark());
+        stockInRecordService.add(stockInRecordDto);
+        return 1;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Integer addStockOutRecordOnly(StockUninventoryDto stockUninventoryDto) {
+        LambdaQueryWrapper<StockUninventory> eq = new LambdaQueryWrapper<>();
+        eq.eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId());
+        if (StringUtils.isEmpty(stockUninventoryDto.getBatchNo())) {
+            eq.isNull(StockUninventory::getBatchNo);
+        } else {
+            eq.eq(StockUninventory::getBatchNo, stockUninventoryDto.getBatchNo());
+        }
+        StockUninventory stockUninventory = stockUninventoryMapper.selectOne(eq);
+        if (stockUninventory == null) {
+            throw new BaseException("搴撳瓨璁板綍涓嶅瓨鍦�");
+        }
+        BigDecimal lockedQty = stockUninventory.getLockedQuantity();
+        if (lockedQty == null) {
+            lockedQty = BigDecimal.ZERO;
+        }
+        BigDecimal pendingOut = stockUninventoryMapper.selectPendingOutQuantity(
+                stockUninventoryDto.getProductModelId(),
+                stockUninventoryDto.getBatchNo(),
+                "1"
+        );
+        if (pendingOut == null) {
+            pendingOut = BigDecimal.ZERO;
+        }
+        BigDecimal availableQty = stockUninventory.getQualitity().subtract(lockedQty).subtract(pendingOut);
+        if (stockUninventoryDto.getQualitity().compareTo(availableQty) > 0) {
+            throw new BaseException("鐢宠鏁伴噺瓒呰繃鍙敤搴撳瓨锛屽綋鍓嶅彲鐢ㄥ簱瀛樹负锛�" + availableQty);
+        }
+        StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
+        stockOutRecordDto.setRecordId(stockUninventoryDto.getRecordId());
+        stockOutRecordDto.setRecordType(stockUninventoryDto.getRecordType());
+        stockOutRecordDto.setStockOutNum(stockUninventoryDto.getQualitity());
+        stockOutRecordDto.setBatchNo(stockUninventoryDto.getBatchNo());
+        stockOutRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
+        stockOutRecordDto.setType("1");
+        stockOutRecordDto.setRemark(stockUninventoryDto.getRemark());
+        stockOutRecordService.add(stockOutRecordDto);
+        return 1;
+    }
+
+    @Override
     public void exportStockUninventory(HttpServletResponse response, StockUninventoryDto stockUninventoryDto) {
         List<StockUnInventoryExportData> list = stockUninventoryMapper.listStockInventoryExportData(stockUninventoryDto);
         ExcelUtil<StockUnInventoryExportData> util = new ExcelUtil<>(StockUnInventoryExportData.class);
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/BomImportDto.java b/src/main/java/com/ruoyi/technology/bean/dto/BomImportDto.java
new file mode 100644
index 0000000..865a612
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/BomImportDto.java
@@ -0,0 +1,37 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class BomImportDto {
+
+    @Excel(name = "鐖堕」浜у搧缂栧彿")
+    private String parentCode;
+
+    @Excel(name = "鐖堕」浜у搧鍚嶇О")
+    private String parentName;
+
+    @Excel(name = "鐖堕」浜у搧瑙勬牸")
+    private String parentSpec;
+
+    @Excel(name = "瀛愰」浜у搧缂栧彿")
+    private String childCode;
+
+    @Excel(name = "瀛愰」浜у搧鍚嶇О")
+    private String childName;
+
+    @Excel(name = "瀛愰」浜у搧瑙勬牸")
+    private String childSpec;
+
+    @Excel(name = "鍗曚綅鐢ㄩ噺")
+    private BigDecimal unitQty;
+
+    @Excel(name = "鎶曟枡宸ュ簭")
+    private String process;
+
+    @Excel(name = "澶囨敞")
+    private String remark;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java
new file mode 100644
index 0000000..1a98275
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java
@@ -0,0 +1,17 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyBom;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class TechnologyBomDto extends TechnologyBom {
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String productModelName;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java
new file mode 100644
index 0000000..ca2b439
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java
@@ -0,0 +1,31 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TechnologyBomStructureDto extends TechnologyBomStructure {
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "浜у搧ID")
+    private Long productId;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    private String tempId;
+
+    private String parentTempId;
+
+    private List<TechnologyBomStructureDto> children;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java
new file mode 100644
index 0000000..3012eca
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyOperation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "TechnologyOperationDto瀵硅薄", description = "宸ュ簭鏌ヨ鍙傛暟")
+public class TechnologyOperationDto extends TechnologyOperation {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java
new file mode 100644
index 0000000..bebeb62
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java
@@ -0,0 +1,29 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TechnologyOperationParamDto extends TechnologyOperationParam {
+
+    @Schema(description = "鍙傛暟缂栫爜")
+    private String paramCode;
+
+    @Schema(description = "鍙傛暟鍚嶇О")
+    private String paramName;
+
+    @Schema(description = "鍙傛暟绫诲瀷")
+    private Byte paramType;
+
+    @Schema(description = "鍙傛暟鏍煎紡")
+    private String paramFormat;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鏄惁蹇呭~")
+    private Byte isRequired;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java
new file mode 100644
index 0000000..2a45544
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java
@@ -0,0 +1,10 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyParam;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class TechnologyParamDto extends TechnologyParam {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java
new file mode 100644
index 0000000..fbe1b89
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java
@@ -0,0 +1,21 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyRouting;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "TechnologyRoutingDto瀵硅薄", description = "宸ヨ壓璺嚎鏌ヨ鍙傛暟")
+public class TechnologyRoutingDto extends TechnologyRouting {
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍚嶇О")
+    private String model;
+
+    @Schema(description = "BOM缂栧彿")
+    private String bomNo;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java
new file mode 100644
index 0000000..87c0517
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "TechnologyRoutingOperationDto瀵硅薄", description = "宸ヨ壓璺嚎宸ュ簭鏌ヨ鍙傛暟")
+public class TechnologyRoutingOperationDto extends TechnologyRoutingOperation {
+
+    @Schema(description = "宸ヨ壓璺嚎id锛堝吋瀹规棫鍙傛暟 routeId锛�")
+    private Long routeId;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamDto.java
new file mode 100644
index 0000000..becfa96
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.technology.bean.dto;
+
+import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Schema(name = "TechnologyRoutingOperationParamDto瀵硅薄", description = "宸ヨ壓璺嚎宸ュ簭鍙傛暟鏌ヨ鍙傛暟")
+public class TechnologyRoutingOperationParamDto extends TechnologyRoutingOperationParam {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamSyncDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamSyncDto.java
new file mode 100644
index 0000000..e7deb3d
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationParamSyncDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.technology.bean.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(name = "TechnologyRoutingOperationParamSyncDto瀵硅薄", description = "宸ヨ壓璺嚎宸ュ簭鍙傛暟鍚屾鍙傛暟")
+public class TechnologyRoutingOperationParamSyncDto {
+
+    @Schema(description = "宸ヨ壓璺嚎宸ュ簭id")
+    private Long technologyRoutingOperationId;
+
+    @Schema(description = "鏄惁瑕嗙洊褰撳墠宸ュ簭宸插瓨鍦ㄥ弬鏁帮紝榛樿true")
+    private Boolean replaceExisting;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java
new file mode 100644
index 0000000..e41540d
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java
@@ -0,0 +1,27 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TechnologyBomStructureVo extends TechnologyBomStructure {
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String operationName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "浜у搧ID")
+    private Long productId;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String model;
+
+    private List<TechnologyBomStructureVo> children;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java
new file mode 100644
index 0000000..c81e401
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java
@@ -0,0 +1,15 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyBom;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class TechnologyBomVo extends TechnologyBom {
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍨嬪彿")
+    private String productModelName;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java
new file mode 100644
index 0000000..e079697
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java
@@ -0,0 +1,29 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TechnologyOperationParamVo extends TechnologyOperationParam {
+
+    @Schema(description = "鍙傛暟缂栫爜")
+    private String paramCode;
+
+    @Schema(description = "鍙傛暟鍚嶇О")
+    private String paramName;
+
+    @Schema(description = "鍙傛暟绫诲瀷")
+    private Byte paramType;
+
+    @Schema(description = "鍙傛暟鏍煎紡")
+    private String paramFormat;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鏄惁蹇呭~")
+    private Byte isRequired;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java
new file mode 100644
index 0000000..1433990
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java
@@ -0,0 +1,12 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyOperation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "TechnologyOperationVo瀵硅薄", description = "宸ュ簭杩斿洖瀵硅薄")
+public class TechnologyOperationVo extends TechnologyOperation {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java
new file mode 100644
index 0000000..21e5299
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java
@@ -0,0 +1,8 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyParam;
+import lombok.Data;
+
+@Data
+public class TechnologyParamVo extends TechnologyParam {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationParamVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationParamVo.java
new file mode 100644
index 0000000..4fb8620
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationParamVo.java
@@ -0,0 +1,12 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Schema(name = "TechnologyRoutingOperationParamVo瀵硅薄", description = "宸ヨ壓璺嚎宸ュ簭鍙傛暟杩斿洖瀵硅薄")
+public class TechnologyRoutingOperationParamVo extends TechnologyRoutingOperationParam {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java
new file mode 100644
index 0000000..a75cdfa
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java
@@ -0,0 +1,27 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "TechnologyRoutingOperationVo瀵硅薄", description = "宸ヨ壓璺嚎宸ュ簭杩斿洖瀵硅薄")
+public class TechnologyRoutingOperationVo extends TechnologyRoutingOperation {
+
+    @Schema(description = "宸ュ簭鍚嶇О")
+    private String technologyOperationName;
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍚嶇О")
+    private String model;
+
+    @Schema(description = "瑙勬牸鍚嶇О")
+    private String specificationName;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java
new file mode 100644
index 0000000..b0763db
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java
@@ -0,0 +1,21 @@
+package com.ruoyi.technology.bean.vo;
+
+import com.ruoyi.technology.pojo.TechnologyRouting;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(name = "TechnologyRoutingVo瀵硅薄", description = "宸ヨ壓璺嚎杩斿洖瀵硅薄")
+public class TechnologyRoutingVo extends TechnologyRouting {
+
+    @Schema(description = "浜у搧鍚嶇О")
+    private String productName;
+
+    @Schema(description = "瑙勬牸鍚嶇О")
+    private String model;
+
+    @Schema(description = "BOM缂栧彿")
+    private String bomNo;
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java
new file mode 100644
index 0000000..226973f
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java
@@ -0,0 +1,97 @@
+package com.ruoyi.technology.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.BomImportDto;
+import com.ruoyi.technology.bean.dto.TechnologyBomDto;
+import com.ruoyi.technology.bean.vo.TechnologyBomVo;
+import com.ruoyi.technology.pojo.TechnologyBom;
+import com.ruoyi.technology.service.TechnologyBomService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/technologyBom")
+@RequiredArgsConstructor
+@Tag(name = "鍩虹BOM")
+public class TechnologyBomController {
+
+    private final TechnologyBomService technologyBomService;
+
+    @GetMapping("/listPage")
+    @Log(title = "Technology BOM page", businessType = BusinessType.OTHER)
+    @Operation(summary = "BOM鍒嗛〉鏌ヨ")
+    public R<IPage<TechnologyBomVo>> listPage(Page<TechnologyBomDto> page, TechnologyBomDto technologyBomDto) {
+        return R.ok(technologyBomService.listPage(page, technologyBomDto));
+    }
+
+    @PostMapping("/add")
+    @Log(title = "Add technology BOM", businessType = BusinessType.INSERT)
+    @Operation(summary = "鏂板BOM")
+    public R add(@RequestBody TechnologyBom technologyBom) {
+        return technologyBomService.add(technologyBom);
+    }
+
+    @PutMapping("/update")
+    @Log(title = "Update technology BOM", businessType = BusinessType.UPDATE)
+    @Operation(summary = "淇敼BOM")
+    public R update(@RequestBody TechnologyBom technologyBom) {
+        return technologyBomService.update(technologyBom);
+    }
+
+    @DeleteMapping("/batchDelete")
+    @Log(title = "Delete technology BOM", businessType = BusinessType.DELETE)
+    @Operation(summary = "鎵归噺鍒犻櫎BOM")
+    public R batchDelete(@RequestBody List<Long> ids) {
+        return R.ok(technologyBomService.batchDelete(ids));
+    }
+
+    @GetMapping("/getByModel")
+    @Log(title = "List BOM by model", businessType = BusinessType.OTHER)
+    @Operation(summary = "鏍规嵁瑙勬牸鏌ヨBOM")
+    public R<List<TechnologyBomVo>> getByModel(Long productModelId) {
+        return R.ok(technologyBomService.listByModel(productModelId));
+    }
+
+    @PostMapping("/uploadBom")
+    @PreAuthorize("@ss.hasPermi('product:bom:import')")
+    @Log(title = "鏍规嵁Excel瀵煎叆BOM", businessType = BusinessType.IMPORT)
+    @Operation(summary = "鏍规嵁Excel瀵煎叆BOM")
+    public R uploadBom(@RequestParam("file") MultipartFile file) {
+        return technologyBomService.uploadBom(file);
+    }
+
+    @PostMapping("/exportBom")
+    @PreAuthorize("@ss.hasPermi('product:bom:export')")
+    @Operation(summary = "瀵煎嚭BOM鏂囦欢")
+    @Log(title = "瀵煎嚭BOM鏂囦欢", businessType = BusinessType.EXPORT)
+    public void exportBom(HttpServletResponse response, @RequestParam Integer bomId) {
+        technologyBomService.exportBom(response, bomId);
+    }
+
+    @GetMapping("/downloadTemplate")
+    @Log(title = "涓嬭浇BOM瀵煎叆妯℃澘", businessType = BusinessType.EXPORT)
+    @Operation(summary = "涓嬭浇BOM瀵煎叆妯℃澘")
+    public void importTemplate(HttpServletResponse response) {
+        ExcelUtil<BomImportDto> excelUtil = new ExcelUtil<>(BomImportDto.class);
+        excelUtil.importTemplateExcel(response, "BOM瀵煎叆妯℃澘");
+    }
+
+    @PostMapping("/copy")
+    @Log(title = "Copy technology BOM", businessType = BusinessType.INSERT)
+    @Operation(summary = "澶嶅埗BOM")
+    public R copy(@RequestBody TechnologyBom technologyBom) {
+        return technologyBomService.copy(technologyBom);
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java
new file mode 100644
index 0000000..3d9048e
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java
@@ -0,0 +1,33 @@
+package com.ruoyi.technology.controller;
+
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto;
+import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo;
+import com.ruoyi.technology.service.TechnologyBomStructureService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/technologyBomStructure")
+@RequiredArgsConstructor
+@Tag(name = "BOM缁撴瀯")
+public class TechnologyBomStructureController {
+
+    private final TechnologyBomStructureService technologyBomStructureService;
+
+    @PostMapping
+    @Operation(summary = "鏂板鎴栦慨鏀笲OM缁撴瀯")
+    public R addOrUpdate(@RequestBody TechnologyBomStructureDto technologyBomStructureDto) {
+        return R.ok(technologyBomStructureService.addTechnologyBomStructure(technologyBomStructureDto));
+    }
+
+    @GetMapping("/listByBomId/{bomId}")
+    @Operation(summary = "鏍规嵁BOM鏌ヨ缁撴瀯鏍�")
+    public R<List<TechnologyBomStructureVo>> listByBomId(@PathVariable Long bomId) {
+        return R.ok(technologyBomStructureService.listByBomId(bomId));
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
new file mode 100644
index 0000000..c24c93f
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
@@ -0,0 +1,59 @@
+package com.ruoyi.technology.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyOperationDto;
+import com.ruoyi.technology.bean.vo.TechnologyOperationVo;
+import com.ruoyi.technology.service.TechnologyOperationService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@Tag(name = "宸ュ簭绠$悊")
+@RequestMapping("/technologyOperation")
+@RequiredArgsConstructor
+public class TechnologyOperationController {
+
+    private final TechnologyOperationService technologyOperationService;
+
+    @GetMapping("/listPage")
+    @Log(title = "Technology operation page", businessType = BusinessType.OTHER)
+    @Operation(summary = "宸ュ簭鍒嗛〉鏌ヨ")
+    public R<IPage<TechnologyOperationVo>> listPage(Page<TechnologyOperationDto> page, TechnologyOperationDto technologyOperationDto) {
+        return R.ok(technologyOperationService.listPage(page, technologyOperationDto));
+    }
+
+    @PostMapping("/add")
+    @Log(title = "Add technology operation", businessType = BusinessType.INSERT)
+    @Operation(summary = "鏂板宸ュ簭")
+    public R add(@RequestBody TechnologyOperationDto technologyOperationDto) {
+        return technologyOperationService.add(technologyOperationDto);
+    }
+
+    @PutMapping("/update")
+    @Log(title = "Update technology operation", businessType = BusinessType.UPDATE)
+    @Operation(summary = "淇敼宸ュ簭")
+    public R update(@RequestBody com.ruoyi.technology.pojo.TechnologyOperation technologyOperation) {
+        return R.ok(technologyOperationService.updateById(technologyOperation));
+    }
+
+    @DeleteMapping("/batchDelete")
+    @Log(title = "Delete technology operation", businessType = BusinessType.DELETE)
+    @Operation(summary = "鎵归噺鍒犻櫎宸ュ簭")
+    public R batchDelete(@RequestBody List<Long> ids) {
+        return R.ok(technologyOperationService.batchDelete(ids));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "鏌ヨ鍏ㄩ儴宸ュ簭")
+    public R<List<TechnologyOperationVo>> list() {
+        return R.ok(technologyOperationService.listVo());
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
new file mode 100644
index 0000000..061a50c
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
@@ -0,0 +1,44 @@
+package com.ruoyi.technology.controller;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyOperationParamDto;
+import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo;
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import com.ruoyi.technology.service.TechnologyOperationParamService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/technologyOperationParam")
+@Tag(name = "宸ュ簭鍙傛暟")
+@RequiredArgsConstructor
+public class TechnologyOperationParamController {
+
+    private final TechnologyOperationParamService technologyOperationParamService;
+
+    @GetMapping("/list")
+    @Operation(summary = "宸ュ簭鍙傛暟鍒楄〃鏌ヨ")
+    public R<List<TechnologyOperationParamVo>> list(TechnologyOperationParamDto technologyOperationParamDto) {
+        return R.ok(technologyOperationParamService.listOperationParam(technologyOperationParamDto));
+    }
+
+    @PostMapping("/")
+    @Operation(summary = "鏂板鎴栦慨鏀瑰伐搴忓弬鏁�")
+    public R addOrUpdate(@RequestBody TechnologyOperationParam technologyOperationParam) {
+        return R.ok(technologyOperationParamService.saveTechnologyOperationParam(technologyOperationParam));
+    }
+
+    @DeleteMapping("/batchDelete/{id}")
+    @Log(title = "Delete technology operation param", businessType = BusinessType.DELETE)
+    @Operation(summary = "鍒犻櫎宸ュ簭鍙傛暟")
+    public AjaxResult batchDelete(@PathVariable("id") Long id) {
+        return AjaxResult.success(technologyOperationParamService.batchDelete(id));
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java
new file mode 100644
index 0000000..3eb6a84
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java
@@ -0,0 +1,52 @@
+package com.ruoyi.technology.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyParamDto;
+import com.ruoyi.technology.bean.vo.TechnologyParamVo;
+import com.ruoyi.technology.service.TechnologyParamService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/technologyParam")
+@RequiredArgsConstructor
+@Tag(name = "鍩虹鍙傛暟")
+public class TechnologyParamController {
+
+    private final TechnologyParamService technologyParamService;
+
+    @GetMapping("list")
+    @Log(title = "鍩虹鍙傛暟鏁版嵁闆嗗悎", businessType = BusinessType.OTHER)
+    @Operation(summary = "鍩虹鍙傛暟鍒嗛〉鏌ヨ")
+    public R<IPage<TechnologyParamVo>> TechnologyParamDtoList(Page<TechnologyParamDto> page, TechnologyParamDto technologyParamDto) {
+        IPage<TechnologyParamVo> paramList = technologyParamService.baseParamList(page, technologyParamDto);
+        return R.ok(paramList);
+    }
+
+    @PostMapping("/add")
+    @Log(title = "鏂板鍩虹鍙傛暟", businessType = BusinessType.INSERT)
+    @Operation(summary = "鏂板鍩虹鍙傛暟")
+    public R TechnologyParamDtoAdd(@RequestBody TechnologyParamDto TechnologyParamDto) {
+        return R.ok(technologyParamService.addBaseParam(TechnologyParamDto));
+    }
+
+    @PutMapping("/edit")
+    @Log(title = "淇敼鍩虹鍙傛暟", businessType = BusinessType.UPDATE)
+    @Operation(summary = "淇敼鍩虹鍙傛暟")
+    public R TechnologyParamDtoEdit(@RequestBody TechnologyParamDto TechnologyParamDto) {
+        return R.ok(technologyParamService.updateBaseParam(TechnologyParamDto));
+    }
+
+    @DeleteMapping("/remove/{ids}")
+    @Log(title = "鍒犻櫎鍩虹鍙傛暟", businessType = BusinessType.DELETE)
+    @Operation(summary = "鍒犻櫎鍩虹鍙傛暟")
+    public R TechnologyParamDtoRemove(@PathVariable Long[] ids) {
+        return R.ok(technologyParamService.deleteBaseParamByIds(ids));
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingController.java
new file mode 100644
index 0000000..9ab62e1
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingController.java
@@ -0,0 +1,70 @@
+package com.ruoyi.technology.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingVo;
+import com.ruoyi.technology.pojo.TechnologyRouting;
+import com.ruoyi.technology.service.TechnologyRoutingService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/technologyRouting")
+@Tag(name = "宸ヨ壓璺嚎")
+@RequiredArgsConstructor
+public class TechnologyRoutingController {
+
+    private final TechnologyRoutingService technologyRoutingService;
+
+    /**
+     * 鍒嗛〉鏌ヨ宸ヨ壓璺嚎銆�
+     */
+    @GetMapping("/page")
+    @Operation(summary = "宸ヨ壓璺嚎鍒嗛〉鏌ヨ")
+    public R<IPage<TechnologyRoutingVo>> page(Page<TechnologyRoutingDto> page, TechnologyRoutingDto technologyRoutingDto) {
+        return R.ok(technologyRoutingService.pageTechnologyRouting(page, technologyRoutingDto));
+    }
+
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎璇︽儏銆�
+     */
+    @GetMapping("/{id}")
+    @Operation(summary = "宸ヨ壓璺嚎璇︽儏")
+    public R<TechnologyRoutingVo> getInfo(@PathVariable("id") Long id) {
+        return R.ok(technologyRoutingService.getTechnologyRoutingInfo(id));
+    }
+
+    /**
+     * 鏂板宸ヨ壓璺嚎銆�
+     */
+    @PostMapping("/addTechRoute")
+    @Operation(summary = "鏂板宸ヨ壓璺嚎")
+    public R add(@RequestBody TechnologyRouting technologyRouting) {
+        return R.ok(technologyRoutingService.saveTechnologyRouting(technologyRouting));
+    }
+
+    /**
+     * 淇敼宸ヨ壓璺嚎銆�
+     */
+    @PutMapping("/editTechRoute")
+    @Operation(summary = "淇敼宸ヨ壓璺嚎")
+    public R edit(@RequestBody TechnologyRouting technologyRouting) {
+        return R.ok(technologyRoutingService.updateTechnologyRouting(technologyRouting));
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宸ヨ壓璺嚎銆�
+     */
+    @DeleteMapping("/delete")
+    @Operation(summary = "鍒犻櫎宸ヨ壓璺嚎")
+    public R remove(@RequestBody List<Long> ids) {
+        return R.ok(technologyRoutingService.removeTechnologyRouting(ids));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationController.java
new file mode 100644
index 0000000..eea52a0
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationController.java
@@ -0,0 +1,67 @@
+package com.ruoyi.technology.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import com.ruoyi.technology.service.TechnologyRoutingOperationService;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/technologyRoutingOperation")
+@Tag(name = "宸ヨ壓璺嚎宸ュ簭")
+@RequiredArgsConstructor
+public class TechnologyRoutingOperationController {
+
+    private final TechnologyRoutingOperationService technologyRoutingOperationService;
+
+    @GetMapping("/page")
+    @Operation(summary = "宸ヨ壓璺嚎宸ュ簭鍒嗛〉鏌ヨ")
+    public R<IPage<TechnologyRoutingOperationVo>> page(Page<TechnologyRoutingOperationDto> page, TechnologyRoutingOperationDto technologyRoutingOperationDto) {
+        return R.ok(technologyRoutingOperationService.pageTechnologyRoutingOperation(page, technologyRoutingOperationDto));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "宸ヨ壓璺嚎宸ュ簭鍒楄〃")
+    public R<List<TechnologyRoutingOperationVo>> list(TechnologyRoutingOperationDto technologyRoutingOperationDto) {
+        return R.ok(technologyRoutingOperationService.listTechnologyRoutingOperation(technologyRoutingOperationDto));
+    }
+
+    @GetMapping("/{id}")
+    @Operation(summary = "宸ヨ壓璺嚎宸ュ簭璇︽儏")
+    public R<TechnologyRoutingOperationVo> getInfo(@PathVariable("id") Long id) {
+        return R.ok(technologyRoutingOperationService.getTechnologyRoutingOperationInfo(id));
+    }
+
+    @PostMapping("/add")
+    @Operation(summary = "鏂板宸ヨ壓璺嚎宸ュ簭")
+    public R add(@RequestBody TechnologyRoutingOperation technologyRoutingOperation) {
+        return R.ok(technologyRoutingOperationService.saveTechnologyRoutingOperation(technologyRoutingOperation));
+    }
+
+    @PutMapping
+    @Operation(summary = "淇敼宸ヨ壓璺嚎宸ュ簭")
+    public R edit(@RequestBody TechnologyRoutingOperation technologyRoutingOperation) {
+        return R.ok(technologyRoutingOperationService.updateById(technologyRoutingOperation));
+    }
+
+    @DeleteMapping("/{id}")
+    @Operation(summary = "鍒犻櫎宸ヨ壓璺嚎宸ュ簭")
+    public R remove(@PathVariable("id") Long id) {
+        return R.ok(technologyRoutingOperationService.removeTechnologyRoutingOperation(id));
+    }
+
+    @PostMapping ("/sort")
+    @Operation(summary = "鎺掑簭宸ヨ壓璺嚎宸ュ簭")
+    public R sort(@RequestBody TechnologyRoutingOperation technologyRoutingOperation) {
+        return R.ok(technologyRoutingOperationService.sort(technologyRoutingOperation));
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationParamController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationParamController.java
new file mode 100644
index 0000000..f685471
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationParamController.java
@@ -0,0 +1,68 @@
+package com.ruoyi.technology.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamDto;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamSyncDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationParamVo;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+import com.ruoyi.technology.service.TechnologyRoutingOperationParamService;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/technologyRoutingOperationParam")
+@Tag(name = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+@RequiredArgsConstructor
+public class TechnologyRoutingOperationParamController {
+
+    private final TechnologyRoutingOperationParamService technologyRoutingOperationParamService;
+
+    @GetMapping("/page")
+    @Operation(summary = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟鍒嗛〉鏌ヨ")
+    public R<IPage<TechnologyRoutingOperationParamVo>> page(Page<TechnologyRoutingOperationParamDto> page,
+                                                            TechnologyRoutingOperationParamDto dto) {
+        return R.ok(technologyRoutingOperationParamService.pageTechnologyRoutingOperationParam(page, dto));
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟鍒楄〃")
+    public R<List<TechnologyRoutingOperationParamVo>> list(TechnologyRoutingOperationParamDto dto) {
+        return R.ok(technologyRoutingOperationParamService.listTechnologyRoutingOperationParam(dto));
+    }
+
+    @GetMapping("/{id}")
+    @Operation(summary = "鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟璇︽儏")
+    public R<TechnologyRoutingOperationParamVo> getInfo(@PathVariable("id") Long id) {
+        return R.ok(technologyRoutingOperationParamService.getTechnologyRoutingOperationParamInfo(id));
+    }
+
+    @PostMapping("/add")
+    @Operation(summary = "鏂板鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+    public R<Boolean> add(@RequestBody TechnologyRoutingOperationParam technologyRoutingOperationParam) {
+        return R.ok(technologyRoutingOperationParamService.saveTechnologyRoutingOperationParam(technologyRoutingOperationParam));
+    }
+
+    @PutMapping
+    @Operation(summary = "淇敼鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+    public R<Boolean> edit(@RequestBody TechnologyRoutingOperationParam technologyRoutingOperationParam) {
+        return R.ok(technologyRoutingOperationParamService.saveTechnologyRoutingOperationParam(technologyRoutingOperationParam));
+    }
+
+    @DeleteMapping("/{id}")
+    @Operation(summary = "鍒犻櫎鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟")
+    public R<Boolean> remove(@PathVariable("id") Long id) {
+        return R.ok(technologyRoutingOperationParamService.removeTechnologyRoutingOperationParam(id));
+    }
+
+    @PostMapping("/sync")
+    @Operation(summary = "鎸夊伐鑹鸿矾绾垮伐搴忓悓姝ュ伐搴忓弬鏁�")
+    public R<Integer> sync(@RequestBody TechnologyRoutingOperationParamSyncDto syncDto) {
+        return R.ok(technologyRoutingOperationParamService.syncTechnologyRoutingOperationParam(syncDto));
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java
new file mode 100644
index 0000000..7ae5509
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.technology.bean.dto.TechnologyBomDto;
+import com.ruoyi.technology.bean.vo.TechnologyBomVo;
+import com.ruoyi.technology.pojo.TechnologyBom;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * BOM琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:05:55
+ */
+@Mapper
+public interface TechnologyBomMapper extends BaseMapper<TechnologyBom> {
+
+    IPage<TechnologyBomVo> listPage(Page<TechnologyBomDto> page, @Param("c") TechnologyBomDto technologyBomDto);
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java
new file mode 100644
index 0000000..29f6cc8
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java
@@ -0,0 +1,23 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo;
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * BOM浜у搧缁撴瀯琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:06:17
+ */
+@Mapper
+public interface TechnologyBomStructureMapper extends BaseMapper<TechnologyBomStructure> {
+
+    List<TechnologyBomStructureVo> listByBomId(@Param("bomId") Long bomId);
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java
new file mode 100644
index 0000000..89596b4
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.technology.bean.dto.TechnologyOperationDto;
+import com.ruoyi.technology.bean.vo.TechnologyOperationVo;
+import com.ruoyi.technology.pojo.TechnologyOperation;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 宸ュ簭琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:33:03
+ */
+@Mapper
+public interface TechnologyOperationMapper extends BaseMapper<TechnologyOperation> {
+
+    IPage<TechnologyOperationVo> listPage(Page<TechnologyOperationDto> page, @Param("c") TechnologyOperationDto technologyOperationDto);
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java
new file mode 100644
index 0000000..040c52a
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo;
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 宸ュ簭鍙傛暟 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:05:35
+ */
+@Mapper
+public interface TechnologyOperationParamMapper extends BaseMapper<TechnologyOperationParam> {
+
+    List<TechnologyOperationParamVo> listOperationParam(@Param("technologyOperationId") Long technologyOperationId,
+                                                        @Param("paramId") Long technologyParamId);
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyParamMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyParamMapper.java
new file mode 100644
index 0000000..ffde12a
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyParamMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.technology.pojo.TechnologyParam;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鍩虹鍙傛暟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 09:45:20
+ */
+@Mapper
+public interface TechnologyParamMapper extends BaseMapper<TechnologyParam> {
+
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java
new file mode 100644
index 0000000..7a29f1b
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingVo;
+import com.ruoyi.technology.pojo.TechnologyRouting;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface TechnologyRoutingMapper extends BaseMapper<TechnologyRouting> {
+
+    IPage<TechnologyRoutingVo> pageTechnologyRouting(Page<TechnologyRoutingDto> page, @Param("c") TechnologyRoutingDto technologyRoutingDto);
+
+    int updateProductModelByBomId(@Param("productModelId") Long productModelId, @Param("bomId") Long bomId);
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationMapper.java
new file mode 100644
index 0000000..890b8f8
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationMapper.java
@@ -0,0 +1,31 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 宸ヨ壓璺嚎宸ュ簭琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:06:47
+ */
+@Mapper
+public interface TechnologyRoutingOperationMapper extends BaseMapper<TechnologyRoutingOperation> {
+    IPage<TechnologyRoutingOperationVo> pageTechnologyRoutingOperation(Page<TechnologyRoutingOperationDto> page,
+                                                                       @Param("c") TechnologyRoutingOperationDto dto);
+
+    List<TechnologyRoutingOperationVo> listTechnologyRoutingOperation(@Param("c") TechnologyRoutingOperationDto dto);
+
+    TechnologyRoutingOperationVo getTechnologyRoutingOperationInfo(@Param("id") Long id);
+
+}
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationParamMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationParamMapper.java
new file mode 100644
index 0000000..83f23c3
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingOperationParamMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.technology.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鐢熶骇璁㈠崟宸ヨ壓璺嚎宸ュ簭鍙傛暟琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:22:16
+ */
+@Mapper
+public interface TechnologyRoutingOperationParamMapper extends BaseMapper<TechnologyRoutingOperationParam> {
+
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyBom.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyBom.java
new file mode 100644
index 0000000..3e77cd5
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyBom.java
@@ -0,0 +1,60 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * BOM琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:05:55
+ */
+@Data
+@TableName("technology_bom")
+@Schema(name = "TechnologyBom瀵硅薄", description = "BOM琛�")
+public class TechnologyBom implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @Schema(description = "浜у搧瑙勬牸id")
+    private Long productModelId;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鐗堟湰鍙�")
+    private String version;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鍒涘缓鑰�")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "鏇存柊鑰�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+
+    @Schema(description = "BOM缂栧彿")
+    private String bomNo;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyBomStructure.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyBomStructure.java
new file mode 100644
index 0000000..133670f
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyBomStructure.java
@@ -0,0 +1,57 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * <p>
+ * BOM浜у搧缁撴瀯琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:06:17
+ */
+@Data
+@TableName("technology_bom_structure")
+@Schema(name = "TechnologyStructure瀵硅薄", description = "BOM浜у搧缁撴瀯琛�")
+public class TechnologyBomStructure implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鐖惰妭鐐笽D")
+    private Long parentId;
+
+    @Schema(description = "浜у搧id")
+    private Long productModelId;
+
+    @Schema(description = "宸ュ簭id")
+    private Long operationId;
+
+    @Schema(description = "鍗曚綅浜у嚭闇�瑕佹暟閲�")
+    private BigDecimal unitQuantity;
+
+    @Schema(description = "闇�姹傛暟閲�")
+    private BigDecimal demandedQuantity;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "bom鐨刬d")
+    private Long bomId;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyOperation.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyOperation.java
new file mode 100644
index 0000000..061169b
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyOperation.java
@@ -0,0 +1,68 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 宸ュ簭琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:33:03
+ */
+@Data
+@TableName("technology_operation")
+@Schema(name = "TechnologyOperation瀵硅薄", description = "宸ュ簭琛�")
+public class TechnologyOperation implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "宸ヨ壓鍚嶇О")
+    private String name;
+
+    @Schema(description = "宸ヨ壓缂栧彿")
+    private String no;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "宸ヨ祫瀹氶")
+    private BigDecimal salaryQuota;
+
+    @Schema(description = "鏄惁璐ㄦ")
+    private Boolean isQuality;
+
+    @Schema(description = "绫诲瀷 鍖哄垎璁℃椂鍜岃浠�")
+    private Integer type;
+
+    @Schema(description = "璁惧id")
+    private String deviceLedgerId;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "鏄惁鐢熶骇")
+    private Boolean isProduction;
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyOperationParam.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyOperationParam.java
new file mode 100644
index 0000000..e3d4015
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyOperationParam.java
@@ -0,0 +1,38 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 宸ュ簭鍙傛暟
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:05:35
+ */
+@Data
+@TableName("technology_operation_param")
+@Schema(name = "TechnologyOperationParam瀵硅薄", description = "宸ュ簭鍙傛暟")
+public class TechnologyOperationParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鍩虹鍙傛暟琛╥d")
+    private Long technologyParamId;
+
+    @Schema(description = "宸ュ簭id")
+    private Long technologyOperationId;
+
+    @Schema(description = "鏍囧噯鍊�")
+    private String standardValue;
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyParam.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyParam.java
new file mode 100644
index 0000000..75d56cf
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyParam.java
@@ -0,0 +1,69 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鍩虹鍙傛暟琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 09:45:20
+ */
+@Data
+@TableName("technology_param")
+@Schema(name = "TechnologyParam瀵硅薄", description = "鍩虹鍙傛暟琛�")
+public class TechnologyParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鍙傛暟缂栫爜(鍞竴鏍囪瘑)")
+    private String paramCode;
+
+    @Schema(description = "鍙傛暟鍚嶇О")
+    private String paramName;
+
+    @Schema(description = "鍙傛暟绫诲瀷(1鏁板瓧 2鏂囨湰 3涓嬫媺閫夋嫨 4鏃堕棿)")
+    private Byte paramType;
+
+    @Schema(description = "鍙傛暟鏍煎紡")
+    private String paramFormat;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鏄惁蹇呭~")
+    private Byte isRequired;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓浜�")
+    @TableField(fill = FieldFill.INSERT)
+    private String createUser;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "淇敼浜�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String updateUser;
+
+    @Schema(description = "淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyRouting.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyRouting.java
new file mode 100644
index 0000000..1427de6
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyRouting.java
@@ -0,0 +1,55 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 宸ヨ壓璺嚎琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:06:33
+ */
+@Data
+@TableName("technology_routing")
+@Schema(name = "TechnologyRouting瀵硅薄", description = "宸ヨ壓璺嚎琛�")
+public class TechnologyRouting implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "浜у搧id")
+    private Long productModelId;
+
+    @Schema(description = "鎻忚堪")
+    private String description;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "宸ヨ壓璺嚎缂栫爜")
+    private String processRouteCode;
+
+    @Schema(description = "鍏宠仈bom鐨刬d")
+    private Long bomId;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperation.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperation.java
new file mode 100644
index 0000000..f91f1e1
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperation.java
@@ -0,0 +1,61 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 宸ヨ壓璺嚎宸ュ簭琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 10:06:47
+ */
+@Data
+@TableName("technology_routing_operation")
+@Schema(name = "TechnologyRoutingOperation瀵硅薄", description = "宸ヨ壓璺嚎宸ュ簭琛�")
+public class TechnologyRoutingOperation implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "宸ヨ壓璺嚎id")
+    private Long technologyRoutingId;
+
+    @Schema(description = "浜у搧id")
+    private Long productModelId;
+
+    @Schema(description = "宸ュ簭id")
+    private Long technologyOperationId;
+
+    @Schema(description = "褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "鎷栧姩鎺掑簭")
+    private Integer dragSort;
+
+    @Schema(description = "鏄惁璐ㄦ宸ュ簭")
+    private Boolean isQuality;
+
+    @Schema(description = "鏄惁鐢熶骇")
+    private Boolean isProduction;
+
+    @Schema(description = "鍒涘缓浜篒D")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperationParam.java b/src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperationParam.java
new file mode 100644
index 0000000..2f3146a
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/pojo/TechnologyRoutingOperationParam.java
@@ -0,0 +1,80 @@
+package com.ruoyi.technology.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("technology_routing_operation_param")
+@Schema(name = "TechnologyRoutingOperationParam瀵硅薄", description = "宸ヨ壓璺嚎宸ュ簭鍙傛暟琛�")
+public class TechnologyRoutingOperationParam implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @Schema(description = "鍙傛暟缂栫爜(鍞竴鏍囪瘑)")
+    private String paramCode;
+
+    @Schema(description = "鍙傛暟鍚嶇О")
+    private String paramName;
+
+    @Schema(description = "鍙傛暟绫诲瀷(1鏁板瓧 2鏂囨湰 3涓嬫媺閫夋嫨 4鏃堕棿)")
+    private Byte paramType;
+
+    @Schema(description = "鍙傛暟鏍煎紡")
+    private String paramFormat;
+
+    @Schema(description = "鍗曚綅")
+    private String unit;
+
+    @Schema(description = "鏄惁蹇呭~")
+    private Byte isRequired;
+
+    @Schema(description = "澶囨敞")
+    private String remark;
+
+    @Schema(description = "鍒涘缓浜�")
+    @TableField(fill = FieldFill.INSERT)
+    private String createUser;
+
+    @Schema(description = "鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @Schema(description = "淇敼浜�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String updateUser;
+
+    @Schema(description = "淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @Schema(description = "閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @Schema(description = "鍩虹鍙傛暟ID")
+    private Long paramId;
+
+    @Schema(description = "宸ュ簭id")
+    private Long technologyOperationId;
+
+    @Schema(description = "宸ュ簭鍙傛暟ID")
+    private Long technologyOperationParamId;
+
+    @Schema(description = "宸ヨ壓璺嚎宸ュ簭ID")
+    private Long technologyRoutingOperationId;
+
+    @Schema(description = "鏍囧噯鍊�")
+    private String standardValue;
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyBomService.java b/src/main/java/com/ruoyi/technology/service/TechnologyBomService.java
new file mode 100644
index 0000000..31fd335
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyBomService.java
@@ -0,0 +1,32 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyBomDto;
+import com.ruoyi.technology.bean.vo.TechnologyBomVo;
+import com.ruoyi.technology.pojo.TechnologyBom;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+public interface TechnologyBomService extends IService<TechnologyBom> {
+
+    IPage<TechnologyBomVo> listPage(Page<TechnologyBomDto> page, TechnologyBomDto technologyBomDto);
+
+    List<TechnologyBomVo> listByModel(Long productModelId);
+
+    R add(TechnologyBom technologyBom);
+
+    R update(TechnologyBom technologyBom);
+
+    boolean batchDelete(List<Long> ids);
+
+    R uploadBom(MultipartFile file);
+
+    void exportBom(HttpServletResponse response, Integer bomId);
+
+    R copy(TechnologyBom technologyBom);
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java b/src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java
new file mode 100644
index 0000000..47ea67d
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java
@@ -0,0 +1,15 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto;
+import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo;
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+
+import java.util.List;
+
+public interface TechnologyBomStructureService extends IService<TechnologyBomStructure> {
+
+    Boolean addTechnologyBomStructure(TechnologyBomStructureDto technologyBomStructureDto);
+
+    List<TechnologyBomStructureVo> listByBomId(Long bomId);
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java b/src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java
new file mode 100644
index 0000000..3f217ab
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java
@@ -0,0 +1,17 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.technology.bean.dto.TechnologyOperationParamDto;
+import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo;
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+
+import java.util.List;
+
+public interface TechnologyOperationParamService extends IService<TechnologyOperationParam> {
+
+    List<TechnologyOperationParamVo> listOperationParam(TechnologyOperationParamDto technologyOperationParamDto);
+
+    boolean saveTechnologyOperationParam(TechnologyOperationParam technologyOperationParam);
+
+    String batchDelete(Long id);
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java b/src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java
new file mode 100644
index 0000000..42ba667
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java
@@ -0,0 +1,22 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyOperationDto;
+import com.ruoyi.technology.bean.vo.TechnologyOperationVo;
+import com.ruoyi.technology.pojo.TechnologyOperation;
+
+import java.util.List;
+
+public interface TechnologyOperationService extends IService<TechnologyOperation> {
+
+    IPage<TechnologyOperationVo> listPage(Page<TechnologyOperationDto> page, TechnologyOperationDto technologyOperationDto);
+
+    R add(TechnologyOperationDto technologyOperationDto);
+
+    String batchDelete(List<Long> ids);
+
+    List<TechnologyOperationVo> listVo();
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyParamService.java b/src/main/java/com/ruoyi/technology/service/TechnologyParamService.java
new file mode 100644
index 0000000..958dab5
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyParamService.java
@@ -0,0 +1,27 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.technology.bean.dto.TechnologyParamDto;
+import com.ruoyi.technology.bean.vo.TechnologyParamVo;
+import com.ruoyi.technology.pojo.TechnologyParam;
+
+/**
+ * <p>
+ * 鍩虹鍙傛暟琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-04-20 09:45:20
+ */
+public interface TechnologyParamService extends IService<TechnologyParam> {
+
+    IPage<TechnologyParamVo> baseParamList(Page<TechnologyParamDto> page, TechnologyParamDto technologyParamDto);
+
+    int addBaseParam(TechnologyParamDto technologyParamDto);
+
+    int updateBaseParam(TechnologyParamDto technologyParamDto);
+
+    int deleteBaseParamByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationParamService.java b/src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationParamService.java
new file mode 100644
index 0000000..5d39eb6
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationParamService.java
@@ -0,0 +1,27 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamDto;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamSyncDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationParamVo;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+
+import java.util.List;
+
+public interface TechnologyRoutingOperationParamService extends IService<TechnologyRoutingOperationParam> {
+
+    IPage<TechnologyRoutingOperationParamVo> pageTechnologyRoutingOperationParam(Page<TechnologyRoutingOperationParamDto> page,
+                                                                                 TechnologyRoutingOperationParamDto technologyRoutingOperationParamDto);
+
+    List<TechnologyRoutingOperationParamVo> listTechnologyRoutingOperationParam(TechnologyRoutingOperationParamDto technologyRoutingOperationParamDto);
+
+    TechnologyRoutingOperationParamVo getTechnologyRoutingOperationParamInfo(Long id);
+
+    boolean saveTechnologyRoutingOperationParam(TechnologyRoutingOperationParam technologyRoutingOperationParam);
+
+    boolean removeTechnologyRoutingOperationParam(Long id);
+
+    int syncTechnologyRoutingOperationParam(TechnologyRoutingOperationParamSyncDto syncDto);
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationService.java b/src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationService.java
new file mode 100644
index 0000000..40c8710
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationService.java
@@ -0,0 +1,26 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+
+import java.util.List;
+
+public interface TechnologyRoutingOperationService extends IService<TechnologyRoutingOperation> {
+
+    IPage<TechnologyRoutingOperationVo> pageTechnologyRoutingOperation(Page<TechnologyRoutingOperationDto> page,
+                                                                       TechnologyRoutingOperationDto technologyRoutingOperationDto);
+
+    List<TechnologyRoutingOperationVo> listTechnologyRoutingOperation(TechnologyRoutingOperationDto technologyRoutingOperationDto);
+
+    TechnologyRoutingOperationVo getTechnologyRoutingOperationInfo(Long id);
+
+    boolean saveTechnologyRoutingOperation(TechnologyRoutingOperation technologyRoutingOperation);
+
+    boolean removeTechnologyRoutingOperation(Long id);
+
+    int sort(TechnologyRoutingOperation technologyRoutingOperation);
+}
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyRoutingService.java b/src/main/java/com/ruoyi/technology/service/TechnologyRoutingService.java
new file mode 100644
index 0000000..fc44450
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/TechnologyRoutingService.java
@@ -0,0 +1,40 @@
+package com.ruoyi.technology.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingVo;
+import com.ruoyi.technology.pojo.TechnologyRouting;
+
+import java.util.List;
+
+public interface TechnologyRoutingService extends IService<TechnologyRouting> {
+
+    /**
+     * 宸ヨ壓璺嚎鍒嗛〉鏌ヨ锛屾煡璇㈠弬鏁颁娇鐢� DTO锛岃繑鍥炴暟鎹娇鐢� VO銆�
+     */
+    IPage<TechnologyRoutingVo> pageTechnologyRouting(Page<TechnologyRoutingDto> page, TechnologyRoutingDto technologyRoutingDto);
+
+    /**
+     * 鏌ヨ宸ヨ壓璺嚎璇︽儏銆�
+     */
+    TechnologyRoutingVo getTechnologyRoutingInfo(Long id);
+
+    /**
+     * 鏂板宸ヨ壓璺嚎銆�
+     * 閫夋嫨浜� BOM 鏃讹紝浼氳嚜鍔ㄦ妸 BOM 涓厤缃殑宸ュ簭鍚屾鍒板伐鑹鸿矾绾垮伐搴忚〃銆�
+     */
+    Long saveTechnologyRouting(TechnologyRouting technologyRouting);
+
+    /**
+     * 淇敼宸ヨ壓璺嚎銆�
+     * 褰� BOM 鍙戠敓鍙樺寲鏃讹紝浼氶噸鏂板悓姝ュ伐鑹鸿矾绾垮伐搴忚〃銆�
+     */
+    boolean updateTechnologyRouting(TechnologyRouting technologyRouting);
+
+    /**
+     * 鍒犻櫎宸ヨ壓璺嚎锛屽苟绾ц仈鍒犻櫎宸ヨ壓璺嚎宸ュ簭銆�
+     */
+    boolean removeTechnologyRouting(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java
new file mode 100644
index 0000000..2a4cd1d
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java
@@ -0,0 +1,485 @@
+package com.ruoyi.technology.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.basic.pojo.ProductModel;
+import com.ruoyi.basic.service.IProductModelService;
+import com.ruoyi.basic.service.IProductService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.production.bean.dto.BomImportDto;
+import com.ruoyi.production.bean.dto.ProductStructureDto;
+import com.ruoyi.technology.bean.dto.TechnologyBomDto;
+import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto;
+import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo;
+import com.ruoyi.technology.bean.vo.TechnologyBomVo;
+import com.ruoyi.technology.mapper.TechnologyBomMapper;
+import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingMapper;
+import com.ruoyi.technology.pojo.TechnologyBom;
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+import com.ruoyi.technology.pojo.TechnologyRouting;
+import com.ruoyi.technology.service.TechnologyBomService;
+import com.ruoyi.technology.service.TechnologyBomStructureService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class TechnologyBomServiceImpl extends ServiceImpl<TechnologyBomMapper, TechnologyBom> implements TechnologyBomService {
+
+    private final TechnologyBomMapper technologyBomMapper;
+    private final IProductModelService productModelService;
+    private final TechnologyBomStructureService technologyBomStructureService;
+    private final TechnologyRoutingMapper technologyRoutingMapper;
+    private final IProductService productService;
+    private final TechnologyBomStructureMapper technologyBomStructureMapper;
+
+    /**
+     * 鍒嗛〉鏌ヨBOM鍒楄〃銆�
+     */
+    @Override
+    public IPage<TechnologyBomVo> listPage(Page<TechnologyBomDto> page, TechnologyBomDto technologyBomDto) {
+        return technologyBomMapper.listPage(page, technologyBomDto);
+    }
+
+    /**
+     * 鏍规嵁瑙勬牸鏌ヨBOM骞惰浆鎹负杩斿洖瀵硅薄銆�
+     */
+    @Override
+    public List<TechnologyBomVo> listByModel(Long productModelId) {
+        List<TechnologyBom> list = this.list(Wrappers.<TechnologyBom>lambdaQuery()
+                .eq(TechnologyBom::getProductModelId, productModelId));
+        List<TechnologyBomVo> result = new ArrayList<>(list.size());
+        for (TechnologyBom item : list) {
+            TechnologyBomVo vo = new TechnologyBomVo();
+            vo.setId(item.getId());
+            vo.setProductModelId(item.getProductModelId());
+            vo.setRemark(item.getRemark());
+            vo.setVersion(item.getVersion());
+            vo.setCreateTime(item.getCreateTime());
+            vo.setUpdateTime(item.getUpdateTime());
+            vo.setCreateUser(item.getCreateUser());
+            vo.setUpdateUser(item.getUpdateUser());
+            vo.setBomNo(item.getBomNo());
+            vo.setDeptId(item.getDeptId());
+            result.add(vo);
+        }
+        return result;
+    }
+
+    /**
+     * 鏂板BOM骞跺垵濮嬪寲鏍圭粨鏋勮妭鐐广��
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R add(TechnologyBom technologyBom) {
+        validateProductModel(technologyBom.getProductModelId());
+        boolean saved = technologyBomMapper.insert(technologyBom) > 0;
+        if (!saved) {
+            return R.fail("Add BOM failed");
+        }
+        technologyBom.setBomNo("BM." + String.format("%05d", technologyBom.getId()));
+        technologyBomMapper.updateById(technologyBom);
+        initRootStructure(technologyBom.getId().longValue(), technologyBom.getProductModelId());
+        return R.ok();
+    }
+
+    /**
+     * 淇敼BOM锛岃鏍煎彉鍖栨椂鍚屾鍒锋柊鍏宠仈缁撴瀯涓庤矾绾挎暟鎹��
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R update(TechnologyBom technologyBom) {
+        if (technologyBom.getId() == null) {
+            throw new ServiceException("BOM id is required");
+        }
+        validateProductModel(technologyBom.getProductModelId());
+        TechnologyBom oldBom = technologyBomMapper.selectById(technologyBom.getId());
+        if (oldBom == null) {
+            throw new ServiceException("BOM not found");
+        }
+        if (oldBom.getProductModelId() != null && !oldBom.getProductModelId().equals(technologyBom.getProductModelId())) {
+            technologyRoutingMapper.updateProductModelByBomId(technologyBom.getProductModelId(), technologyBom.getId().longValue());
+            technologyBomStructureService.remove(Wrappers.<TechnologyBomStructure>lambdaQuery()
+                    .eq(TechnologyBomStructure::getBomId, technologyBom.getId().longValue()));
+            initRootStructure(technologyBom.getId().longValue(), technologyBom.getProductModelId());
+        }
+        if (technologyBom.getBomNo() == null) {
+            technologyBom.setBomNo(oldBom.getBomNo());
+        }
+        technologyBomMapper.updateById(technologyBom);
+        return R.ok();
+    }
+
+    /**
+     * 鍒犻櫎BOM鍓嶆牎楠屾槸鍚﹀凡琚伐鑹鸿矾绾垮紩鐢ㄣ��
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean batchDelete(List<Long> ids) {
+        if (ids == null || ids.isEmpty()) {
+            throw new ServiceException("Select at least one BOM");
+        }
+        List<TechnologyRouting> list = technologyRoutingMapper.selectList(Wrappers.<TechnologyRouting>lambdaQuery()
+                .in(TechnologyRouting::getBomId, ids));
+        if (!list.isEmpty()) {
+            throw new ServiceException("BOM is referenced by routing");
+        }
+        technologyBomStructureService.remove(Wrappers.<TechnologyBomStructure>lambdaQuery()
+                .in(TechnologyBomStructure::getBomId, ids));
+        return this.removeBatchByIds(ids);
+    }
+
+    /**
+     * 鏍¢獙浜у搧瑙勬牸鏄惁瀛樺湪銆�
+     */
+    private void validateProductModel(Long productModelId) {
+        if (productModelId == null) {
+            throw new ServiceException("Product model is required");
+        }
+        ProductModel productModel = productModelService.getById(productModelId);
+        if (productModel == null) {
+            throw new ServiceException("Product model not found");
+        }
+    }
+
+    /**
+     * 鍒濆鍖朆OM鏍硅妭鐐圭粨鏋勩��
+     */
+    private void initRootStructure(Long bomId, Long productModelId) {
+        ProductModel productModel = productModelService.getById(productModelId);
+        TechnologyBomStructure root = new TechnologyBomStructure();
+        root.setBomId(bomId);
+        root.setParentId(null);
+        root.setProductModelId(productModelId);
+        root.setUnit(productModel.getUnit());
+        root.setUnitQuantity(BigDecimal.ONE);
+        technologyBomStructureService.save(root);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R uploadBom(MultipartFile file) {
+        ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class);
+        List<BomImportDto> list;
+        try {
+            list = util.importExcel(file.getInputStream());
+        } catch (Exception e) {
+            return R.fail("Excel瑙f瀽澶辫触");
+        }
+
+        if (list == null || list.isEmpty()) return R.fail("鏁版嵁涓虹┖");
+
+        //  澶勭悊宸ュ簭
+        list.forEach(dto -> {
+            dto.setParentName(clean(dto.getParentName()));
+            dto.setParentSpec(clean(dto.getParentSpec()));
+            dto.setChildName(clean(dto.getChildName()));
+            dto.setChildSpec(clean(dto.getChildSpec()));
+        });
+        handleProcess(list);
+//        Map<String, Long> processMap = productProcessService.list().stream()
+//                .collect(Collectors.toMap(ProductProcess::getName, ProductProcess::getId, (k1, k2) -> k1));
+
+        //  鍒涘缓 BOM 鏁版嵁
+        BomImportDto first = list.get(0);
+        ProductModel rootModel = findModel(first.getParentName(), first.getParentSpec());
+        TechnologyBom bom = new TechnologyBom();
+        bom.setProductModelId(rootModel.getId());
+        bom.setVersion("1.0");
+        technologyBomMapper.insert(bom);
+        bom.setBomNo("BM." + String.format("%05d", bom.getId()));
+        technologyBomMapper.updateById(bom);
+
+        // 璁板綍宸茬粡鎻掑叆缁撴瀯鐨勮妭鐐癸細Key = "鍚嶇О+瑙勬牸", Value = structure_id
+        Map<String, Long> treePathMap = new HashMap<>();
+
+        for (int i = 0; i < list.size(); i++) {
+            BomImportDto dto = list.get(i);
+            String parentKey = dto.getParentName() + "|" + dto.getParentSpec();
+            String childKey = dto.getChildName() + "|" + dto.getChildSpec();
+
+            //澶勭悊鏍硅妭鐐�,绗竴琛屼笖瀛愰」涓虹┖
+            if (i == 0 && StringUtils.isBlank(dto.getChildName())) {
+                TechnologyBomStructure rootNode = new TechnologyBomStructure();
+                rootNode.setBomId(bom.getId().longValue());
+                rootNode.setParentId(null); // 椤跺眰娌℃湁鐖惰妭鐐�
+                rootNode.setProductModelId(rootModel.getId());
+                rootNode.setUnitQuantity(BigDecimal.ONE);
+                rootNode.setUnit(rootModel.getUnit());
+                technologyBomStructureService.save(rootNode);
+
+                treePathMap.put(parentKey, rootNode.getId());
+                continue;
+            }
+
+            //  澶勭悊瀛愬眰绾ц妭鐐�
+            //  鎵惧埌鐖惰妭鐐瑰湪鏁版嵁搴撻噷鐨� ID
+            Long parentStructureId = treePathMap.get(parentKey);
+            if (parentStructureId == null) {
+                // 濡傛灉 Map 閲屾壘涓嶅埌锛岃鏄� Excel 椤哄簭涔变簡鎴栬�呮暟鎹湁璇�
+                throw new ServiceException("瀵煎叆澶辫触: 鐖堕」[" + dto.getParentName() + "]蹇呴』鍦ㄥ叾瀛愰」涔嬪墠瀹氫箟");
+            }
+
+            //  鑾峰彇瀛愰」妯″瀷淇℃伅
+            ProductModel childModel = findModel(dto.getChildName(), dto.getChildSpec());
+
+            //  鎻掑叆缁撴瀯琛�
+            TechnologyBomStructure node = new TechnologyBomStructure();
+            node.setBomId(bom.getId().longValue());
+            node.setParentId(parentStructureId); // 鐖惰妭鐐笽D
+            node.setProductModelId(childModel.getId());
+            node.setUnitQuantity(dto.getUnitQty());
+            node.setUnit(childModel.getUnit());
+//            if (processMap.containsKey(dto.getProcess())) {
+//                node.setProcessId(processMap.get(dto.getProcess()));
+//            }
+            technologyBomStructureService.save(node);
+
+            //  鎶婂綋鍓嶅瓙椤硅褰曞埌 Map,浣滀负浠ュ悗鏇存繁灞傜骇鐨勭埗椤规煡鎵句緷鎹�
+            //  鍚屼竴鐖堕」涓嬬殑鍚屽悕瀛愰」涓嶉渶瑕侀噸澶嶈褰�
+            treePathMap.put(childKey, node.getId());
+        }
+
+        return R.ok("BOM瀵煎叆鎴愬姛");
+    }
+
+
+    @Override
+    public void exportBom(HttpServletResponse response, Integer bomId) {
+        if (bomId == null) {
+            return;
+        }
+
+//        List<ProductStructureDto> treeData = productStructureService.listBybomId(bomId);
+//        if (treeData == null || treeData.isEmpty()) {
+//            return;
+//        }
+//
+//        //  灏嗘爲褰㈢粨鏋勬墎骞冲寲 浣跨敤 BFS绠楁硶 瀵煎嚭,鎸夊眰绾ч『搴�
+//        List<BomImportDto> exportList = new ArrayList<>();
+//
+//        // Map<ID, Node> idMap 鐢ㄤ簬鏌ユ壘鐖惰妭鐐�
+//        Map<Long, ProductStructureDto> idMap = new HashMap<>();
+//        populateMap(treeData, idMap);
+//
+//        //  treeData 鐨勭涓�涓槸鏍硅妭鐐�
+//        for (ProductStructureDto root : treeData) {
+//            //  娣诲姞鏍硅妭鐐�
+//            BomImportDto rootRow = new BomImportDto();
+//            rootRow.setParentName(root.getProductName());
+//            rootRow.setParentSpec(root.getModel());
+//            rootRow.setUnitQty(root.getUnitQuantity());
+//            rootRow.setRemark("");
+//            exportList.add(rootRow);
+//
+//            //  BFS 閬嶅巻-闃熷垪
+//            Queue<ProductStructureDto> queue = new LinkedList<>();
+//            if (root.getChildren() != null) {
+//                queue.addAll(root.getChildren());
+//            }
+//
+//            while (!queue.isEmpty()) {
+//                ProductStructureDto child = queue.poll();
+//
+//                // 鏌ユ壘鐖惰妭鐐�
+//                ProductStructureDto parent = idMap.get(child.getParentId());
+//                if (parent == null) {
+//                    // 闄や簡鏈�澶栧眰鑺傜偣,鍏朵粬鑺傜偣鐨勭埗绫昏偗瀹氭槸涓嶄細涓虹┖鐨�
+//                    continue;
+//                }
+//
+//                BomImportDto row = new BomImportDto();
+//                // 鐖剁被淇℃伅
+//                row.setParentName(parent.getProductName());
+//                row.setParentSpec(parent.getModel());
+//                // 瀛愮被淇℃伅
+//                row.setChildName(child.getProductName());
+//                row.setChildSpec(child.getModel());
+//                row.setUnitQty(child.getUnitQuantity());
+//                row.setProcess(child.getProcessName());
+//
+//                exportList.add(row);
+//
+//                //  灏嗗瓙鑺傜偣鐨勫瓙鑺傜偣鍔犲叆闃熷垪-涓嬩竴灞�
+//                if (child.getChildren() != null && !child.getChildren().isEmpty()) {
+//                    queue.addAll(child.getChildren());
+//                }
+//            }
+//        }
+
+        ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class);
+//        util.exportExcel(response, exportList, "BOM缁撴瀯瀵煎嚭");
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R copy(TechnologyBom technologyBom) {
+        TechnologyBom oldTechnologyBom = technologyBomMapper.selectById(technologyBom.getId());
+        List<TechnologyBomStructureVo> oldTechnologyBomStructureVos = technologyBomStructureService.listByBomId(technologyBom.getId().longValue());
+        //鏍¢獙浜у搧瑙勬牸鏄惁瀛樺湪銆�
+        validateProductModel(oldTechnologyBom.getProductModelId());
+        TechnologyBom newTechnologyBom = new TechnologyBom();
+        newTechnologyBom.setProductModelId(oldTechnologyBom.getProductModelId());
+        newTechnologyBom.setVersion("FZ" + oldTechnologyBom.getVersion());
+        newTechnologyBom.setRemark(oldTechnologyBom.getRemark());
+        boolean saved = technologyBomMapper.insert(newTechnologyBom) > 0;
+        if (!saved) {
+            return R.fail("Copy BOM failed");
+        }
+        newTechnologyBom.setBomNo("BM." + String.format("%05d", newTechnologyBom.getId()));
+        technologyBomMapper.updateById(newTechnologyBom);
+        //鍒濆鍖朆OM鏍硅妭鐐圭粨鏋勩��
+        initRootStructure(newTechnologyBom.getId().longValue(), newTechnologyBom.getProductModelId());
+        //鎶婁骇鍝佺粨鏋勯噷闈㈢殑鏁版嵁涔熷叏閮ㄩ兘澶嶅埗
+        TechnologyBomStructureVo technologyBomStructureVo = oldTechnologyBomStructureVos.get(0);
+        TechnologyBomStructureDto technologyBomStructureDto = convertTree(technologyBomStructureVo);
+        technologyBomStructureDto.setBomId(newTechnologyBom.getId().longValue());
+        technologyBomStructureService.addTechnologyBomStructure(technologyBomStructureDto);
+        return R.ok();
+    }
+
+    private ProductModel findModel(String name, String spec) {
+        Product product = productService.getOne(new LambdaQueryWrapper<Product>()
+                .eq(Product::getProductName, name).last("limit 1"));
+        if (product == null) throw new ServiceException("浜у搧鏈淮鎶わ細" + name);
+
+        ProductModel model = productModelService.getOne(new LambdaQueryWrapper<ProductModel>()
+                .eq(ProductModel::getProductId, product.getId())
+                .eq(ProductModel::getModel, spec).last("limit 1"));
+        if (model == null) throw new ServiceException("瑙勬牸鏈淮鎶わ細" + name + "[" + spec + "]");
+        return model;
+    }
+
+    private void handleProcess(List<BomImportDto> list) {
+
+        Set<String> processNames = list.stream()
+                .map(BomImportDto::getProcess)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toSet());
+
+        if (processNames.isEmpty()) {
+            return;
+        }
+
+//        List<ProductProcess> exists = productProcessService.list(
+//                new LambdaQueryWrapper<ProductProcess>().in(ProductProcess::getName, processNames)
+//        );
+
+//        Set<String> existNames = exists.stream()
+//                .map(ProductProcess::getName)
+//                .collect(Collectors.toSet());
+//
+//        List<ProductProcess> needSave = processNames.stream()
+//                .filter(n -> !existNames.contains(n))
+//                .map(n -> {
+//                    ProductProcess p = new ProductProcess();
+//                    p.setName(n);
+//                    return p;
+//                })
+//                .collect(Collectors.toList());
+//
+//        if (!needSave.isEmpty()) {
+//            productProcessService.saveBatch(needSave);
+//            needSave.forEach(p -> p.setNo("GX" + String.format("%08d", p.getId())));
+//            productProcessService.updateBatchById(needSave);
+//        }
+    }
+
+    private String clean(String s) {
+        if (s == null) return null;
+        return s.replaceAll("[\\u00A0\\u3000]", "").trim();
+    }
+
+    private void populateMap(List<ProductStructureDto> nodes, Map<Long, ProductStructureDto> map) {
+        if (nodes == null || nodes.isEmpty()) {
+            return;
+        }
+        for (ProductStructureDto node : nodes) {
+            map.put(node.getId(), node);
+            populateMap(node.getChildren(), map);
+        }
+    }
+
+    /**
+     * 閫掑綊杞崲鏍戝舰缁撴瀯 VO -> DTO
+     * 鑷姩鐢熸垚铏氭嫙 tempId / parentTempId锛屼繚璇佷换鎰忓眰绾ф爲缁撴瀯姝g‘
+     */
+    public static TechnologyBomStructureDto convertTree(TechnologyBomStructureVo vo) {
+        if (vo == null) {
+            return null;
+        }
+        TechnologyBomStructureDto realDto = convertNode(vo, "0"); // 鏍硅妭鐐圭埗ID=0锛堢函鏁板瓧锛�
+        TechnologyBomStructureDto rootDto = new TechnologyBomStructureDto();
+        rootDto.setTempId("0");
+        rootDto.setChildren(Collections.singletonList(realDto));
+
+        return rootDto;
+    }
+
+    /**
+     * 鏍稿績閫掑綊鏂规硶
+     * @param vo 鍘熷鑺傜偣
+     * @param parentTempId 鐖惰妭鐐� 绾暟瀛桰D
+     * @return 杞崲鍚嶥TO
+     */
+    private static TechnologyBomStructureDto convertNode(TechnologyBomStructureVo vo, String parentTempId) {
+        if (vo == null) {
+            return null;
+        }
+
+        TechnologyBomStructureDto dto = new TechnologyBomStructureDto();
+        BeanUtils.copyProperties(vo, dto);
+
+        String currentTempId = getNumberId();
+        dto.setTempId(currentTempId);
+        dto.setParentTempId(parentTempId);
+
+
+        dto.setId(null);
+        dto.setParentId(null);
+
+        // ===================== 閫掑綊瀛愯妭鐐� =====================
+        List<TechnologyBomStructureVo> voChildren = vo.getChildren();
+        if (CollUtil.isNotEmpty(voChildren)) {
+            List<TechnologyBomStructureDto> dtoChildren = new ArrayList<>();
+            for (TechnologyBomStructureVo childVo : voChildren) {
+                // 瀛愯妭鐐圭殑鐖禝D = 褰撳墠鑺傜偣鐨勬暟瀛桰D
+                dtoChildren.add(convertNode(childVo, currentTempId));
+            }
+            dto.setChildren(dtoChildren);
+        } else {
+            dto.setChildren(new ArrayList<>());
+        }
+
+        return dto;
+    }
+
+    /**
+     * 鐢熸垚 13浣� 绾暟瀛楅殢鏈篒D锛堝畨鍏ㄣ�佷笉閲嶅銆侀珮鎬ц兘锛�
+     */
+    private static String getNumberId() {
+        // 鐢熸垚 1000000000000 ~ 9999999999999 涔嬮棿鐨勬暟瀛�
+        long min = 1000000000000L;
+        long max = 9999999999999L;
+        long randomNum = ThreadLocalRandom.current().nextLong(min, max + 1);
+        return String.valueOf(randomNum);
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java
new file mode 100644
index 0000000..5cb898a
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java
@@ -0,0 +1,136 @@
+package com.ruoyi.technology.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto;
+import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo;
+import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+import com.ruoyi.technology.service.TechnologyBomStructureService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+@Service
+@RequiredArgsConstructor
+public class TechnologyBomStructureServiceImpl extends ServiceImpl<TechnologyBomStructureMapper, TechnologyBomStructure> implements TechnologyBomStructureService {
+
+    private final TechnologyBomStructureMapper technologyBomStructureMapper;
+
+    /**
+     * 淇濆瓨BOM缁撴瀯鏍戯紝澶勭悊鏂板銆佹洿鏂板拰鍒犻櫎鑺傜偣銆�
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean addTechnologyBomStructure(TechnologyBomStructureDto dto) {
+        Long bomId = dto.getBomId();
+        List<TechnologyBomStructureDto> flatDtoList = new ArrayList<>();
+        flattenTree(dto.getChildren(), flatDtoList);
+
+        List<TechnologyBomStructure> dbList = this.list(new LambdaQueryWrapper<TechnologyBomStructure>()
+                .eq(TechnologyBomStructure::getBomId, bomId));
+
+        Set<Long> frontendIds = new HashSet<>();
+        for (TechnologyBomStructureDto item : flatDtoList) {
+            if (item.getId() != null) {
+                frontendIds.add(item.getId());
+            }
+        }
+
+        Set<Long> deleteIds = new HashSet<>();
+        for (TechnologyBomStructure dbItem : dbList) {
+            if (!frontendIds.contains(dbItem.getId())) {
+                deleteIds.add(dbItem.getId());
+            }
+        }
+        if (!deleteIds.isEmpty()) {
+            this.removeByIds(deleteIds);
+        }
+
+        List<TechnologyBomStructure> insertList = new ArrayList<>();
+        List<TechnologyBomStructure> updateList = new ArrayList<>();
+        Map<String, TechnologyBomStructure> tempEntityMap = new HashMap<>();
+
+        for (TechnologyBomStructureDto item : flatDtoList) {
+            TechnologyBomStructure entity = new TechnologyBomStructure();
+            BeanUtils.copyProperties(item, entity);
+            entity.setBomId(bomId);
+            if (item.getId() == null) {
+                entity.setParentId(null);
+                insertList.add(entity);
+                tempEntityMap.put(item.getTempId(), entity);
+            } else {
+                updateList.add(entity);
+            }
+        }
+
+        if (!insertList.isEmpty()) {
+            this.saveBatch(insertList);
+        }
+
+        List<TechnologyBomStructure> parentFixList = new ArrayList<>();
+        for (TechnologyBomStructureDto item : flatDtoList) {
+            if (item.getId() == null && item.getParentTempId() != null) {
+                TechnologyBomStructure child = tempEntityMap.get(item.getTempId());
+                if (child == null) {
+                    continue;
+                }
+                TechnologyBomStructure parent = tempEntityMap.get(item.getParentTempId());
+                Long realParentId = parent != null ? parent.getId() : Long.valueOf(item.getParentTempId());
+                child.setParentId(realParentId);
+                parentFixList.add(child);
+            }
+        }
+
+        if (!parentFixList.isEmpty()) {
+            this.updateBatchById(parentFixList);
+        }
+        if (!updateList.isEmpty()) {
+            this.updateBatchById(updateList);
+        }
+        return true;
+    }
+
+    /**
+     * 鏍规嵁BOM鏌ヨ骞剁粍瑁呯粨鏋勬爲銆�
+     */
+    @Override
+    public List<TechnologyBomStructureVo> listByBomId(Long bomId) {
+        List<TechnologyBomStructureVo> list = technologyBomStructureMapper.listByBomId(bomId);
+        Map<Long, TechnologyBomStructureVo> map = new HashMap<>();
+        for (TechnologyBomStructureVo node : list) {
+            node.setChildren(new ArrayList<>());
+            map.put(node.getId(), node);
+        }
+
+        List<TechnologyBomStructureVo> tree = new ArrayList<>();
+        for (TechnologyBomStructureVo node : list) {
+            Long parentId = node.getParentId();
+            if (parentId == null || parentId == 0L) {
+                tree.add(node);
+                continue;
+            }
+            TechnologyBomStructureVo parent = map.get(parentId);
+            if (parent != null) {
+                parent.getChildren().add(node);
+            }
+        }
+        return tree;
+    }
+
+    /**
+     * 灏嗘爲褰㈢粨鏋勬媿骞虫垚鍒楄〃锛屼究浜庣粺涓�淇濆瓨銆�
+     */
+    private void flattenTree(List<TechnologyBomStructureDto> source, List<TechnologyBomStructureDto> result) {
+        if (source == null) {
+            return;
+        }
+        for (TechnologyBomStructureDto node : source) {
+            result.add(node);
+            flattenTree(node.getChildren(), result);
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java
new file mode 100644
index 0000000..107fa22
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java
@@ -0,0 +1,75 @@
+package com.ruoyi.technology.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.technology.bean.dto.TechnologyOperationParamDto;
+import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo;
+import com.ruoyi.technology.mapper.TechnologyOperationMapper;
+import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
+import com.ruoyi.technology.mapper.TechnologyParamMapper;
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import com.ruoyi.technology.pojo.TechnologyParam;
+import com.ruoyi.technology.service.TechnologyOperationParamService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class TechnologyOperationParamServiceImpl extends ServiceImpl<TechnologyOperationParamMapper, TechnologyOperationParam> implements TechnologyOperationParamService {
+
+    private final TechnologyOperationParamMapper technologyOperationParamMapper;
+    private final TechnologyOperationMapper technologyOperationMapper;
+    private final TechnologyParamMapper technologyParamMapper;
+
+    /**
+     * 鎸夊伐搴忔垨鍙傛暟鏉′欢鏌ヨ宸ュ簭鍙傛暟鍒楄〃銆�
+     */
+    @Override
+    public List<TechnologyOperationParamVo> listOperationParam(TechnologyOperationParamDto technologyOperationParamDto) {
+        Long operationId = technologyOperationParamDto == null ? null : technologyOperationParamDto.getTechnologyOperationId();
+        Long paramId = technologyOperationParamDto == null ? null : technologyOperationParamDto.getTechnologyParamId();
+        return technologyOperationParamMapper.listOperationParam(operationId, paramId);
+    }
+
+    /**
+     * 淇濆瓨宸ュ簭鍙傛暟骞舵牎楠屽伐搴忋�佸弬鏁板拰鍞竴鎬с��
+     */
+    @Override
+    public boolean saveTechnologyOperationParam(TechnologyOperationParam technologyOperationParam) {
+        if (technologyOperationParam.getTechnologyOperationId() == null
+                || technologyOperationMapper.selectById(technologyOperationParam.getTechnologyOperationId()) == null) {
+            throw new ServiceException("Operation not found");
+        }
+        if (technologyOperationParam.getTechnologyParamId() == null) {
+            throw new ServiceException("Param is required");
+        }
+        TechnologyParam technologyParam = technologyParamMapper.selectById(technologyOperationParam.getTechnologyParamId());
+        if (technologyParam == null) {
+            throw new ServiceException("Param not found");
+        }
+        boolean duplicate = technologyOperationParamMapper.selectCount(Wrappers.<TechnologyOperationParam>lambdaQuery()
+                .eq(TechnologyOperationParam::getTechnologyOperationId, technologyOperationParam.getTechnologyOperationId())
+                .eq(TechnologyOperationParam::getTechnologyParamId, technologyOperationParam.getTechnologyParamId())
+                .ne(technologyOperationParam.getId() != null, TechnologyOperationParam::getId, technologyOperationParam.getId())) > 0;
+        if (duplicate) {
+            throw new ServiceException("Duplicate param in operation");
+        }
+        return this.saveOrUpdate(technologyOperationParam);
+    }
+
+    /**
+     * 鍒犻櫎鍗曚釜宸ュ簭鍙傛暟銆�
+     */
+    @Override
+    public String batchDelete(Long id) {
+        TechnologyOperationParam deleteItem = technologyOperationParamMapper.selectById(id);
+        if (deleteItem == null) {
+            return "Delete failed";
+        }
+        technologyOperationParamMapper.deleteById(id);
+        return "Success";
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java
new file mode 100644
index 0000000..da9ed8b
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java
@@ -0,0 +1,89 @@
+package com.ruoyi.technology.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.technology.bean.dto.TechnologyOperationDto;
+import com.ruoyi.technology.bean.vo.TechnologyOperationVo;
+import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
+import com.ruoyi.technology.mapper.TechnologyOperationMapper;
+import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+import com.ruoyi.technology.pojo.TechnologyOperation;
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import com.ruoyi.technology.service.TechnologyOperationService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class TechnologyOperationServiceImpl extends ServiceImpl<TechnologyOperationMapper, TechnologyOperation> implements TechnologyOperationService {
+
+    private final TechnologyOperationMapper technologyOperationMapper;
+    private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+    private final TechnologyBomStructureMapper technologyBomStructureMapper;
+    private final TechnologyOperationParamMapper technologyOperationParamMapper;
+
+    /**
+     * 鍒嗛〉鏌ヨ宸ュ簭鍒楄〃銆�
+     */
+    @Override
+    public IPage<TechnologyOperationVo> listPage(Page<TechnologyOperationDto> page, TechnologyOperationDto technologyOperationDto) {
+        return technologyOperationMapper.listPage(page, technologyOperationDto);
+    }
+
+    /**
+     * 鏂板宸ュ簭骞惰ˉ榻愬伐搴忕紪鐮併��
+     */
+    @Override
+    public R add(TechnologyOperationDto technologyOperationDto) {
+        TechnologyOperation technologyOperation = new TechnologyOperation();
+        BeanUtils.copyProperties(technologyOperationDto, technologyOperation);
+        boolean saved = technologyOperationMapper.insert(technologyOperation) > 0;
+        if (saved && ObjectUtils.isNull(technologyOperationDto.getNo())) {
+            technologyOperation.setNo("GX" + String.format("%08d", technologyOperation.getId()));
+            technologyOperationMapper.updateById(technologyOperation);
+        }
+        return R.ok();
+    }
+
+    /**
+     * 鍒犻櫎宸ュ簭鍓嶆牎楠屾槸鍚﹀凡琚獴OM缁撴瀯鎴栧伐鑹鸿矾绾垮紩鐢ㄣ��
+     */
+    @Override
+    public String batchDelete(List<Long> ids) {
+        List<TechnologyRoutingOperation> routingOperations = technologyRoutingOperationMapper.selectList(
+                Wrappers.<TechnologyRoutingOperation>lambdaQuery().in(TechnologyRoutingOperation::getTechnologyOperationId, ids));
+        List<TechnologyBomStructure> bomStructures = technologyBomStructureMapper.selectList(
+                Wrappers.<TechnologyBomStructure>lambdaQuery().in(TechnologyBomStructure::getOperationId, ids));
+        if (!CollectionUtils.isEmpty(routingOperations) || !CollectionUtils.isEmpty(bomStructures)) {
+            throw new RuntimeException("Operation is referenced and cannot be deleted");
+        }
+        technologyOperationParamMapper.delete(Wrappers.<TechnologyOperationParam>lambdaQuery()
+                .in(TechnologyOperationParam::getTechnologyOperationId, ids));
+        technologyOperationMapper.deleteBatchIds(ids);
+        return null;
+    }
+
+    /**
+     * 鏌ヨ鍏ㄩ儴宸ュ簭骞惰浆鎹负杩斿洖瀵硅薄銆�
+     */
+    @Override
+    public List<TechnologyOperationVo> listVo() {
+        return this.list().stream().map(item -> {
+            TechnologyOperationVo vo = new TechnologyOperationVo();
+            BeanUtils.copyProperties(item, vo);
+            return vo;
+        }).collect(Collectors.toList());
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java
new file mode 100644
index 0000000..a3e8f5e
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java
@@ -0,0 +1,170 @@
+package com.ruoyi.technology.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.technology.bean.dto.TechnologyParamDto;
+import com.ruoyi.technology.bean.vo.TechnologyParamVo;
+import com.ruoyi.technology.mapper.TechnologyParamMapper;
+import com.ruoyi.technology.pojo.TechnologyParam;
+import com.ruoyi.technology.service.TechnologyParamService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class TechnologyParamServiceImpl extends ServiceImpl<TechnologyParamMapper, TechnologyParam> implements TechnologyParamService {
+
+    private static final List<Integer> VALID_PARAM_TYPES = Arrays.asList(1, 2, 3, 4);
+    private static final String PARAM_CODE_PREFIX = "PARAM_";
+    private static final Byte DATE_PARAM_TYPE = (byte) 4;
+
+    /**
+     * 鍒嗛〉鏌ヨ鍩虹鍙傛暟骞舵牸寮忓寲鏃ユ湡绫诲瀷灞曠ず銆�
+     */
+    @Override
+    public IPage<TechnologyParamVo> baseParamList(Page<TechnologyParamDto> page, TechnologyParamDto baseParam) {
+        LambdaQueryWrapper<TechnologyParam> queryWrapper = new LambdaQueryWrapper<>();
+        if (baseParam != null && StringUtils.isNotEmpty(baseParam.getParamName())) {
+            queryWrapper.like(TechnologyParam::getParamName, baseParam.getParamName());
+        }
+        queryWrapper.orderByDesc(TechnologyParam::getId);
+
+        Page<TechnologyParam> entityPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
+        Page<TechnologyParam> paramPage = page(entityPage, queryWrapper);
+
+        Page<TechnologyParamVo> resultPage = new Page<>(paramPage.getCurrent(), paramPage.getSize(), paramPage.getTotal());
+        List<TechnologyParamVo> records = new ArrayList<>(paramPage.getRecords().size());
+        for (TechnologyParam item : paramPage.getRecords()) {
+            TechnologyParamVo vo = new TechnologyParamVo();
+            BeanUtils.copyProperties(item, vo);
+            if (DATE_PARAM_TYPE.equals(item.getParamType()) && StringUtils.isNotEmpty(item.getParamFormat())) {
+                vo.setParamFormat(toDisplayDatePattern(item.getParamFormat()));
+            }
+            records.add(vo);
+        }
+        resultPage.setRecords(records);
+        return resultPage;
+    }
+
+    /**
+     * 鏂板鍩虹鍙傛暟骞剁敓鎴愬敮涓�鍙傛暟缂栫爜銆�
+     */
+    @Override
+    public int addBaseParam(TechnologyParamDto baseParam) {
+        if (baseParam == null) {
+            throw new RuntimeException("鏂板鍙傛暟涓嶈兘涓虹┖");
+        }
+        checkBaseParam(baseParam);
+        baseParam.setParamCode(generateParamCode());
+        baseParam.setCreateUser(SecurityUtils.getUsername());
+        baseParam.setCreateTime(LocalDateTime.now());
+        if (baseParam.getIsRequired() == null) {
+            baseParam.setIsRequired((byte) 0);
+        }
+        return baseMapper.insert(baseParam);
+    }
+
+    /**
+     * 淇敼鍩虹鍙傛暟骞朵繚鐣欏師鏈夊弬鏁扮紪鐮併��
+     */
+    @Override
+    public int updateBaseParam(TechnologyParamDto baseParam) {
+        if (baseParam == null || baseParam.getId() == null) {
+            throw new RuntimeException("淇敼鍙傛暟ID涓嶈兘涓虹┖");
+        }
+        checkBaseParam(baseParam);
+        TechnologyParam current = baseMapper.selectById(baseParam.getId());
+        if (current == null) {
+            throw new RuntimeException("鍙傛暟涓嶅瓨鍦�");
+        }
+        if (StringUtils.isEmpty(baseParam.getParamCode())) {
+            baseParam.setParamCode(current.getParamCode());
+        }
+        baseParam.setUpdateUser(SecurityUtils.getUsername());
+        baseParam.setUpdateTime(LocalDateTime.now());
+        return baseMapper.updateById(baseParam);
+    }
+
+    /**
+     * 鍙傛暟瀹氫箟鍚堟硶鏍¢獙銆�
+     */
+    private void checkBaseParam(TechnologyParamDto baseParam) {
+        if (StringUtils.isEmpty(baseParam.getParamName())) {
+            throw new RuntimeException("鍙傛暟鍚嶇О涓嶈兘涓虹┖");
+        }
+        if (baseParam.getParamType() == null || !VALID_PARAM_TYPES.contains(Integer.valueOf(baseParam.getParamType()))) {
+            throw new RuntimeException("闈炴硶鍙傛暟绫诲瀷");
+        }
+
+        if (DATE_PARAM_TYPE.equals(baseParam.getParamType())) {
+            if (StringUtils.isEmpty(baseParam.getParamFormat())) {
+                throw new RuntimeException("鏃ユ湡绫诲瀷蹇呴』閰嶇疆鍙傛暟鏍煎紡(濡�: yyyy-MM-dd)");
+            }
+            try {
+                String standardPattern = normalizeDatePattern(baseParam.getParamFormat());
+                DateTimeFormatter.ofPattern(standardPattern);
+                baseParam.setParamFormat(standardPattern);
+            } catch (Exception e) {
+                throw new RuntimeException("鏃ユ湡鏍煎紡闈炴硶: " + baseParam.getParamFormat());
+            }
+        } else {
+            baseParam.setParamFormat(baseParam.getParamFormat());
+        }
+    }
+
+    /**
+     * 鐢熸垚鍙傛暟鍞竴缂栫爜锛屼緵宸ヨ壓鍙傛暟鍜岀敓浜ц鍗曞揩鐓у紩鐢ㄣ��
+     */
+    private String generateParamCode() {
+        LambdaQueryWrapper<TechnologyParam> wrapper = new LambdaQueryWrapper<>();
+        wrapper.select(TechnologyParam::getParamCode)
+                .likeRight(TechnologyParam::getParamCode, PARAM_CODE_PREFIX)
+                .orderByDesc(TechnologyParam::getParamCode)
+                .last("limit 1");
+
+        TechnologyParam last = baseMapper.selectOne(wrapper);
+        int nextNum = 1;
+        if (last != null && StringUtils.isNotEmpty(last.getParamCode())) {
+            try {
+                String numStr = last.getParamCode().replace(PARAM_CODE_PREFIX, "");
+                nextNum = Integer.parseInt(numStr) + 1;
+            } catch (Exception e) {
+                log.error("瑙f瀽 paramCode 寮傚父", e);
+            }
+        }
+        return PARAM_CODE_PREFIX + String.format("%04d", nextNum);
+    }
+
+    private String normalizeDatePattern(String pattern) {
+        return pattern.trim()
+                .replace('Y', 'y')
+                .replace('D', 'd')
+                .replace('S', 's');
+    }
+
+    private String toDisplayDatePattern(String pattern) {
+        return normalizeDatePattern(pattern);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鍩虹鍙傛暟銆�
+     */
+    @Override
+    public int deleteBaseParamByIds(Long[] ids) {
+        if (ids == null || ids.length == 0) {
+            throw new RuntimeException("鍒犻櫎ID涓嶈兘涓虹┖");
+        }
+        return baseMapper.deleteBatchIds(Arrays.asList(ids));
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationParamServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationParamServiceImpl.java
new file mode 100644
index 0000000..9f270fa
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationParamServiceImpl.java
@@ -0,0 +1,228 @@
+package com.ruoyi.technology.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamDto;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamSyncDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationParamVo;
+import com.ruoyi.technology.mapper.TechnologyOperationParamMapper;
+import com.ruoyi.technology.mapper.TechnologyParamMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationParamMapper;
+import com.ruoyi.technology.pojo.TechnologyOperationParam;
+import com.ruoyi.technology.pojo.TechnologyParam;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam;
+import com.ruoyi.technology.service.TechnologyRoutingOperationParamService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class TechnologyRoutingOperationParamServiceImpl extends ServiceImpl<TechnologyRoutingOperationParamMapper, TechnologyRoutingOperationParam>
+        implements TechnologyRoutingOperationParamService {
+
+    private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper;
+    private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+    private final TechnologyOperationParamMapper technologyOperationParamMapper;
+    private final TechnologyParamMapper technologyParamMapper;
+
+    @Override
+    public IPage<TechnologyRoutingOperationParamVo> pageTechnologyRoutingOperationParam(Page<TechnologyRoutingOperationParamDto> page,
+                                                                                         TechnologyRoutingOperationParamDto dto) {
+        Page<TechnologyRoutingOperationParam> entityPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
+        return this.page(entityPage, buildQueryWrapper(dto))
+                .convert(item -> BeanUtil.copyProperties(item, TechnologyRoutingOperationParamVo.class));
+    }
+
+    @Override
+    public List<TechnologyRoutingOperationParamVo> listTechnologyRoutingOperationParam(TechnologyRoutingOperationParamDto dto) {
+        return BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), TechnologyRoutingOperationParamVo.class);
+    }
+
+    @Override
+    public TechnologyRoutingOperationParamVo getTechnologyRoutingOperationParamInfo(Long id) {
+        TechnologyRoutingOperationParam item = this.getById(id);
+        if (item == null) {
+            return null;
+        }
+        return BeanUtil.copyProperties(item, TechnologyRoutingOperationParamVo.class);
+    }
+
+    @Override
+    public boolean saveTechnologyRoutingOperationParam(TechnologyRoutingOperationParam item) {
+        TechnologyRoutingOperation routingOperation = getRoutingOperation(item.getTechnologyRoutingOperationId());
+        fillFromOperationParam(item, routingOperation);
+        checkDuplicate(item);
+        return this.saveOrUpdate(item);
+    }
+
+    @Override
+    public boolean removeTechnologyRoutingOperationParam(Long id) {
+        return this.removeById(id);
+    }
+
+    @Override
+    public int syncTechnologyRoutingOperationParam(TechnologyRoutingOperationParamSyncDto syncDto) {
+        if (syncDto == null || syncDto.getTechnologyRoutingOperationId() == null) {
+            throw new ServiceException("宸ヨ壓璺嚎宸ュ簭ID涓嶈兘涓虹┖");
+        }
+        TechnologyRoutingOperation routingOperation = getRoutingOperation(syncDto.getTechnologyRoutingOperationId());
+        List<TechnologyOperationParam> operationParamList = technologyOperationParamMapper.selectList(
+                Wrappers.<TechnologyOperationParam>lambdaQuery()
+                        .eq(TechnologyOperationParam::getTechnologyOperationId, routingOperation.getTechnologyOperationId())
+                        .orderByAsc(TechnologyOperationParam::getId)
+        );
+        boolean replaceExisting = syncDto.getReplaceExisting() == null || syncDto.getReplaceExisting();
+        if (replaceExisting) {
+            technologyRoutingOperationParamMapper.delete(
+                    Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
+                            .eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, routingOperation.getId())
+            );
+        }
+        int successCount = 0;
+        if (CollectionUtils.isNotEmpty(operationParamList)) {
+            for (TechnologyOperationParam operationParam : operationParamList) {
+                boolean exists = technologyRoutingOperationParamMapper.selectCount(
+                        Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
+                                .eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, routingOperation.getId())
+                                .eq(TechnologyRoutingOperationParam::getTechnologyOperationParamId, operationParam.getId())
+                ) > 0;
+                if (!replaceExisting && exists) {
+                    continue;
+                }
+                TechnologyRoutingOperationParam snapshot = new TechnologyRoutingOperationParam();
+                snapshot.setTechnologyRoutingOperationId(routingOperation.getId());
+                snapshot.setTechnologyOperationParamId(operationParam.getId());
+                snapshot.setTechnologyOperationId(operationParam.getTechnologyOperationId());
+                snapshot.setStandardValue(operationParam.getStandardValue());
+                fillFromOperationParam(snapshot, routingOperation);
+                technologyRoutingOperationParamMapper.insert(snapshot);
+                successCount++;
+            }
+        }
+        return successCount;
+    }
+
+    private LambdaQueryWrapper<TechnologyRoutingOperationParam> buildQueryWrapper(TechnologyRoutingOperationParamDto dto) {
+        TechnologyRoutingOperationParam query = dto == null ? new TechnologyRoutingOperationParam() : dto;
+        return Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
+                .eq(query.getId() != null, TechnologyRoutingOperationParam::getId, query.getId())
+                .eq(query.getTechnologyRoutingOperationId() != null,
+                        TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, query.getTechnologyRoutingOperationId())
+                .eq(query.getTechnologyOperationId() != null,
+                        TechnologyRoutingOperationParam::getTechnologyOperationId, query.getTechnologyOperationId())
+                .eq(query.getTechnologyOperationParamId() != null,
+                        TechnologyRoutingOperationParam::getTechnologyOperationParamId, query.getTechnologyOperationParamId())
+                .eq(query.getParamId() != null, TechnologyRoutingOperationParam::getParamId, query.getParamId())
+                .eq(query.getParamType() != null, TechnologyRoutingOperationParam::getParamType, query.getParamType())
+                .like(query.getParamCode() != null && !query.getParamCode().isEmpty(),
+                        TechnologyRoutingOperationParam::getParamCode, query.getParamCode())
+                .like(query.getParamName() != null && !query.getParamName().isEmpty(),
+                        TechnologyRoutingOperationParam::getParamName, query.getParamName())
+                .orderByAsc(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId)
+                .orderByAsc(TechnologyRoutingOperationParam::getId);
+    }
+
+    private TechnologyRoutingOperation getRoutingOperation(Long technologyRoutingOperationId) {
+        if (technologyRoutingOperationId == null) {
+            throw new ServiceException("宸ヨ壓璺嚎宸ュ簭ID涓嶈兘涓虹┖");
+        }
+        TechnologyRoutingOperation routingOperation = technologyRoutingOperationMapper.selectById(technologyRoutingOperationId);
+        if (routingOperation == null) {
+            throw new ServiceException("宸ヨ壓璺嚎宸ュ簭涓嶅瓨鍦�");
+        }
+        return routingOperation;
+    }
+
+    private void fillFromOperationParam(TechnologyRoutingOperationParam item, TechnologyRoutingOperation routingOperation) {
+        if (item.getTechnologyOperationId() == null) {
+            item.setTechnologyOperationId(routingOperation.getTechnologyOperationId());
+        } else if (!item.getTechnologyOperationId().equals(routingOperation.getTechnologyOperationId())) {
+            throw new ServiceException("宸ュ簭ID涓庡伐鑹鸿矾绾垮伐搴忎笉鍖归厤");
+        }
+
+        if (item.getTechnologyOperationParamId() != null) {
+            TechnologyOperationParam operationParam = technologyOperationParamMapper.selectById(item.getTechnologyOperationParamId());
+            if (operationParam == null) {
+                throw new ServiceException("宸ュ簭鍙傛暟涓嶅瓨鍦�");
+            }
+            if (!routingOperation.getTechnologyOperationId().equals(operationParam.getTechnologyOperationId())) {
+                throw new ServiceException("宸ュ簭鍙傛暟涓嶅睘浜庡綋鍓嶅伐鑹鸿矾绾垮伐搴�");
+            }
+            TechnologyParam technologyParam = technologyParamMapper.selectById(operationParam.getTechnologyParamId());
+            if (technologyParam == null) {
+                throw new ServiceException("鍩虹鍙傛暟涓嶅瓨鍦�");
+            }
+            fillFromTechnologyParam(item, technologyParam);
+            if (item.getStandardValue() == null) {
+                item.setStandardValue(operationParam.getStandardValue());
+            }
+            return;
+        }
+
+        if (item.getParamId() != null) {
+            TechnologyParam technologyParam = technologyParamMapper.selectById(item.getParamId());
+            if (technologyParam == null) {
+                throw new ServiceException("鍩虹鍙傛暟涓嶅瓨鍦�");
+            }
+            fillFromTechnologyParam(item, technologyParam);
+            TechnologyOperationParam operationParam = technologyOperationParamMapper.selectOne(
+                    Wrappers.<TechnologyOperationParam>lambdaQuery()
+                            .eq(TechnologyOperationParam::getTechnologyOperationId, routingOperation.getTechnologyOperationId())
+                            .eq(TechnologyOperationParam::getTechnologyParamId, item.getParamId())
+                            .orderByAsc(TechnologyOperationParam::getId)
+                            .last("limit 1")
+            );
+            if (operationParam != null) {
+                item.setTechnologyOperationParamId(operationParam.getId());
+                if (item.getStandardValue() == null) {
+                    item.setStandardValue(operationParam.getStandardValue());
+                }
+            }
+            return;
+        }
+
+        throw new ServiceException("paramId鎴杢echnologyOperationParamId涓嶈兘涓虹┖");
+    }
+
+    private void fillFromTechnologyParam(TechnologyRoutingOperationParam item, TechnologyParam technologyParam) {
+        item.setParamId(technologyParam.getId());
+        item.setParamCode(technologyParam.getParamCode());
+        item.setParamName(technologyParam.getParamName());
+        item.setParamType(technologyParam.getParamType());
+        item.setParamFormat(technologyParam.getParamFormat());
+        item.setUnit(technologyParam.getUnit());
+        item.setIsRequired(technologyParam.getIsRequired());
+        if (item.getRemark() == null || item.getRemark().trim().isEmpty()) {
+            item.setRemark(technologyParam.getRemark());
+        }
+    }
+
+    private void checkDuplicate(TechnologyRoutingOperationParam item) {
+        boolean duplicate = technologyRoutingOperationParamMapper.selectCount(
+                Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
+                        .eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, item.getTechnologyRoutingOperationId())
+                        .eq(item.getTechnologyOperationParamId() != null,
+                                TechnologyRoutingOperationParam::getTechnologyOperationParamId, item.getTechnologyOperationParamId())
+                        .eq(item.getTechnologyOperationParamId() == null && item.getParamId() != null,
+                                TechnologyRoutingOperationParam::getParamId, item.getParamId())
+                        .eq(item.getTechnologyOperationParamId() == null && item.getParamId() == null && item.getParamCode() != null,
+                                TechnologyRoutingOperationParam::getParamCode, item.getParamCode())
+                        .ne(item.getId() != null, TechnologyRoutingOperationParam::getId, item.getId())
+        ) > 0;
+        if (duplicate) {
+            throw new ServiceException("宸ヨ壓璺嚎宸ュ簭鍙傛暟閲嶅");
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationServiceImpl.java
new file mode 100644
index 0000000..bff3a44
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationServiceImpl.java
@@ -0,0 +1,142 @@
+package com.ruoyi.technology.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationDto;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamSyncDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo;
+import com.ruoyi.technology.mapper.TechnologyRoutingMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
+import com.ruoyi.technology.service.TechnologyRoutingOperationParamService;
+import com.ruoyi.technology.service.TechnologyRoutingOperationService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class TechnologyRoutingOperationServiceImpl extends ServiceImpl<TechnologyRoutingOperationMapper, TechnologyRoutingOperation> implements TechnologyRoutingOperationService {
+
+    private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+
+    private final TechnologyRoutingMapper technologyRoutingMapper;
+    private final TechnologyRoutingOperationParamService technologyRoutingOperationParamService;
+
+    @Override
+    public IPage<TechnologyRoutingOperationVo> pageTechnologyRoutingOperation(Page<TechnologyRoutingOperationDto> page,
+                                                                              TechnologyRoutingOperationDto technologyRoutingOperationDto) {
+        return technologyRoutingOperationMapper.pageTechnologyRoutingOperation(page, technologyRoutingOperationDto);
+    }
+
+    @Override
+    public List<TechnologyRoutingOperationVo> listTechnologyRoutingOperation(TechnologyRoutingOperationDto technologyRoutingOperationDto) {
+        return technologyRoutingOperationMapper.listTechnologyRoutingOperation(technologyRoutingOperationDto);
+    }
+
+    @Override
+    public TechnologyRoutingOperationVo getTechnologyRoutingOperationInfo(Long id) {
+        return technologyRoutingOperationMapper.getTechnologyRoutingOperationInfo(id);
+    }
+
+    @Override
+    public boolean saveTechnologyRoutingOperation(TechnologyRoutingOperation technologyRoutingOperation) {
+        if (technologyRoutingOperation.getTechnologyRoutingId() == null
+                || technologyRoutingMapper.selectById(technologyRoutingOperation.getTechnologyRoutingId()) == null) {
+            throw new RuntimeException("宸ヨ壓璺嚎涓嶅瓨鍦紝鏃犳硶淇濆瓨宸ュ簭");
+        }
+        if (technologyRoutingOperation.getDragSort() == null || technologyRoutingOperation.getDragSort() <= 0) {
+            technologyRoutingOperation.setDragSort(nextDragSort(technologyRoutingOperation.getTechnologyRoutingId()));
+        }
+        boolean saved = this.save(technologyRoutingOperation);
+        if (saved) {
+            TechnologyRoutingOperationParamSyncDto syncDto = new TechnologyRoutingOperationParamSyncDto();
+            syncDto.setTechnologyRoutingOperationId(technologyRoutingOperation.getId());
+            syncDto.setReplaceExisting(true);
+            technologyRoutingOperationParamService.syncTechnologyRoutingOperationParam(syncDto);
+        }
+        return saved;
+    }
+
+    @Override
+    public boolean removeTechnologyRoutingOperation(Long id) {
+        TechnologyRoutingOperation technologyRoutingOperation = this.getById(id);
+        if (technologyRoutingOperation == null) {
+            return false;
+        }
+        boolean removed = this.removeById(id);
+        if (removed) {
+            resetDragSort(technologyRoutingOperation.getTechnologyRoutingId());
+        }
+        return removed;
+    }
+
+    @Override
+    public int sort(TechnologyRoutingOperation technologyRoutingOperation) {
+        //鏌ヨ琚敼鍔ㄧ殑杩欐潯鏁版嵁
+        TechnologyRoutingOperation oldtechnologyRoutingOperation = technologyRoutingOperationMapper.selectById(technologyRoutingOperation.getId());
+        //鏌ヨ璇ュ伐鑹鸿矾绾跨殑鎵�鏈夊伐搴忓苟鎸夌収椤哄簭鎺掑簭
+        List<TechnologyRoutingOperation> technologyRouteOperations = technologyRoutingOperationMapper.selectList(Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                .eq(TechnologyRoutingOperation::getTechnologyRoutingId, oldtechnologyRoutingOperation.getTechnologyRoutingId())
+                .orderByAsc(TechnologyRoutingOperation::getDragSort));
+        // 鑾峰彇鐩爣浣嶇疆锛堢Щ鍔ㄥ埌绗嚑涓箣鍚庯級
+        Integer targetPosition = technologyRoutingOperation.getDragSort();
+        if (targetPosition != null && targetPosition >= 0) {
+            // 绉诲姩鍏冪礌鍒版柊鐨勪綅缃�
+            technologyRouteOperations.remove(oldtechnologyRoutingOperation);
+            technologyRouteOperations.add(targetPosition-1, oldtechnologyRoutingOperation);
+            // 鏇存柊鎵�鏈夊彈褰卞搷鐨勬帓搴忓瓧娈�
+            for (int i = 0; i < technologyRouteOperations.size(); i++) {
+                TechnologyRoutingOperation item = technologyRouteOperations.get(i);
+                if (!item.getId().equals(oldtechnologyRoutingOperation.getId())) {
+                    // 妫�鏌ユ槸鍚﹂渶瑕佹洿鏂版帓搴忓��
+                    if (item.getDragSort() != i+1) {
+                        item.setDragSort(i+1);
+                        technologyRoutingOperationMapper.updateById(item);
+                    }
+                } else {
+                    // 鏇存柊鍘熻褰曠殑鏂版帓搴忎綅缃�
+                    oldtechnologyRoutingOperation.setDragSort(targetPosition);
+                    technologyRoutingOperationMapper.updateById(oldtechnologyRoutingOperation);
+                }
+            }
+            return 1;
+        }
+        return 0;
+    }
+
+    private Integer nextDragSort(Long technologyRoutingId) {
+        TechnologyRoutingOperation lastOperation = technologyRoutingOperationMapper.selectOne(
+                Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                        .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRoutingId)
+                        .orderByDesc(TechnologyRoutingOperation::getDragSort)
+                        .last("limit 1")
+        );
+        if (lastOperation == null || lastOperation.getDragSort() == null) {
+            return 1;
+        }
+        return lastOperation.getDragSort() + 1;
+    }
+
+    private void resetDragSort(Long technologyRoutingId) {
+        List<TechnologyRoutingOperation> operationList = technologyRoutingOperationMapper.selectList(
+                Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                        .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRoutingId)
+                        .orderByAsc(TechnologyRoutingOperation::getDragSort)
+                        .orderByAsc(TechnologyRoutingOperation::getId)
+        );
+        for (int i = 0; i < operationList.size(); i++) {
+            TechnologyRoutingOperation item = operationList.get(i);
+            int dragSort = i + 1;
+            if (item.getDragSort() == null || item.getDragSort() != dragSort) {
+                item.setDragSort(dragSort);
+                technologyRoutingOperationMapper.updateById(item);
+            }
+        }
+    }
+}
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
new file mode 100644
index 0000000..4079f84
--- /dev/null
+++ b/src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingServiceImpl.java
@@ -0,0 +1,224 @@
+package com.ruoyi.technology.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.OrderUtils;
+import com.ruoyi.technology.bean.dto.TechnologyRoutingDto;
+import com.ruoyi.technology.bean.vo.TechnologyRoutingVo;
+import com.ruoyi.technology.mapper.*;
+import com.ruoyi.technology.pojo.*;
+import com.ruoyi.technology.service.TechnologyRoutingService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Service
+@Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
+public class TechnologyRoutingServiceImpl extends ServiceImpl<TechnologyRoutingMapper, TechnologyRouting> implements TechnologyRoutingService {
+
+    private final TechnologyRoutingMapper technologyRoutingMapper;
+
+    private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+
+    private final TechnologyBomStructureMapper technologyBomStructureMapper;
+
+    private final TechnologyOperationMapper technologyOperationMapper;
+    private final TechnologyOperationParamMapper technologyOperationParamMapper;
+    private final TechnologyParamMapper technologyParamMapper;
+    private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper;
+
+    @Override
+    public IPage<TechnologyRoutingVo> pageTechnologyRouting(Page<TechnologyRoutingDto> page, TechnologyRoutingDto technologyRoutingDto) {
+        return technologyRoutingMapper.pageTechnologyRouting(page, technologyRoutingDto);
+    }
+
+    @Override
+    public TechnologyRoutingVo getTechnologyRoutingInfo(Long id) {
+        TechnologyRouting technologyRouting = this.getById(id);
+        if (technologyRouting == null) {
+            return null;
+        }
+        return BeanUtil.copyProperties(technologyRouting, TechnologyRoutingVo.class);
+    }
+
+    @Override
+    public Long saveTechnologyRouting(TechnologyRouting technologyRouting) {
+        String code = OrderUtils.countTodayByCreateTime(technologyRoutingMapper, "GYLX", "process_route_code");
+        technologyRouting.setProcessRouteCode(code);
+        technologyRoutingMapper.insert(technologyRouting);
+        // 甯﹀叆bom浜у搧缁撴瀯
+        syncRoutingOperationsByBom(technologyRouting);
+        return technologyRouting.getId();
+    }
+
+    @Override
+    public boolean updateTechnologyRouting(TechnologyRouting technologyRouting) {
+        boolean updated = this.updateById(technologyRouting);
+        if (updated) {
+            TechnologyRouting currentRouting = this.getById(technologyRouting.getId());
+            syncRoutingOperationsByBom(currentRouting);
+        }
+        return updated;
+    }
+
+    @Override
+    public boolean removeTechnologyRouting(List<Long> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        List<TechnologyRoutingOperation> routingOperationList = technologyRoutingOperationMapper.selectList(
+                Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                        .in(TechnologyRoutingOperation::getTechnologyRoutingId, ids));
+        if (!routingOperationList.isEmpty()) {
+            List<Long> routingOperationIdList = routingOperationList.stream().map(TechnologyRoutingOperation::getId).collect(Collectors.toList());
+            technologyRoutingOperationParamMapper.delete(Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
+                    .in(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, routingOperationIdList));
+        }
+        technologyRoutingOperationMapper.delete(Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                .in(TechnologyRoutingOperation::getTechnologyRoutingId, ids));
+        return this.removeByIds(ids);
+    }
+
+    /**
+     * 鎸夊綋鍓嶉�夋嫨鐨� BOM 閲嶅缓宸ヨ壓璺嚎宸ュ簭锛�
+     * 1. 鍏堝垹闄よ宸ヨ壓璺嚎涓嬪凡鏈夊伐搴�
+     * 2. 璇诲彇 BOM 缁撴瀯涓殑 operation_id
+     * 3. 鎸� BOM 鍑虹幇椤哄簭鍘婚噸鍚庨噸鏂板啓鍏ュ伐鑹鸿矾绾垮伐搴忚〃
+     */
+    private void syncRoutingOperationsByBom(TechnologyRouting technologyRouting) {
+        List<TechnologyRoutingOperation> oldRoutingOperationList = technologyRoutingOperationMapper.selectList(
+                Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                        .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId()));
+        if (!oldRoutingOperationList.isEmpty()) {
+            List<Long> oldRoutingOperationIdList = oldRoutingOperationList.stream().map(TechnologyRoutingOperation::getId).collect(Collectors.toList());
+            technologyRoutingOperationParamMapper.delete(Wrappers.<TechnologyRoutingOperationParam>lambdaQuery()
+                    .in(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, oldRoutingOperationIdList));
+            technologyRoutingOperationMapper.delete(Wrappers.<TechnologyRoutingOperation>lambdaQuery()
+                    .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId()));
+        }
+        if (technologyRouting.getBomId() == null) {
+            return;
+        }
+        List<TechnologyBomStructure> bomStructures = technologyBomStructureMapper.selectList(
+                Wrappers.<TechnologyBomStructure>lambdaQuery()
+                        .eq(TechnologyBomStructure::getBomId, technologyRouting.getBomId())
+                        .isNotNull(TechnologyBomStructure::getOperationId)
+                        .orderByDesc(TechnologyBomStructure::getId)
+        );
+        if (bomStructures.isEmpty()) {
+            throw new ServiceException("bom浜у搧缁撴瀯涓虹┖锛�");
+        }
+
+        // 鍚屼竴涓� BOM 涓彲鑳介噸澶嶅紩鐢ㄧ浉鍚屽伐搴忥紝鎸夌収涓婁竴灞傜殑鐖惰妭鐐圭殑浜у搧鏄惁鐩稿悓鍜屽伐搴忔槸鍚︾浉鍚�
+        Map<Long, TechnologyBomStructure> structureById = new HashMap<>();
+        for (TechnologyBomStructure bomStructure : bomStructures) {
+            if (bomStructure != null && bomStructure.getId() != null) {
+                structureById.put(bomStructure.getId(), bomStructure);
+            }
+        }
+
+        Map<String, TechnologyBomStructure> uniqueOperationMap = new LinkedHashMap<>();
+        for (TechnologyBomStructure bomStructure : bomStructures) {
+            Long outputProductModelId = resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId());
+            uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure);
+        }
+
+        int dragSort = 1;
+        for (TechnologyBomStructure bomStructure : uniqueOperationMap.values()) {
+            TechnologyRoutingOperation routingOperation = new TechnologyRoutingOperation();
+            routingOperation.setTechnologyRoutingId(technologyRouting.getId());
+            routingOperation.setProductModelId(resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId()));
+            routingOperation.setTechnologyOperationId(bomStructure.getOperationId());
+            routingOperation.setDragSort(dragSort++);
+            routingOperation.setIsQuality(getOperationQuality(bomStructure.getOperationId()));
+            technologyRoutingOperationMapper.insert(routingOperation);
+            syncRoutingOperationParams(routingOperation.getId(), bomStructure.getOperationId());
+        }
+    }
+
+    private String buildBomOperationDedupKey(TechnologyBomStructure bomStructure, Long outputProductModelId) {
+        Long operationId = bomStructure == null ? null : bomStructure.getOperationId();
+        Long parentId = bomStructure == null ? null : bomStructure.getParentId();
+        return operationId + "#"
+                + outputProductModelId + "#"
+                + parentId;
+    }
+
+    private Long resolveOutputProductModelId(TechnologyBomStructure bomStructure,
+                                             Map<Long, TechnologyBomStructure> structureById,
+                                             Long routingProductModelId) {
+        if (bomStructure == null) {
+            return routingProductModelId;
+        }
+        Long parentId = bomStructure.getParentId();
+        if (parentId == null) {
+            return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
+        }
+        TechnologyBomStructure parent = structureById.get(parentId);
+        if (parent != null && parent.getProductModelId() != null) {
+            return parent.getProductModelId();
+        }
+        return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId();
+    }
+
+    private void syncRoutingOperationParams(Long technologyRoutingOperationId, Long technologyOperationId) {
+        List<TechnologyOperationParam> operationParamList = technologyOperationParamMapper.selectList(
+                Wrappers.<TechnologyOperationParam>lambdaQuery()
+                        .eq(TechnologyOperationParam::getTechnologyOperationId, technologyOperationId)
+                        .orderByAsc(TechnologyOperationParam::getId));
+        if (operationParamList.isEmpty()) {
+            return;
+        }
+        for (TechnologyOperationParam operationParam : operationParamList) {
+            TechnologyParam technologyParam = technologyParamMapper.selectById(operationParam.getTechnologyParamId());
+            if (technologyParam == null) {
+                continue;
+            }
+            TechnologyRoutingOperationParam snapshot = new TechnologyRoutingOperationParam();
+            snapshot.setTechnologyRoutingOperationId(technologyRoutingOperationId);
+            snapshot.setTechnologyOperationParamId(operationParam.getId());
+            snapshot.setTechnologyOperationId(operationParam.getTechnologyOperationId());
+            snapshot.setParamId(technologyParam.getId());
+            snapshot.setParamCode(technologyParam.getParamCode());
+            snapshot.setParamName(technologyParam.getParamName());
+            snapshot.setParamType(technologyParam.getParamType());
+            snapshot.setParamFormat(technologyParam.getParamFormat());
+            snapshot.setUnit(technologyParam.getUnit());
+            snapshot.setIsRequired(technologyParam.getIsRequired());
+            snapshot.setRemark(technologyParam.getRemark());
+            snapshot.setStandardValue(operationParam.getStandardValue());
+            technologyRoutingOperationParamMapper.insert(snapshot);
+        }
+    }
+
+    /**
+     * 璐ㄦ鏍囪瘑浠ュ伐搴忓熀纭�琛ㄥ畾涔変负鍑嗐��
+     */
+    private Boolean getOperationQuality(Long operationId) {
+        TechnologyOperation technologyOperation = technologyOperationMapper.selectById(operationId);
+        return technologyOperation != null ? technologyOperation.getIsQuality() : null;
+    }
+
+    private String buildProcessRouteCode(Long id) {
+        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        String idStr = String.format("%06d", id);
+        return "GYLX" + dateStr + idStr;
+    }
+
+    private boolean isNotBlank(String value) {
+        return value != null && !value.trim().isEmpty();
+    }
+}
diff --git a/src/main/java/com/ruoyi/warehouse/controller/DocumentClassificationController.java b/src/main/java/com/ruoyi/warehouse/controller/DocumentClassificationController.java
index 625c82b..7b51803 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/DocumentClassificationController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/DocumentClassificationController.java
@@ -1,51 +1,51 @@
 package com.ruoyi.warehouse.controller;
 
-import com.ruoyi.basic.dto.ProductDto;
-import com.ruoyi.basic.dto.ProductTreeDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.warehouse.dto.DocumentClassificationDto;
-import com.ruoyi.warehouse.dto.DocumentClassificationTreeDto;
 import com.ruoyi.warehouse.pojo.DocumentClassification;
 import com.ruoyi.warehouse.service.DocumentClassificationService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
 @RestController
-@Api(tags = "鏂囨。鍒嗙被")
+@Tag(name = "鏂囨。鍒嗙被")
 @RequestMapping("/warehouse/documentClassification")
+@AllArgsConstructor
 public class DocumentClassificationController extends BaseController {
-    @Autowired
     private DocumentClassificationService documentClassificationService;
+
     //鏍戠粨鏋�
     @GetMapping("/getList")
-    public  AjaxResult getList() {
+    public AjaxResult getList() {
         return AjaxResult.success(documentClassificationService.selectDocumentClassificationList());
     }
+
     @PostMapping("/add")
-    @ApiOperation("鏂囨。鍒嗙被-娣诲姞")
+    @Operation(summary = "鏂囨。鍒嗙被-娣诲姞")
     @Log(title = "鏂囨。鍒嗙被-娣诲姞", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody DocumentClassification documentClassification) {
         return AjaxResult.success(documentClassificationService.save(documentClassification));
     }
+
     @PutMapping("/update")
-    @ApiOperation("鏂囨。鍒嗙被-鏇存柊")
+    @Operation(summary = "鏂囨。鍒嗙被-鏇存柊")
     @Log(title = "鏂囨。鍒嗙被-鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody DocumentClassification documentClassification) {
         return AjaxResult.success(documentClassificationService.updateById(documentClassification));
     }
+
     @DeleteMapping("/delete")
-    @ApiOperation("鏂囨。鍒嗙被鍒犻櫎")
+    @Operation(summary = "鏂囨。鍒嗙被鍒犻櫎")
     @Log(title = "鏂囨。鍒嗙被鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
-        if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
+        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         return AjaxResult.success(documentClassificationService.deleteByIds(ids));
     }
 
diff --git a/src/main/java/com/ruoyi/warehouse/controller/DocumentationBorrowManagementController.java b/src/main/java/com/ruoyi/warehouse/controller/DocumentationBorrowManagementController.java
index fdf07fd..2a1c966 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/DocumentationBorrowManagementController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/DocumentationBorrowManagementController.java
@@ -1,111 +1,102 @@
 package com.ruoyi.warehouse.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-
-import com.ruoyi.warehouse.mapper.DocumentationBorrowManagementMapper;
 import com.ruoyi.warehouse.mapper.DocumentationReturnManagementMapper;
 import com.ruoyi.warehouse.pojo.DocumentationBorrowManagement;
 import com.ruoyi.warehouse.pojo.DocumentationReturnManagement;
-import com.ruoyi.warehouse.pojo.Warehouse;
 import com.ruoyi.warehouse.service.DocumentationBorrowManagementService;
-import com.ruoyi.warehouse.service.WarehouseService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
-import java.time.LocalDateTime;
 import java.util.List;
 
 @RestController
-@Api(tags = "鏂囨。鍊熼槄绠$悊")
+@Tag(name = "鏂囨。鍊熼槄绠$悊")
 @RequestMapping("/documentationBorrowManagement")
+@AllArgsConstructor
 public class DocumentationBorrowManagementController extends BaseController {
-    @Autowired
+
     private DocumentationBorrowManagementService documentationBorrowManagementService;
-    @Autowired
-    private DocumentationBorrowManagementMapper documentationBorrowManagementMapper;
-    @Autowired
     private DocumentationReturnManagementMapper documentationReturnManagementMapper;
+
     @GetMapping("/listPage")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-鍊熼槄鍒嗛〉鏌ヨ")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-鍊熼槄鍒嗛〉鏌ヨ")
     @Log(title = "鏂囨。鍊熼槄绠$悊-鍊熼槄鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, DocumentationBorrowManagement documentationBorrowManagement) {
         return AjaxResult.success(documentationBorrowManagementService.listPage(page, documentationBorrowManagement));
     }
     @GetMapping("/list")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-鍊熼槄鏌ヨ")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-鍊熼槄鏌ヨ")
     @Log(title = "鏂囨。鍊熼槄绠$悊-鍊熼槄鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult list() {
         return AjaxResult.success(documentationBorrowManagementService.listAll());
     }
     @GetMapping("/listPageReturn")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-褰掕繕鍒嗛〉鏌ヨ")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-褰掕繕鍒嗛〉鏌ヨ")
     @Log(title = "鏂囨。鍊熼槄绠$悊-褰掕繕鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPageReturn(Page page, DocumentationReturnManagement documentationReturnManagement) {
         return AjaxResult.success(documentationReturnManagementMapper.listPage(page, documentationReturnManagement));
     }
     @GetMapping("/getByDocumentationId/{id}")
-    @ApiOperation("鏍规嵁涔︾睄id鏌ヨ鍊熼槄璁板綍")
+    @Operation(summary = "鏍规嵁涔︾睄id鏌ヨ鍊熼槄璁板綍")
     @Log(title = "鏍规嵁涔︾睄id鏌ヨ鍊熼槄璁板綍", businessType = BusinessType.OTHER)
     public AjaxResult getByDocumentationId(@PathVariable Long id) {
         return AjaxResult.success(documentationBorrowManagementService.selectByDocumentationId(id));
     }
     @PostMapping("/add")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-鍊熼槄")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-鍊熼槄")
     @Log(title = "鏂囨。鍊熼槄绠$悊-鍊熼槄", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody DocumentationBorrowManagement documentationBorrowManagement) {
         return AjaxResult.success(documentationBorrowManagementService.add(documentationBorrowManagement));
     }
     @PutMapping("/revent")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-褰掕繕")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-褰掕繕")
     @Log(title = "鏂囨。鍊熼槄绠$悊-褰掕繕", businessType = BusinessType.UPDATE)
     public AjaxResult revent(@RequestBody DocumentationReturnManagement documentationReturnManagement) {
         return AjaxResult.success(documentationBorrowManagementService.reventdbm(documentationReturnManagement));
     }
     @PutMapping("/update")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-鏇存柊")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-鏇存柊")
     @Log(title = "鏂囨。鍊熼槄绠$悊-鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody DocumentationBorrowManagement documentationBorrowManagement) {
         return AjaxResult.success(documentationBorrowManagementService.updateById(documentationBorrowManagement));
     }
     @PutMapping("/reventUpdate")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-褰掕繕鏇存柊")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-褰掕繕鏇存柊")
     @Log(title = "鏂囨。鍊熼槄绠$悊-褰掕繕鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult reventupdate(@RequestBody DocumentationReturnManagement documentationReturnManagement) {
         return AjaxResult.success(documentationReturnManagementMapper.updateById(documentationReturnManagement));
     }
     @DeleteMapping ("/delete")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-鍊熼槄鍒犻櫎")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-鍊熼槄鍒犻櫎")
     @Log(title = "鏂囨。鍊熼槄绠$悊-鍊熼槄鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         return AjaxResult.success(documentationBorrowManagementService.deleteByIds(ids));
     }
     @DeleteMapping ("/reventDelete")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-褰掕繕鍒犻櫎")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-褰掕繕鍒犻櫎")
     @Log(title = "鏂囨。鍊熼槄绠$悊-褰掕繕鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult reventdelete(@RequestBody List<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         return AjaxResult.success(documentationBorrowManagementService.reventDeleteByIds(ids));
     }
     @PostMapping("/export")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-鍊熼槄瀵煎嚭")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-鍊熼槄瀵煎嚭")
     @Log(title = "鏂囨。鍊熼槄绠$悊-鍊熼槄瀵煎嚭", businessType = BusinessType.EXPORT)
     public void export(HttpServletResponse response,DocumentationBorrowManagement documentationBorrowManagement) {
         documentationBorrowManagementService.export(response,documentationBorrowManagement);
     }
     @PostMapping("/exportrevent")
-    @ApiOperation("鏂囨。鍊熼槄绠$悊-褰掕繕瀵煎嚭")
+    @Operation(summary = "鏂囨。鍊熼槄绠$悊-褰掕繕瀵煎嚭")
     @Log(title = "鏂囨。鍊熼槄绠$悊-褰掕繕瀵煎嚭", businessType = BusinessType.EXPORT)
     public void exportrevent(HttpServletResponse response, DocumentationReturnManagement documentationReturnManagement) {
         documentationBorrowManagementService.exportrevent(response,documentationReturnManagement);
diff --git a/src/main/java/com/ruoyi/warehouse/controller/DocumentationController.java b/src/main/java/com/ruoyi/warehouse/controller/DocumentationController.java
index 586c330..427396b 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/DocumentationController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/DocumentationController.java
@@ -6,69 +6,73 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
-
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.warehouse.dto.DocumentationDto;
 import com.ruoyi.warehouse.pojo.Documentation;
-import com.ruoyi.warehouse.pojo.Warehouse;
 import com.ruoyi.warehouse.service.DocumentationService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 @RestController
 @RequestMapping("/documentation")
-@Api(tags = "鏂囨。淇℃伅琛�")
+@Tag(name = "鏂囨。淇℃伅琛�")
+@AllArgsConstructor
 public class DocumentationController extends BaseController {
-    @Autowired
     private DocumentationService documentationService;
+
     @GetMapping("/listPage")
-    @ApiOperation("鏂囨。淇℃伅琛�-鍒嗛〉鏌ヨ")
+    @Operation(summary = "鏂囨。淇℃伅琛�-鍒嗛〉鏌ヨ")
     @Log(title = "鏂囨。淇℃伅琛�-鍒嗛〉鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listPage(Page page, Documentation documentation) {
         IPage<DocumentationDto> list = documentationService.listPage(page, documentation);
         return AjaxResult.success(list);
     }
+
     @GetMapping("/list")
-    @ApiOperation("鏂囨。淇℃伅琛ㄦ煡璇�")
+    @Operation(summary = "鏂囨。淇℃伅琛ㄦ煡璇�")
     @Log(title = "鏂囨。淇℃伅琛ㄦ煡璇�", businessType = BusinessType.OTHER)
     public AjaxResult list() {
         List<DocumentationDto> list = documentationService.listAll();
         return AjaxResult.success(list);
     }
+
     @PostMapping("/add")
-    @ApiOperation("鏂囨。淇℃伅琛�-娣诲姞")
+    @Operation(summary = "鏂囨。淇℃伅琛�-娣诲姞")
     @Log(title = "鏂囨。淇℃伅琛�-娣诲姞", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody Documentation documentation) {
         return AjaxResult.success(documentationService.save(documentation));
     }
+
     @PutMapping("/update")
-    @ApiOperation("鏂囨。淇℃伅琛�-鏇存柊")
+    @Operation(summary = "鏂囨。淇℃伅琛�-鏇存柊")
     @Log(title = "鏂囨。淇℃伅琛�-鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody Documentation documentation) {
         return AjaxResult.success(documentationService.updateById(documentation));
     }
+
     @DeleteMapping("/delete")
-    @ApiOperation("鏂囨。淇℃伅琛�-鍒犻櫎")
+    @Operation(summary = "鏂囨。淇℃伅琛�-鍒犻櫎")
     @Log(title = "鏂囨。淇℃伅琛�-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
-        if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
+        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         return AjaxResult.success(documentationService.deleteByIds(ids));
     }
 
     @PostMapping("/export")
-    @ApiOperation("鏂囨。淇℃伅琛�-瀵煎嚭")
+    @Operation(summary = "鏂囨。淇℃伅琛�-瀵煎嚭")
     @Log(title = "鏂囨。淇℃伅琛�-瀵煎嚭", businessType = BusinessType.EXPORT)
-    public void export(HttpServletResponse response,Documentation documentation ) {
-        documentationService.export(response,documentation);
+    public void export(HttpServletResponse response, Documentation documentation) {
+        documentationService.export(response, documentation);
     }
-    @ApiOperation("鏂囨。淇℃伅琛�-缁熻")
+
+    @Operation(summary = "鏂囨。淇℃伅琛�-缁熻")
     @GetMapping("/overview")
     public AjaxResult getOverviewStatistics() {
         Map<String, Object> result = new HashMap<>();
@@ -78,12 +82,14 @@
         result.put("monthlyAddedDocsCount", documentationService.getMonthlyAddedDocsCount());
         return AjaxResult.success(result);
     }
-    @ApiOperation("鏂囨。淇℃伅琛�-鍒嗙被缁熻")
+
+    @Operation(summary = "鏂囨。淇℃伅琛�-鍒嗙被缁熻")
     @GetMapping("/category")
     public AjaxResult getCategoryDistribution() {
         return AjaxResult.success(documentationService.getCategoryDistribution());
     }
-    @ApiOperation("鏂囨。淇℃伅琛�-鐘舵�佺粺璁�")
+
+    @Operation(summary = "鏂囨。淇℃伅琛�-鐘舵�佺粺璁�")
     @GetMapping("/status")
     public AjaxResult getStatusDistribution() {
         return AjaxResult.success(documentationService.getStatusDistribution());
diff --git a/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java b/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java
index 13a1bc7..9c8517e 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java
@@ -9,7 +9,7 @@
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import javax.annotation.Resource;
+import jakarta.annotation.Resource;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/warehouse/controller/WarehouseController.java b/src/main/java/com/ruoyi/warehouse/controller/WarehouseController.java
index 0876334..7d80dd1 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/WarehouseController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/WarehouseController.java
@@ -1,63 +1,60 @@
 package com.ruoyi.warehouse.controller;
 
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.ruoyi.warehouse.pojo.Warehouse;
-import com.ruoyi.warehouse.pojo.WarehouseGoodsShelves;
-import com.ruoyi.warehouse.service.WarehouseGoodsShelvesService;
 import com.ruoyi.warehouse.service.WarehouseService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
 @RestController
-@Api(tags = "浠撳簱")
+@Tag(name = "浠撳簱")
 @RequestMapping("/warehouse")
+@AllArgsConstructor
 public class WarehouseController extends BaseController {
-    @Autowired
     private WarehouseService warehouseService;
+
     @GetMapping("/tree")
-    @ApiOperation("浠撳簱-鏌ヨ鏍�")
+    @Operation(summary = "浠撳簱-鏌ヨ鏍�")
     @Log(title = "浠撳簱-鏌ヨ鏍�", businessType = BusinessType.OTHER)
     public AjaxResult listTree() {
         return AjaxResult.success(warehouseService.findListTree());
     }
+
     @GetMapping("/list")
-    @ApiOperation("浠撳簱-鏌ヨ")
+    @Operation(summary = "浠撳簱-鏌ヨ")
     @Log(title = "浠撳簱-鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult list(Warehouse warehouse) {
         return AjaxResult.success(warehouseService.findList(warehouse));
     }
+
     @PostMapping("/add")
-    @ApiOperation("浠撳簱-娣诲姞")
+    @Operation(summary = "浠撳簱-娣诲姞")
     @Log(title = "浠撳簱-娣诲姞", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody Warehouse warehouse) {
         return AjaxResult.success(warehouseService.save(warehouse));
     }
 
     @PutMapping("/update")
-    @ApiOperation("浠撳簱-鏇存柊")
+    @Operation(summary = "浠撳簱-鏇存柊")
     @Log(title = "浠撳簱-鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody Warehouse warehouse) {
         return AjaxResult.success(warehouseService.updateById(warehouse));
     }
 
     @DeleteMapping("/delete")
-    @ApiOperation("浠撳簱-鍒犻櫎")
+    @Operation(summary = "浠撳簱-鍒犻櫎")
     @Log(title = "浠撳簱-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
-        if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
+        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
         return AjaxResult.success(warehouseService.deleteByIds(ids));
     }
 }
diff --git a/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesController.java b/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesController.java
index bed5510..5aebb76 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesController.java
@@ -1,9 +1,6 @@
 package com.ruoyi.warehouse.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
@@ -11,41 +8,41 @@
 import com.ruoyi.warehouse.dto.WarehouseGoodsShelvesDto;
 import com.ruoyi.warehouse.pojo.WarehouseGoodsShelves;
 import com.ruoyi.warehouse.service.WarehouseGoodsShelvesService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
 @RestController
-@Api(tags = "鍟嗗搧璐ф灦")
+@Tag(name = "鍟嗗搧璐ф灦")
 @RequestMapping("/warehouse/goodsShelves")
+@AllArgsConstructor
 public class WarehouseGoodsShelvesController extends BaseController {
-    @Autowired
     private WarehouseGoodsShelvesService warehouseGoodsShelvesService;
 
     @GetMapping("/listById")
-    @ApiOperation("鍟嗗搧璐ф灦-鏌ヨ")
+    @Operation(summary = "鍟嗗搧璐ф灦-鏌ヨ")
     @Log(title = "鍟嗗搧璐ф灦-鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult listById(WarehouseGoodsShelves warehouseGoodsShelves) {
         List<WarehouseGoodsShelvesDto> list = warehouseGoodsShelvesService.findList(warehouseGoodsShelves);
         return AjaxResult.success(list);
     }
     @PostMapping("/add")
-    @ApiOperation("鍟嗗搧璐ф灦-娣诲姞")
+    @Operation(summary = "鍟嗗搧璐ф灦-娣诲姞")
     @Log(title = "鍟嗗搧璐ф灦-娣诲姞", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody WarehouseGoodsShelves warehouseGoodsShelves) {
         return AjaxResult.success(warehouseGoodsShelvesService.add(warehouseGoodsShelves));
     }
     @PutMapping("/update")
-    @ApiOperation("鍟嗗搧璐ф灦-鏇存柊")
+    @Operation(summary = "鍟嗗搧璐ф灦-鏇存柊")
     @Log(title = "鍟嗗搧璐ф灦-鏇存柊", businessType = BusinessType.UPDATE)
     public AjaxResult update(@RequestBody WarehouseGoodsShelves warehouseGoodsShelves) {
         return AjaxResult.success(warehouseGoodsShelvesService.updateRowcolById(warehouseGoodsShelves));
     }
     @DeleteMapping("/delete")
-    @ApiOperation("鍟嗗搧璐ф灦-鍒犻櫎")
+    @Operation(summary = "鍟嗗搧璐ф灦-鍒犻櫎")
     @Log(title = "鍟嗗搧璐ф灦-鍒犻櫎", businessType = BusinessType.DELETE)
     public AjaxResult delete(@RequestBody List<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) return AjaxResult.error("璇蜂紶鍏ヨ鍒犻櫎鐨処D");
diff --git a/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesRowcolController.java b/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesRowcolController.java
index 36073ac..ed3ed06 100644
--- a/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesRowcolController.java
+++ b/src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesRowcolController.java
@@ -4,24 +4,27 @@
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.warehouse.pojo.WarehouseGoodsShelvesRowcol;
 import com.ruoyi.warehouse.dto.WarehouseGoodsShelvesRowcolDto;
+import com.ruoyi.warehouse.pojo.WarehouseGoodsShelvesRowcol;
 import com.ruoyi.warehouse.service.WarehouseGoodsShelvesRowcolService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
 @RestController
-@Api(tags = "鍟嗗搧璐ф灦琛屽垪")
+@Tag(name = "鍟嗗搧璐ф灦琛屽垪")
 @RequestMapping("/warehouse/goodsShelvesRowcol")
+@AllArgsConstructor
 public class WarehouseGoodsShelvesRowcolController extends BaseController {
-    @Autowired
     private WarehouseGoodsShelvesRowcolService warehouseGoodsShelvesRowcolService;
+
     @GetMapping("/list")
-    @ApiOperation("鍟嗗搧璐ф灦琛屽垪-鏌ヨ")
+    @Operation(summary = "鍟嗗搧璐ф灦琛屽垪-鏌ヨ")
     @Log(title = "鍟嗗搧璐ф灦琛屽垪-鏌ヨ", businessType = BusinessType.OTHER)
     public AjaxResult list(WarehouseGoodsShelvesRowcol warehouseGoodsShelvesRowcol) {
 
diff --git a/src/main/java/com/ruoyi/warehouse/dto/DocumentationBorrowManagementDto.java b/src/main/java/com/ruoyi/warehouse/dto/DocumentationBorrowManagementDto.java
index 8fb893a..94880a3 100644
--- a/src/main/java/com/ruoyi/warehouse/dto/DocumentationBorrowManagementDto.java
+++ b/src/main/java/com/ruoyi/warehouse/dto/DocumentationBorrowManagementDto.java
@@ -2,7 +2,7 @@
 
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import com.ruoyi.warehouse.pojo.DocumentationBorrowManagement;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 @Data
diff --git a/src/main/java/com/ruoyi/warehouse/dto/ReturnExportDto.java b/src/main/java/com/ruoyi/warehouse/dto/ReturnExportDto.java
index bb9c391..246e3ab 100644
--- a/src/main/java/com/ruoyi/warehouse/dto/ReturnExportDto.java
+++ b/src/main/java/com/ruoyi/warehouse/dto/ReturnExportDto.java
@@ -4,7 +4,7 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.time.LocalDateTime;
 
 public class ReturnExportDto {
diff --git a/src/main/java/com/ruoyi/warehouse/mapper/DocumentationBorrowManagementMapper.java b/src/main/java/com/ruoyi/warehouse/mapper/DocumentationBorrowManagementMapper.java
index 6af2ceb..803c66b 100644
--- a/src/main/java/com/ruoyi/warehouse/mapper/DocumentationBorrowManagementMapper.java
+++ b/src/main/java/com/ruoyi/warehouse/mapper/DocumentationBorrowManagementMapper.java
@@ -11,7 +11,7 @@
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/DocumentClassification.java b/src/main/java/com/ruoyi/warehouse/pojo/DocumentClassification.java
index 98855ce..bece83d 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/DocumentClassification.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/DocumentClassification.java
@@ -6,7 +6,7 @@
 import java.time.LocalDateTime;
 import java.util.Date;
 
-import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -15,7 +15,7 @@
  */
 @TableName(value ="document_classification")
 @Data
-@ApiModel(value = "鏂囨。鍒嗙被琛�")
+@Schema(name = "鏂囨。鍒嗙被琛�")
 public class DocumentClassification implements Serializable {
     /**
      *
@@ -64,4 +64,7 @@
     private Long tenantId;
 
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/Documentation.java b/src/main/java/com/ruoyi/warehouse/pojo/Documentation.java
index 0c1a612..d9e85e4 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/Documentation.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/Documentation.java
@@ -8,8 +8,7 @@
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -18,55 +17,55 @@
  */
 @TableName(value ="documentation")
 @Data
-@ApiModel(value = "鏂囨。淇℃伅琛�")
+@Schema(name = "鏂囨。淇℃伅琛�")
 public class Documentation implements Serializable {
     /**
      * 
      */
     @TableId(type = IdType.AUTO)
-    @ApiModelProperty(value = "鏂囨。ID")
+    @Schema(description = "鏂囨。ID")
     private Long id;
 
     /**
      * 绫诲埆鍚嶇Оid
      */
     @Excel(name = "绫诲埆鍚嶇Оid")
-    @ApiModelProperty(value = "绫诲埆鍚嶇Оid")
+    @Schema(description = "绫诲埆鍚嶇Оid")
     private Long documentClassificationId;
 
     /**
      * 鏂囨。鍚嶇О
      */
     @Excel(name = "鏂囨。鍚嶇О")
-    @ApiModelProperty(value = "鏂囨。鍚嶇О")
+    @Schema(description = "鏂囨。鍚嶇О")
     private String docName;
 
     /**
      * 鏂囨。缂栧彿
      */
     @Excel(name = "鏂囨。缂栧彿")
-    @ApiModelProperty(value = "鏂囨。缂栧彿")
+    @Schema(description = "鏂囨。缂栧彿")
     private String docNumber;
 
     /**
      * 骞翠唤
      */
     @Excel(name = "骞翠唤")
-    @ApiModelProperty(value = "骞翠唤")
+    @Schema(description = "骞翠唤")
     private Long year;
 
     /**
      * 璐d换浜�
      */
     @Excel(name = "璐d换浜�")
-    @ApiModelProperty(value = "璐d换浜�")
+    @Schema(description = "璐d换浜�")
     private String responsiblePerson;
 
     /**
      * 鏂囨。鏀剧疆浣嶇疆
      */
     @Excel(name = "鏂囨。鏀剧疆浣嶇疆")
-    @ApiModelProperty(value = "鏂囨。鏀剧疆浣嶇疆")
+    @Schema(description = "鏂囨。鏀剧疆浣嶇疆")
     private Long warehouseGoodsShelvesRowcolId;
 
     /**
@@ -74,7 +73,7 @@
      */
 
     @Excel(name = "鏂囨。鏃ユ湡", dateFormat = "yyyy-MM-dd", width = 30)
-    @ApiModelProperty(value = "鏂囨。鏃ユ湡")
+    @Schema(description = "鏂囨。鏃ユ湡")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime docDate;
 
@@ -82,63 +81,63 @@
      * 淇濈鏈熼檺
      */
     @Excel(name = "淇濈鏈熼檺")
-    @ApiModelProperty(value = "淇濈鏈熼檺")
+    @Schema(description = "淇濈鏈熼檺")
     private Long retentionPeriod;
 
     /**
      * 淇濆瘑绾у埆
      */
     @Excel(name = "淇濆瘑绾у埆")
-    @ApiModelProperty(value = "淇濆瘑绾у埆")
+    @Schema(description = "淇濆瘑绾у埆")
     private String securityLevel;
 
     /**
      * 浠芥暟
      */
     @Excel(name = "浠芥暟")
-    @ApiModelProperty(value = "浠芥暟")
+    @Schema(description = "浠芥暟")
     private Long copyCount;
 
     /**
      * 椤垫暟
      */
     @Excel(name = "椤垫暟")
-    @ApiModelProperty(value = "椤垫暟")
+    @Schema(description = "椤垫暟")
     private Long pageCount;
 
     /**
      * 鏂囨。绫诲埆
      */
     @Excel(name = "鏂囨。绫诲埆")
-    @ApiModelProperty(value = "鏂囨。绫诲埆")
+    @Schema(description = "鏂囨。绫诲埆")
     private String docCategory;
 
     /**
      * 鏂囨。绉嶇被
      */
     @Excel(name = "鏂囨。绉嶇被")
-    @ApiModelProperty(value = "鏂囨。绉嶇被")
+    @Schema(description = "鏂囨。绉嶇被")
     private String docType;
 
     /**
      * 绱ф�ョ▼搴�
      */
     @Excel(name = "绱ф�ョ▼搴�")
-    @ApiModelProperty(value = "绱ф�ョ▼搴�")
+    @Schema(description = "绱ф�ョ▼搴�")
     private String urgencyLevel;
 
     /**
      * 鏂囨。鐘舵��
      */
     @Excel(name = "鏂囨。鐘舵��")
-    @ApiModelProperty(value = "鏂囨。鐘舵��")
+    @Schema(description = "鏂囨。鐘舵��")
     private String docStatus;
 
     /**
      * 澶囨敞
      */
     @Excel(name = "澶囨敞")
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remark;
 
     /**
@@ -172,4 +171,7 @@
     private Long tenantId;
 
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/DocumentationBorrowManagement.java b/src/main/java/com/ruoyi/warehouse/pojo/DocumentationBorrowManagement.java
index a6c560f..8887198 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/DocumentationBorrowManagement.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/DocumentationBorrowManagement.java
@@ -10,8 +10,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -21,7 +20,7 @@
  */
 @TableName(value ="documentation_borrow_management")
 @Data
-@ApiModel(value = "鏂囨。鍊熼槄琛�")
+@Schema(name = "鏂囨。鍊熼槄琛�")
 public class DocumentationBorrowManagement extends DateQueryDto implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -34,19 +33,19 @@
     /**
      * 鏂囨。id
      */
-    @ApiModelProperty(value = "鏂囨。id")
+    @Schema(description = "鏂囨。id")
     private Long documentationId;
 
     /**
      * 鍊熼槄浜�
      */
-    @ApiModelProperty(value = "鍊熼槄浜�")
+    @Schema(description = "鍊熼槄浜�")
     @Excel(name = "鍊熼槄浜�")
     private String borrower;
     /**
      * 褰掕繕浜�
      */
-    @ApiModelProperty(value = "褰掕繕浜�")
+    @Schema(description = "褰掕繕浜�")
     @Excel(name = "褰掕繕浜�")
     private String returner;
 
@@ -54,14 +53,14 @@
      * 鍊熼槄鐩殑
      */
     @Excel(name = "鍊熼槄鐩殑")
-    @ApiModelProperty(value = "鍊熼槄鐩殑")
+    @Schema(description = "鍊熼槄鐩殑")
     private String borrowPurpose;
 
     /**
      * 鍊熼槄鏃ユ湡
      */
 
-    @ApiModelProperty(value = "鍊熼槄鏃ユ湡")
+    @Schema(description = "鍊熼槄鏃ユ湡")
     @Excel(name = "鍊熼槄鏃ユ湡", dateFormat = "yyyy-MM-dd", width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -70,7 +69,7 @@
     /**
      * 搴斿綊杩樻棩鏈�
      */
-    @ApiModelProperty(value = "搴斿綊杩樻棩鏈�")
+    @Schema(description = "搴斿綊杩樻棩鏈�")
     @Excel(name = "搴斿綊杩樻棩鏈�", dateFormat = "yyyy-MM-dd", width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private LocalDate dueReturnDate;
@@ -78,7 +77,7 @@
     /**
      * 瀹為檯褰掕繕鏃ユ湡
      */
-    @ApiModelProperty(value = "瀹為檯褰掕繕鏃ユ湡")
+    @Schema(description = "瀹為檯褰掕繕鏃ユ湡")
     @Excel(name = "瀹為檯褰掕繕鏃ユ湡", dateFormat = "yyyy-MM-dd", width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private LocalDate returnDate;
@@ -86,14 +85,14 @@
     /**
      * 鍊熼槄鐘舵��
      */
-    @ApiModelProperty(value = "鍊熼槄鐘舵��")
+    @Schema(description = "鍊熼槄鐘舵��")
     @Excel(name = "鍊熼槄鐘舵��")
     private String borrowStatus;
 
     /**
      * 澶囨敞
      */
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     @Excel(name = "澶囨敞")
     private String remark;
 
@@ -126,4 +125,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/DocumentationFile.java b/src/main/java/com/ruoyi/warehouse/pojo/DocumentationFile.java
index c24805c..72f94cc 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/DocumentationFile.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/DocumentationFile.java
@@ -1,10 +1,10 @@
 package com.ruoyi.warehouse.pojo;
 
 import com.baomidou.mybatisplus.annotation.*;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.time.LocalDateTime;
 
@@ -23,38 +23,41 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    @ApiModelProperty(value = "鏂囦欢鍚嶇О")
+    @Schema(description = "鏂囦欢鍚嶇О")
     private String name;
 
-    @ApiModelProperty(value = "鏂囦欢璺緞")
+    @Schema(description = "鏂囦欢璺緞")
     private String url;
 
-    @ApiModelProperty(value = "鏂囦欢澶у皬")
+    @Schema(description = "鏂囦欢澶у皬")
     private Long fileSize;
 
-    @ApiModelProperty(value = "鏂囨。ID")
+    @Schema(description = "鏂囨。ID")
     @NotBlank(message = "鏂囨。id涓嶈兘涓虹┖!")
     private Long documentationId;
 
-    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
-    @ApiModelProperty(value = "淇敼鏃堕棿")
+    @Schema(description = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-    @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+    @Schema(description = "鍒涘缓鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+    @Schema(description = "淇敼鐢ㄦ埛")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    @ApiModelProperty(value = "绉熸埛ID")
+    @Schema(description = "绉熸埛ID")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/DocumentationReturnManagement.java b/src/main/java/com/ruoyi/warehouse/pojo/DocumentationReturnManagement.java
index 5573923..2887cda 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/DocumentationReturnManagement.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/DocumentationReturnManagement.java
@@ -4,8 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.dto.DateQueryDto;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -19,7 +18,7 @@
  */
 @TableName(value ="documentation_return_management")
 @Data
-@ApiModel(value = "鏂囨。褰掕繕琛�")
+@Schema(name = "鏂囨。褰掕繕琛�")
 public class DocumentationReturnManagement extends DateQueryDto implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -32,7 +31,7 @@
     /**
      * 鏂囨。id
      */
-    @ApiModelProperty(value = "鏂囨。id")
+    @Schema(description = "鏂囨。id")
     private Long documentationId;
     /**
      * 鍊熼槄id
@@ -41,13 +40,13 @@
     /**
      * 鍊熼槄浜�
      */
-    @ApiModelProperty(value = "鍊熼槄浜�")
+    @Schema(description = "鍊熼槄浜�")
     @Excel(name = "鍊熼槄浜�")
     private String borrower;
     /**
      * 褰掕繕浜�
      */
-    @ApiModelProperty(value = "褰掕繕浜�")
+    @Schema(description = "褰掕繕浜�")
     @Excel(name = "褰掕繕浜�")
     private String returner;
 
@@ -55,14 +54,14 @@
      * 鍊熼槄鐩殑
      */
     @Excel(name = "鍊熼槄鐩殑")
-    @ApiModelProperty(value = "鍊熼槄鐩殑")
+    @Schema(description = "鍊熼槄鐩殑")
     private String borrowPurpose;
 
     /**
      * 鍊熼槄鏃ユ湡
      */
 
-    @ApiModelProperty(value = "鍊熼槄鏃ユ湡")
+    @Schema(description = "鍊熼槄鏃ユ湡")
     @Excel(name = "鍊熼槄鏃ユ湡", dateFormat = "yyyy-MM-dd", width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -71,7 +70,7 @@
     /**
      * 搴斿綊杩樻棩鏈�
      */
-    @ApiModelProperty(value = "搴斿綊杩樻棩鏈�")
+    @Schema(description = "搴斿綊杩樻棩鏈�")
     @Excel(name = "搴斿綊杩樻棩鏈�", dateFormat = "yyyy-MM-dd", width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private LocalDate dueReturnDate;
@@ -79,7 +78,7 @@
     /**
      * 瀹為檯褰掕繕鏃ユ湡
      */
-    @ApiModelProperty(value = "瀹為檯褰掕繕鏃ユ湡")
+    @Schema(description = "瀹為檯褰掕繕鏃ユ湡")
     @Excel(name = "瀹為檯褰掕繕鏃ユ湡", dateFormat = "yyyy-MM-dd", width = 30)
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     private LocalDate returnDate;
@@ -87,14 +86,14 @@
     /**
      * 鍊熼槄鐘舵��
      */
-    @ApiModelProperty(value = "鍊熼槄鐘舵��")
+    @Schema(description = "鍊熼槄鐘舵��")
     @Excel(name = "鍊熼槄鐘舵��")
     private String borrowStatus;
 
     /**
      * 澶囨敞
      */
-    @ApiModelProperty(value = "澶囨敞")
+    @Schema(description = "澶囨敞")
     @Excel(name = "澶囨敞")
     private String remark;
 
@@ -127,4 +126,7 @@
      */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/Warehouse.java b/src/main/java/com/ruoyi/warehouse/pojo/Warehouse.java
index a8ae602..780246a 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/Warehouse.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/Warehouse.java
@@ -6,7 +6,7 @@
 import java.time.LocalDateTime;
 import java.util.Date;
 
-import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -15,7 +15,7 @@
  */
 @TableName(value ="warehouse")
 @Data
-@ApiModel
+@Schema
 public class Warehouse implements Serializable {
     /**
      * 
@@ -59,4 +59,7 @@
     private Long tenantId;
 
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelves.java b/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelves.java
index d267986..32163ac 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelves.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelves.java
@@ -6,7 +6,7 @@
 import java.time.LocalDateTime;
 import java.util.Date;
 
-import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -15,7 +15,7 @@
  */
 @TableName(value ="warehouse_goods_shelves")
 @Data
-@ApiModel
+@Schema
 public class WarehouseGoodsShelves implements Serializable {
     /**
      * 
@@ -76,4 +76,7 @@
     private Long tenantId;
 
     private static final long serialVersionUID = 1L;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelvesRowcol.java b/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelvesRowcol.java
index 4372314..f2a0daa 100644
--- a/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelvesRowcol.java
+++ b/src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelvesRowcol.java
@@ -6,7 +6,7 @@
 import java.time.LocalDateTime;
 import java.util.Date;
 
-import io.swagger.annotations.ApiModel;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 /**
@@ -15,7 +15,7 @@
  */
 @TableName(value ="warehouse_goods_shelves_rowcol")
 @Data
-@ApiModel(value = "浠撳簱璐ф灦灞傦紝鍒楄〃")
+@Schema(name = "浠撳簱璐ф灦灞傦紝鍒楄〃")
 public class WarehouseGoodsShelvesRowcol implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -76,4 +76,7 @@
      */
     private String remark;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/warehouse/service/DocumentationBorrowManagementService.java b/src/main/java/com/ruoyi/warehouse/service/DocumentationBorrowManagementService.java
index 3f76061..1ba6278 100644
--- a/src/main/java/com/ruoyi/warehouse/service/DocumentationBorrowManagementService.java
+++ b/src/main/java/com/ruoyi/warehouse/service/DocumentationBorrowManagementService.java
@@ -7,7 +7,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.warehouse.pojo.DocumentationReturnManagement;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
diff --git a/src/main/java/com/ruoyi/warehouse/service/DocumentationService.java b/src/main/java/com/ruoyi/warehouse/service/DocumentationService.java
index 32910ce..8efa2b8 100644
--- a/src/main/java/com/ruoyi/warehouse/service/DocumentationService.java
+++ b/src/main/java/com/ruoyi/warehouse/service/DocumentationService.java
@@ -6,7 +6,7 @@
 import com.ruoyi.warehouse.pojo.Documentation;
 import com.baomidou.mybatisplus.extension.service.IService;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 
diff --git a/src/main/java/com/ruoyi/warehouse/service/impl/DocumentClassificationServiceImpl.java b/src/main/java/com/ruoyi/warehouse/service/impl/DocumentClassificationServiceImpl.java
index 54c642e..986e277 100644
--- a/src/main/java/com/ruoyi/warehouse/service/impl/DocumentClassificationServiceImpl.java
+++ b/src/main/java/com/ruoyi/warehouse/service/impl/DocumentClassificationServiceImpl.java
@@ -3,23 +3,18 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.basic.dto.ProductTreeDto;
-import com.ruoyi.basic.pojo.Product;
 import com.ruoyi.common.utils.bean.BeanUtils;
-import com.ruoyi.warehouse.dto.DocumentClassificationDto;
 import com.ruoyi.warehouse.dto.DocumentClassificationTreeDto;
 import com.ruoyi.warehouse.dto.DocumentationDto;
+import com.ruoyi.warehouse.mapper.DocumentClassificationMapper;
 import com.ruoyi.warehouse.mapper.DocumentationMapper;
 import com.ruoyi.warehouse.pojo.DocumentClassification;
-import com.ruoyi.warehouse.pojo.Documentation;
 import com.ruoyi.warehouse.service.DocumentClassificationService;
-import com.ruoyi.warehouse.mapper.DocumentClassificationMapper;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 
 /**
 * @author 86151
@@ -27,12 +22,12 @@
 * @createDate 2025-08-15 10:44:23
 */
 @Service
-public class DocumentClassificationServiceImpl extends ServiceImpl<DocumentClassificationMapper, DocumentClassification>
-    implements DocumentClassificationService{
-    @Autowired
-    private DocumentationMapper documentationMapper;
-    @Autowired
-    private DocumentClassificationMapper documentClassificationMapper;
+@RequiredArgsConstructor
+public class DocumentClassificationServiceImpl extends ServiceImpl<DocumentClassificationMapper, DocumentClassification> implements DocumentClassificationService{
+
+    private final DocumentationMapper documentationMapper;
+    private final DocumentClassificationMapper documentClassificationMapper;
+
     @Override
     public boolean deleteByIds(List<Long> ids) {
         List<DocumentClassification> list = documentClassificationMapper.selectList(new LambdaQueryWrapper<DocumentClassification>().in(DocumentClassification::getId, ids));
diff --git a/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationBorrowManagementServiceImpl.java b/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationBorrowManagementServiceImpl.java
index 4ddf5a2..73e9ab2 100644
--- a/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationBorrowManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationBorrowManagementServiceImpl.java
@@ -8,39 +8,36 @@
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.warehouse.dto.DocumentationBorrowManagementDto;
 import com.ruoyi.warehouse.dto.ReturnExportDto;
+import com.ruoyi.warehouse.mapper.DocumentationBorrowManagementMapper;
 import com.ruoyi.warehouse.mapper.DocumentationReturnManagementMapper;
 import com.ruoyi.warehouse.pojo.Documentation;
 import com.ruoyi.warehouse.pojo.DocumentationBorrowManagement;
 import com.ruoyi.warehouse.pojo.DocumentationReturnManagement;
 import com.ruoyi.warehouse.service.DocumentationBorrowManagementService;
-import com.ruoyi.warehouse.mapper.DocumentationBorrowManagementMapper;
 import com.ruoyi.warehouse.service.DocumentationService;
-import org.springframework.beans.factory.annotation.Autowired;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.servlet.http.HttpServletResponse;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
-* @author 86151
-* @description 閽堝琛ㄣ�恉ocumentation_borrow_management(鏂囨。鍊熼槄-褰掕繕琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
-* @createDate 2025-08-14 15:55:45
-*/
+ * @author 86151
+ * @description 閽堝琛ㄣ�恉ocumentation_borrow_management(鏂囨。鍊熼槄-褰掕繕琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+ * @createDate 2025-08-14 15:55:45
+ */
 @Service
 @Transactional(rollbackFor = Exception.class)
+@RequiredArgsConstructor
 public class DocumentationBorrowManagementServiceImpl extends ServiceImpl<DocumentationBorrowManagementMapper, DocumentationBorrowManagement>
-    implements DocumentationBorrowManagementService{
-    @Autowired
-    private DocumentationBorrowManagementMapper documentationBorrowManagementMapper;
-    @Autowired
-    private DocumentationReturnManagementMapper documentationReturnManagementMapper;
-    @Autowired
-    private DocumentationService documentationService;
-    @Override
+        implements DocumentationBorrowManagementService {
+
+    private final DocumentationBorrowManagementMapper documentationBorrowManagementMapper;
+    private final DocumentationReturnManagementMapper documentationReturnManagementMapper;
+    private final DocumentationService documentationService;
+
     public IPage<DocumentationBorrowManagement> listPage(Page page, DocumentationBorrowManagement documentationBorrowManagement) {
         IPage<DocumentationBorrowManagement> listPage = documentationBorrowManagementMapper.listPage(page, documentationBorrowManagement);
         return listPage;
@@ -56,6 +53,7 @@
         documentationService.updateById(documentation);
         return true;
     }
+
     @Override
     public boolean reventdbm(DocumentationReturnManagement documentationReturnManagement) {
         // 鏇存柊鍊熼槄璁板綍鐘舵�佷负褰掕繕
@@ -137,7 +135,7 @@
         List<DocumentationBorrowManagementDto> list = documentationBorrowManagementMapper.list(new LambdaQueryWrapper<DocumentationBorrowManagementDto>()
                 .eq(DocumentationBorrowManagementDto::getDocumentationId, id)
                 .eq(DocumentationBorrowManagementDto::getBorrowStatus, "鍊熼槄"));
-        if (list.isEmpty()){
+        if (list.isEmpty()) {
             throw new RuntimeException("鏂囨。鏈鍊熼槄");
         }
         return list;
@@ -150,15 +148,13 @@
             Documentation documentation = documentationService.getById(documentationBorrowManagement.getDocumentationId());
             documentation.setDocStatus("姝e父");
             boolean b = documentationService.updateById(documentation);
-            if (!b){
+            if (!b) {
                 throw new RuntimeException("鏇存柊鏂囨。鐘舵�佸け璐�");
             }
         }
         documentationBorrowManagementMapper.deleteBatchIds(ids);
         return true;
     }
-
-
 
 
 }
diff --git a/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationServiceImpl.java b/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationServiceImpl.java
index 5a7cf30..cf3b910 100644
--- a/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationServiceImpl.java
+++ b/src/main/java/com/ruoyi/warehouse/service/impl/DocumentationServiceImpl.java
@@ -6,35 +6,34 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.warehouse.dto.DocumentationDto;
-import com.ruoyi.warehouse.pojo.Documentation;
-import com.ruoyi.warehouse.pojo.DocumentationBorrowManagement;
-import com.ruoyi.warehouse.service.DocumentationService;
 import com.ruoyi.warehouse.mapper.DocumentationMapper;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.warehouse.pojo.Documentation;
+import com.ruoyi.warehouse.service.DocumentationService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
-import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
-* @author 86151
-* @description 閽堝琛ㄣ�恉ocumentation(鏂囨。淇℃伅琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
-* @createDate 2025-08-14 14:05:49
-*/
+ * @author 86151
+ * @description 閽堝琛ㄣ�恉ocumentation(鏂囨。淇℃伅琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+ * @createDate 2025-08-14 14:05:49
+ */
 @Service
-public class DocumentationServiceImpl extends ServiceImpl<DocumentationMapper, Documentation>
-    implements DocumentationService{
-    @Autowired
-    private DocumentationMapper documentationMapper;
+@RequiredArgsConstructor
+public class DocumentationServiceImpl extends ServiceImpl<DocumentationMapper, Documentation> implements DocumentationService {
+    private final DocumentationMapper documentationMapper;
+
     @Override
     public IPage<DocumentationDto> listPage(Page page, Documentation documentation) {
         return documentationMapper.listPage(page, documentation);
     }
 
     @Override
-    public void export(HttpServletResponse response,Documentation documentation) {
+    public void export(HttpServletResponse response, Documentation documentation) {
         IPage<DocumentationDto> list = documentationMapper.listPage(null, documentation);
         ExcelUtil<DocumentationDto> util = new ExcelUtil<>(DocumentationDto.class);
         util.exportExcel(response, list.getRecords(), "鏂囨。淇℃伅琛�");
@@ -52,8 +51,10 @@
         }
         return true;
     }
+
     /**
      * 鍒楄〃鎵�鏈夋枃妗�
+     *
      * @return
      */
     @Override
@@ -61,48 +62,60 @@
         List<DocumentationDto> list = documentationMapper.list().stream().filter(documentationDto -> "姝e父".equals(documentationDto.getDocStatus())).collect(Collectors.toList());
         return list;
     }
+
     /**
      * 鑾峰彇鏂囨。鎬绘暟
+     *
      * @return
      */
     @Override
     public Integer getTotalDocsCount() {
         return documentationMapper.countTotalDocs();
     }
+
     /**
      * 鑾峰彇鏂囨。鍒嗙被鎬绘暟
+     *
      * @return
      */
     @Override
     public Integer getCategoryNumCount() {
         return documentationMapper.countCategoryNum();
     }
+
     /**
      * 鑾峰彇宸插�熷嚭鏂囨。鎬绘暟
+     *
      * @return
      */
     @Override
     public Integer getBorrowedDocsCount() {
         return documentationMapper.countBorrowedDocs();
     }
+
     /**
      * 鑾峰彇姣忔湀鏂板鏂囨。鎬绘暟
+     *
      * @return
      */
     @Override
     public Integer getMonthlyAddedDocsCount() {
         return documentationMapper.countMonthlyAddedDocs();
     }
+
     /**
      * 鑾峰彇鏂囨。鍒嗙被鍒嗗竷
+     *
      * @return
      */
     @Override
     public List<Map<String, Object>> getCategoryDistribution() {
         return documentationMapper.countCategoryDistribution();
     }
+
     /**
      * 鑾峰彇鏂囨。鐘舵�佸垎甯�
+     *
      * @return
      */
     @Override
diff --git a/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesRowcolServiceImpl.java b/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesRowcolServiceImpl.java
index 7715520..29135c0 100644
--- a/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesRowcolServiceImpl.java
+++ b/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesRowcolServiceImpl.java
@@ -4,33 +4,30 @@
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.warehouse.dto.WarehouseGoodsShelvesRowcolDto;
 import com.ruoyi.warehouse.mapper.DocumentationMapper;
 import com.ruoyi.warehouse.mapper.WarehouseGoodsShelvesRowcolMapper;
 import com.ruoyi.warehouse.pojo.Documentation;
 import com.ruoyi.warehouse.pojo.WarehouseGoodsShelvesRowcol;
-import com.ruoyi.warehouse.dto.WarehouseGoodsShelvesRowcolDto;
 import com.ruoyi.warehouse.service.WarehouseGoodsShelvesRowcolService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.Arrays;
 import java.util.List;
 
 
 /**
-* @author 86151
-* @description 閽堝琛ㄣ�恮arehouse_goods_shelves_rowcol(浠撳簱璐ф灦灞傦紝鍒楄〃)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
-* @createDate 2025-08-13 11:49:02
-*/
+ * @author 86151
+ * @description 閽堝琛ㄣ�恮arehouse_goods_shelves_rowcol(浠撳簱璐ф灦灞傦紝鍒楄〃)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+ * @createDate 2025-08-13 11:49:02
+ */
 @Service
 @Slf4j
-public class WarehouseGoodsShelvesRowcolServiceImpl extends ServiceImpl<WarehouseGoodsShelvesRowcolMapper, WarehouseGoodsShelvesRowcol>
-    implements WarehouseGoodsShelvesRowcolService {
-    @Autowired
-    private WarehouseGoodsShelvesRowcolMapper warehouseGoodsShelvesRowcolMapper;
-    @Autowired
-    private DocumentationMapper documentationMapper;
+@RequiredArgsConstructor
+public class WarehouseGoodsShelvesRowcolServiceImpl extends ServiceImpl<WarehouseGoodsShelvesRowcolMapper, WarehouseGoodsShelvesRowcol> implements WarehouseGoodsShelvesRowcolService {
+    private final WarehouseGoodsShelvesRowcolMapper warehouseGoodsShelvesRowcolMapper;
+    private final DocumentationMapper documentationMapper;
 
     @Override
     public List<WarehouseGoodsShelvesRowcolDto> getList(WarehouseGoodsShelvesRowcol warehouseGoodsShelvesRowcol) {
@@ -43,6 +40,7 @@
         }
         return list;
     }
+
     @Override
     public boolean deleteByIds(List<Long> ids) {
         // 3. 妫�鏌ユ槸鍚︽湁鍟嗗搧
@@ -53,7 +51,6 @@
         warehouseGoodsShelvesRowcolMapper.deleteBatchIds(ids);
         return true;
     }
-
 
 
 }
diff --git a/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesServiceImpl.java b/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesServiceImpl.java
index 3d33d5c..4fc62fc 100644
--- a/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesServiceImpl.java
+++ b/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesServiceImpl.java
@@ -1,32 +1,26 @@
 package com.ruoyi.warehouse.service.impl;
 
 
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.warehouse.dto.WarehouseGoodsShelvesDto;
 import com.ruoyi.warehouse.mapper.DocumentationMapper;
 import com.ruoyi.warehouse.mapper.WarehouseGoodsShelvesMapper;
 import com.ruoyi.warehouse.mapper.WarehouseGoodsShelvesRowcolMapper;
 import com.ruoyi.warehouse.pojo.Documentation;
+import com.ruoyi.warehouse.pojo.WarehouseGoodsShelves;
 import com.ruoyi.warehouse.pojo.WarehouseGoodsShelvesRowcol;
 import com.ruoyi.warehouse.service.DocumentationService;
 import com.ruoyi.warehouse.service.WarehouseGoodsShelvesRowcolService;
 import com.ruoyi.warehouse.service.WarehouseGoodsShelvesService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import com.ruoyi.warehouse.pojo.WarehouseGoodsShelves;
-
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -38,18 +32,12 @@
 @Service
 @Slf4j
 @Transactional(rollbackFor = Exception.class)
-public class WarehouseGoodsShelvesServiceImpl extends ServiceImpl<WarehouseGoodsShelvesMapper, WarehouseGoodsShelves>
-    implements WarehouseGoodsShelvesService {
-    @Autowired
-    private WarehouseGoodsShelvesRowcolService warehouseGoodsShelvesRowcolService;
-    @Autowired
-    private WarehouseGoodsShelvesRowcolMapper warehouseGoodsShelvesRowcolMapper;
-    @Autowired
-    private WarehouseGoodsShelvesMapper warehouseGoodsShelvesMapper;
-    @Autowired
-    private DocumentationService documentationService;
-    @Autowired
-    private DocumentationMapper documentationMapper;
+@RequiredArgsConstructor
+public class WarehouseGoodsShelvesServiceImpl extends ServiceImpl<WarehouseGoodsShelvesMapper, WarehouseGoodsShelves> implements WarehouseGoodsShelvesService {
+
+    private final WarehouseGoodsShelvesRowcolService warehouseGoodsShelvesRowcolService;
+    private final WarehouseGoodsShelvesMapper warehouseGoodsShelvesMapper;
+    private final DocumentationMapper documentationMapper;
 
     @Override
     public boolean add(WarehouseGoodsShelves warehouseGoodsShelves) {
diff --git a/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseServiceImpl.java b/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseServiceImpl.java
index 74276a7..fb8afc6 100644
--- a/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseServiceImpl.java
+++ b/src/main/java/com/ruoyi/warehouse/service/impl/WarehouseServiceImpl.java
@@ -2,14 +2,7 @@
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-
-import com.ruoyi.framework.web.domain.AjaxResult;
-import com.ruoyi.warehouse.dto.WarehouseDto;
-import com.ruoyi.warehouse.dto.WarehouseGoodsShelvesDto;
 import com.ruoyi.warehouse.dto.WarehouseTreeDto;
 import com.ruoyi.warehouse.mapper.WarehouseGoodsShelvesMapper;
 import com.ruoyi.warehouse.mapper.WarehouseGoodsShelvesRowcolMapper;
@@ -19,12 +12,10 @@
 import com.ruoyi.warehouse.pojo.WarehouseGoodsShelvesRowcol;
 import com.ruoyi.warehouse.service.WarehouseGoodsShelvesService;
 import com.ruoyi.warehouse.service.WarehouseService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
-import java.sql.Array;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -38,16 +29,12 @@
 */
 @Service
 @Slf4j
-public class WarehouseServiceImpl extends ServiceImpl<WarehouseMapper, Warehouse>
-    implements WarehouseService {
-    @Autowired
-    private WarehouseMapper warehouseMapper;
-    @Autowired
-    private WarehouseGoodsShelvesService warehouseGoodsShelvesService;
-    @Autowired
-    private WarehouseGoodsShelvesMapper warehouseGoodsShelvesMapper;
-    @Autowired
-    private WarehouseGoodsShelvesRowcolMapper warehouseGoodsShelvesRowcolMapper;
+@RequiredArgsConstructor
+public class WarehouseServiceImpl extends ServiceImpl<WarehouseMapper, Warehouse> implements WarehouseService {
+    private final WarehouseMapper warehouseMapper;
+    private final WarehouseGoodsShelvesService warehouseGoodsShelvesService;
+    private final WarehouseGoodsShelvesMapper warehouseGoodsShelvesMapper;
+    private final WarehouseGoodsShelvesRowcolMapper warehouseGoodsShelvesRowcolMapper;
 
     @Override
     public boolean deleteByIds(List<Long> ids) {
diff --git a/src/main/java/com/ruoyi/waterrecord/controller/WaterRecordController.java b/src/main/java/com/ruoyi/waterrecord/controller/WaterRecordController.java
index a963aa1..be3933b 100644
--- a/src/main/java/com/ruoyi/waterrecord/controller/WaterRecordController.java
+++ b/src/main/java/com/ruoyi/waterrecord/controller/WaterRecordController.java
@@ -9,15 +9,16 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.waterrecord.pojo.WaterRecord;
 import com.ruoyi.waterrecord.service.WaterRecordService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.AllArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -25,11 +26,11 @@
  * @date : 2025/8/11 10:08
  */
 @RestController
-@Api(tags = "鐢ㄦ按绠$悊")
+@Tag(name = "鐢ㄦ按绠$悊")
 @RequestMapping("/waterRecord")
+@AllArgsConstructor
 public class WaterRecordController extends BaseController {
 
-    @Autowired
     private WaterRecordService waterRecordService;
 
     @GetMapping("/listPage")
@@ -69,7 +70,7 @@
      */
     @Log(title = "瀵煎叆鐢ㄦ按绠$悊", businessType = BusinessType.IMPORT)
     @PostMapping("/importData")
-    @ApiOperation("瀵煎叆鐢ㄦ按绠$悊")
+    @Operation(summary = "瀵煎叆鐢ㄦ按绠$悊")
     public AjaxResult importData(MultipartFile file) throws Exception {
         return waterRecordService.importData(file);
     }
@@ -79,7 +80,7 @@
      */
     @Log(title = "瀵煎嚭鐢ㄦ按绠$悊", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    @ApiOperation("瀵煎嚭鐢ㄦ按绠$悊")
+    @Operation(summary = "瀵煎嚭鐢ㄦ按绠$悊")
     public void export(HttpServletResponse response) {
         Page page = new Page(-1,-1);
         WaterRecord waterRecord = new WaterRecord();
diff --git a/src/main/java/com/ruoyi/waterrecord/pojo/WaterRecord.java b/src/main/java/com/ruoyi/waterrecord/pojo/WaterRecord.java
index e2c6e9b..a6e63e0 100644
--- a/src/main/java/com/ruoyi/waterrecord/pojo/WaterRecord.java
+++ b/src/main/java/com/ruoyi/waterrecord/pojo/WaterRecord.java
@@ -3,8 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.framework.aspectj.lang.annotation.Excel;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 
@@ -18,7 +17,7 @@
  */
 @Data
 @TableName("water_record")
-@ApiModel
+@Schema
 public class WaterRecord {
 
 
@@ -30,21 +29,21 @@
     /**
      * 瑙勬牸鍨嬪彿
      */
-    @ApiModelProperty("瑙勬牸鍨嬪彿")
+    @Schema(description = "瑙勬牸鍨嬪彿")
     @Excel(name = "瑙勬牸鍨嬪彿")
     private String deviceModel;
 
     /**
      * 鐢ㄦ按绫诲瀷
      */
-    @ApiModelProperty("鐢ㄦ按绫诲瀷")
+    @Schema(description = "鐢ㄦ按绫诲瀷")
     @Excel(name = "鐢ㄦ按绫诲瀷", readConverterExp = "industrial=宸ヤ笟鐢ㄦ按,domestic=鐢熸椿鐢ㄦ按,fire=娑堥槻鐢ㄦ按,greening=缁垮寲鐢ㄦ按")
     private String type;
 
     /**
      * 璁惧鍚嶇О
      */
-    @ApiModelProperty("璁惧鍚嶇О")
+    @Schema(description = "璁惧鍚嶇О")
     @Excel(name = "璁惧鍚嶇О")
     @TableField(exist = false)
     private String deviceName;
@@ -54,21 +53,21 @@
     /**
      * 棰濆畾娴侀噺
      */
-    @ApiModelProperty("棰濆畾娴侀噺")
+    @Schema(description = "棰濆畾娴侀噺")
     @Excel(name = "棰濆畾娴侀噺")
     private String ratedRate;
 
     /**
      * 瀹為檯娴侀噺
      */
-    @ApiModelProperty("瀹為檯娴侀噺")
+    @Schema(description = "瀹為檯娴侀噺")
     @Excel(name = "瀹為檯娴侀噺")
     private String actualTraffic;
 
     /**
      * 杩愯鏃堕棿
      */
-    @ApiModelProperty("杩愯鏃堕棿")
+    @Schema(description = "杩愯鏃堕棿")
     @Excel(name = "杩愯鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
@@ -78,28 +77,28 @@
     /**
      * 褰撴棩鐢ㄦ按閲�
      */
-    @ApiModelProperty("褰撴棩鐢ㄦ按閲�")
+    @Schema(description = "褰撴棩鐢ㄦ按閲�")
     @Excel(name = "褰撴棩鐢ㄦ按閲�")
     private String waterDay;
 
     /**
      * 姣忔棩闄愬埗姘撮噺
      */
-    @ApiModelProperty("姣忔棩闄愬埗姘撮噺")
+    @Schema(description = "姣忔棩闄愬埗姘撮噺")
     @Excel(name = "姣忔棩闄愬埗姘撮噺")
     private String waterDayLimit;
 
     /**
      * 姘磋垂鍗曚环
      */
-    @ApiModelProperty("姘磋垂鍗曚环")
+    @Schema(description = "姘磋垂鍗曚环")
     @Excel(name = "姘磋垂鍗曚环")
     private String waterPrice;
 
     /**
      * 澶囨敞
      */
-    @ApiModelProperty("澶囨敞")
+    @Schema(description = "澶囨敞")
     private String remarks;
 
     /**
@@ -132,4 +131,7 @@
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
 
+
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
 }
diff --git a/src/main/java/com/ruoyi/waterrecord/service/impl/WaterRecordServiceImpl.java b/src/main/java/com/ruoyi/waterrecord/service/impl/WaterRecordServiceImpl.java
index 4359ea8..09604bc 100644
--- a/src/main/java/com/ruoyi/waterrecord/service/impl/WaterRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/waterrecord/service/impl/WaterRecordServiceImpl.java
@@ -4,13 +4,12 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.equipmentenergyconsumption.pojo.EquipmentEnergyConsumption;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.waterrecord.mapper.WaterRecordMapper;
 import com.ruoyi.waterrecord.pojo.WaterRecord;
 import com.ruoyi.waterrecord.service.WaterRecordService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
@@ -23,10 +22,10 @@
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class WaterRecordServiceImpl extends ServiceImpl<WaterRecordMapper, WaterRecord> implements WaterRecordService {
 
-    @Autowired
-    private WaterRecordMapper waterRecordMapper;
+    private final WaterRecordMapper waterRecordMapper;
 
 
     @Override
diff --git a/src/main/resources/application-demo.yml b/src/main/resources/application-demo.yml
index ee53b79..096da4e 100644
--- a/src/main/resources/application-demo.yml
+++ b/src/main/resources/application-demo.yml
@@ -13,11 +13,22 @@
   addressEnabled: false
   # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
   captchaType: math
+  # 鍗忓悓瀹℃壒缂栧彿鍓嶇紑(閰嶇疆鏂囦欢鍚庣紑鍛藉悕)
+  approvalNumberPrefix: NEW
+
+  # 涓帹 Unipush 閰嶇疆
+  getui:
+    appId: PfjyAAE0FK64FaO1w2CMb1
+    appKey: zTMb831OEL6J4GK1uE3Ob4
+    masterSecret: K1GFtsv42v61tXGnF7SGE5
+    domain: https://restapi.getui.cn/v2/
+    # 绂荤嚎鎺ㄩ�佷娇鐢ㄧ殑鍖呭悕/缁勪欢鍚�
+    intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry
 
 # 寮�鍙戠幆澧冮厤缃�
 server:
   # 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
-  port: 9036
+  port: 9003
   servlet:
     # 搴旂敤鐨勮闂矾寰�
     context-path: /
@@ -45,7 +56,7 @@
   accessKey: admin
   secretKey: 12345678
   preview-expiry: 24 # 棰勮鍦板潃榛樿24灏忔椂
-  default-bucket: demo-product
+  default-bucket: jxc
 # 鐢ㄦ埛閰嶇疆
 user:
   password:
@@ -62,9 +73,9 @@
     druid:
       # 涓诲簱鏁版嵁婧�
       master:
-        url: jdbc:mysql://172.17.0.1:3306/product-inventory-management-demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        url: jdbc:mysql://172.17.0.1:9002/product-inventory-management-sdjc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
         username: root
-        password: xd@123456..
+        password: sdjc@123456..
       # 浠庡簱鏁版嵁婧�
       slave:
         # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
@@ -132,40 +143,69 @@
       # 鐑儴缃插紑鍏�
       enabled: false
   # redis 閰嶇疆
-  redis:
-    # 鍦板潃
-#    host: 127.0.0.1
-    host: 172.17.0.1
-    # 绔彛锛岄粯璁や负6379
-    port: 6379
-    # 鏁版嵁搴撶储寮�
-    database: 0
-    # 瀵嗙爜
-#    password: root2022!
-    password:
+  data:
+    mongodb:
+      uri: mongodb://114.132.189.42:9028/chat_memory_db
+    # redis 閰嶇疆
+    redis:
+      # 鍦板潃
+      #      host: 127.0.0.1
+      host: 172.17.0.1
+      # 绔彛锛岄粯璁や负6379
+      port: 6379
+      # 鏁版嵁搴撶储寮�
+      database: 0
+      # 瀵嗙爜
+      #    password: root2022!
+      password:
 
-    # 杩炴帴瓒呮椂鏃堕棿
-    timeout: 10s
-    lettuce:
-      pool:
-        # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
-        min-idle: 0
-        # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
-        max-idle: 8
-        # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
-        max-active: 8
-        # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
-        max-wait: -1ms
+      # 杩炴帴瓒呮椂鏃堕棿
+      timeout: 10s
+      lettuce:
+        pool:
+          # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+          min-idle: 0
+          # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+          max-idle: 8
+          # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+          max-active: 8
+          # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+          max-wait: -1ms
 
+  # Quartz瀹氭椂浠诲姟閰嶇疆锛堟柊澧為儴鍒嗭級
+  quartz:
+    job-store-type: jdbc  # 浣跨敤鏁版嵁搴撳瓨鍌�
+    jdbc:
+      initialize-schema: never  # 棣栨杩愯鏃惰嚜鍔ㄥ垱寤鸿〃缁撴瀯锛屾垚鍔熷悗鏀逛负never
+      schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql  # MySQL琛ㄧ粨鏋勮剼鏈�
+    properties:
+      org:
+        quartz:
+          scheduler:
+            instanceName: RuoYiScheduler
+            instanceId: AUTO
+          jobStore:
+            class: org.quartz.impl.jdbcjobstore.JobStoreTX
+            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # MySQL閫傞厤
+            tablePrefix: qrtz_  # 琛ㄥ悕鍓嶇紑锛屼笌鑴氭湰涓�鑷�
+            isClustered: false  # 鍗曡妭鐐规ā寮忥紙闆嗙兢闇�鏀逛负true锛�
+            clusterCheckinInterval: 10000
+            txIsolationLevelSerializable: true
+          threadPool:
+            class: org.quartz.simpl.SimpleThreadPool
+            threadCount: 10  # 绾跨▼姹犲ぇ灏�
+            threadPriority: 5
+            makeThreadsDaemons: true
+          updateCheck: false  # 鍏抽棴鐗堟湰妫�鏌�
 # token閰嶇疆
 token:
   # 浠ょ墝鑷畾涔夋爣璇�
   header: Authorization
   # 浠ょ墝瀵嗛挜
-  secret: abcdefghijklmnopqrstuvwxyz
+  secret: xpAVjhCjQDaDB7mjPAzMDSbQWXNu2zYkTdDNUsPMS5Xx8QMmQVYN7n74eZrYJxDJ
   # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
   expireTime: 450
-  
+
 # MyBatis Plus閰嶇疆
 mybatis-plus:
   # 鎼滅储鎸囧畾鍖呭埆鍚�   鏍规嵁鑷繁鐨勯」鐩潵
@@ -178,7 +218,7 @@
     enable-sql-runner: true
     db-config:
       id-type: auto
-  
+
 # PageHelper鍒嗛〉鎻掍欢
 pagehelper:
   helperDialect: mysql
@@ -200,7 +240,7 @@
   excludes: /system/notice
   # 鍖归厤閾炬帴
   urlPatterns: /system/*,/monitor/*,/tool/*
-  
+
 # 浠g爜鐢熸垚
 gen:
   # 浣滆��
@@ -214,6 +254,15 @@
   # 鏄惁鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦帮紙鑷畾涔夎矾寰勶級锛岄粯璁や笉鍏佽
   allowOverwrite: false
 
+# 鏂囦欢涓婁紶閰嶇疆
 file:
-  temp-dir: /javaWork/product-inventory-management/file/temp/uploads
-  upload-dir: /javaWork/product-inventory-management/file/prod/uploads
\ No newline at end of file
+  temp-dir: /javaWork/product-inventory-management/file/temp/uploads   # 涓存椂鐩綍
+  upload-dir: /javaWork/product-inventory-management/file/prod/uploads # 姝e紡鐩綍
+  path: /javaWork/product-inventory-management/file # 涓婁紶鐩綍
+  urlPrefix: /common # 閾炬帴鍓嶇紑
+  domain: http://36.138.236.153:9001 # 鍩熷悕鍓嶇紑
+  expired: 120 # 杩囨湡鏃堕棿(鍗曚綅:鍒嗛挓)
+  useLimit: 10 # 浣跨敤娆℃暟
+  compress: true # 鏄惁鍘嬬缉
+  needCompressSize: 10MB # 鍘嬬缉闃堝��
+  compressQuality: 0.5 # 鍘嬬缉璐ㄩ噺(0.0-1.0)
diff --git a/src/main/resources/application-dev-pro.yml b/src/main/resources/application-dev-pro.yml
new file mode 100644
index 0000000..abb1950
--- /dev/null
+++ b/src/main/resources/application-dev-pro.yml
@@ -0,0 +1,266 @@
+# 椤圭洰鐩稿叧閰嶇疆
+ruoyi:
+  # 鍚嶇О
+  name: RuoYi
+  # 鐗堟湰
+  version: 3.8.9
+  # 鐗堟潈骞翠唤
+  copyrightYear: 2025
+  # 鏂囦欢璺緞 绀轰緥锛� Windows閰嶇疆D:/ruoyi/uploadPath锛孡inux閰嶇疆 /home/ruoyi/uploadPath锛�
+  profile: D:/ruoyi/uploadPath
+
+  # 鑾峰彇ip鍦板潃寮�鍏�
+  addressEnabled: false
+  # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
+  captchaType: math
+  # 鍗忓悓瀹℃壒缂栧彿鍓嶇紑(閰嶇疆鏂囦欢鍚庣紑鍛藉悕)
+  approvalNumberPrefix: DEV
+
+  # 涓帹 Unipush 閰嶇疆
+  getui:
+    appId: PfjyAAE0FK64FaO1w2CMb1
+    appKey: zTMb831OEL6J4GK1uE3Ob4
+    masterSecret: K1GFtsv42v61tXGnF7SGE5
+    domain: https://restapi.getui.cn/v2/
+    # 绂荤嚎鎺ㄩ�佷娇鐢ㄧ殑鍖呭悕/缁勪欢鍚�
+    intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry
+
+# 寮�鍙戠幆澧冮厤缃�
+server:
+  # 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
+  port: 7003
+  servlet:
+    # 搴旂敤鐨勮闂矾寰�
+    context-path: /
+  tomcat:
+    # tomcat鐨刄RI缂栫爜
+    uri-encoding: UTF-8
+    # 杩炴帴鏁版弧鍚庣殑鎺掗槦鏁帮紝榛樿涓�100
+    accept-count: 1000
+    max-swallow-size: -1          # -1 琛ㄧず涓嶉檺鍒�
+    max-http-form-post-size: -1   # POST 璇锋眰浣撲笉闄愬埗
+    connection-timeout: 60000     # 杩炴帴瓒呮椂鏃堕棿(姣)
+    threads:
+      # tomcat鏈�澶х嚎绋嬫暟锛岄粯璁や负200
+      max: 800
+      # Tomcat鍚姩鍒濆鍖栫殑绾跨▼鏁帮紝榛樿鍊�10
+      min-spare: 100
+
+# 鏃ュ織閰嶇疆
+logging:
+  level:
+    org.quartz: DEBUG
+    com.ruoyi: warn
+    org.springframework: warn
+
+# 鐢ㄦ埛閰嶇疆
+user:
+  password:
+    # 瀵嗙爜鏈�澶ч敊璇鏁�
+    maxRetryCount: 5
+    # 瀵嗙爜閿佸畾鏃堕棿锛堥粯璁�10鍒嗛挓锛�
+    lockTime: 10
+
+# Spring閰嶇疆
+spring:
+  main:
+    allow-circular-references: true # 鍏佽寰幆渚濊禆
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 涓诲簱鏁版嵁婧�
+      master:
+        url: jdbc:mysql://localhost:3306/product-inventory-management-new-pro?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        username: root
+        password: 123456
+      # 浠庡簱鏁版嵁婧�
+      slave:
+        # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
+        enabled: false
+        url:
+        username:
+        password:
+      # 鍒濆杩炴帴鏁�
+      initialSize: 5
+      # 鏈�灏忚繛鎺ユ睜鏁伴噺
+      minIdle: 10
+      # 鏈�澶ц繛鎺ユ睜鏁伴噺
+      maxActive: 20
+      # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
+      maxWait: 60000
+      # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
+      connectTimeout: 30000
+      # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
+      socketTimeout: 60000
+      # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
+      timeBetweenEvictionRunsMillis: 60000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      minEvictableIdleTimeMillis: 300000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      maxEvictableIdleTimeMillis: 900000
+      # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 璁剧疆鐧藉悕鍗曪紝涓嶅~鍒欏厑璁告墍鏈夎闂�
+        allow:
+        url-pattern: /druid/*
+        # 鎺у埗鍙扮鐞嗙敤鎴峰悕鍜屽瘑鐮�
+        login-username: ruoyi
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 鎱QL璁板綍
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  # 璧勬簮淇℃伅
+  messages:
+    # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
+    basename: i18n/messages
+  # 鏂囦欢涓婁紶
+  servlet:
+    multipart:
+      # 鍗曚釜鏂囦欢澶у皬
+      max-file-size: 1GB
+      # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
+      max-request-size: 2GB
+  # 鏈嶅姟妯″潡
+  devtools:
+    restart:
+      # 鐑儴缃插紑鍏�
+      enabled: false
+  # redis 閰嶇疆
+  data:
+    mongodb:
+      uri: mongodb://114.132.189.42:9028/chat_memory_db
+    # redis 閰嶇疆
+    redis:
+      # 鍦板潃
+      host: 127.0.0.1
+      #    host: 172.17.0.1
+      # 绔彛锛岄粯璁や负6379
+      port: 6379
+      # 鏁版嵁搴撶储寮�
+      database: 0
+      # 瀵嗙爜
+      #    password: root2022!
+      password:
+
+      # 杩炴帴瓒呮椂鏃堕棿
+      timeout: 10s
+      lettuce:
+        pool:
+          # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+          min-idle: 0
+          # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+          max-idle: 8
+          # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+          max-active: 8
+          # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+          max-wait: -1ms
+  # Quartz瀹氭椂浠诲姟閰嶇疆锛堟柊澧為儴鍒嗭級
+  quartz:
+    job-store-type: jdbc  # 浣跨敤鏁版嵁搴撳瓨鍌�
+    jdbc:
+      initialize-schema: never  # 棣栨杩愯鏃惰嚜鍔ㄥ垱寤鸿〃缁撴瀯锛屾垚鍔熷悗鏀逛负never
+      schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql  # MySQL琛ㄧ粨鏋勮剼鏈�
+    properties:
+      org:
+        quartz:
+          scheduler:
+            instanceName: RuoYiScheduler
+            instanceId: AUTO
+          jobStore:
+            class: org.quartz.impl.jdbcjobstore.JobStoreTX
+            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # MySQL閫傞厤
+            tablePrefix: qrtz_  # 琛ㄥ悕鍓嶇紑锛屼笌鑴氭湰涓�鑷�
+            isClustered: false  # 鍗曡妭鐐规ā寮忥紙闆嗙兢闇�鏀逛负true锛�
+            clusterCheckinInterval: 10000
+            txIsolationLevelSerializable: true
+          threadPool:
+            class: org.quartz.simpl.SimpleThreadPool
+            threadCount: 10  # 绾跨▼姹犲ぇ灏�
+            threadPriority: 5
+            makeThreadsDaemons: true
+          updateCheck: false  # 鍏抽棴鐗堟湰妫�鏌�
+
+# token閰嶇疆
+token:
+  # 浠ょ墝鑷畾涔夋爣璇�
+  header: Authorization
+  # 浠ょ墝瀵嗛挜 鏂扮増jwt瀵嗛挜闀垮害蹇呴』64浣嶄互涓�
+  secret: xpAVjhCjQDaDB7mjPAzMDSbQWXNu2zYkTdDNUsPMS5Xx8QMmQVYN7n74eZrYJxDJ
+  # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+  expireTime: 450
+
+# MyBatis Plus閰嶇疆
+mybatis-plus:
+  # 鎼滅储鎸囧畾鍖呭埆鍚�   鏍规嵁鑷繁鐨勯」鐩潵
+  typeAliasesPackage: com.ruoyi.**.pojo
+  # 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
+  configLocation: classpath:mybatis/mybatis-config.xml
+  global-config:
+    enable-sql-runner: true
+    db-config:
+      id-type: auto
+
+# PageHelper鍒嗛〉鎻掍欢
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger閰嶇疆
+swagger:
+  # 鏄惁寮�鍚痵wagger
+  enabled: true
+  # 璇锋眰鍓嶇紑
+  pathMapping: /dev-api
+
+# 闃叉XSS鏀诲嚮
+xss:
+  # 杩囨护寮�鍏�
+  enabled: true
+  # 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
+  excludes: /system/notice
+  # 鍖归厤閾炬帴
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+# 浠g爜鐢熸垚
+gen:
+  # 浣滆��
+  author: ruoyi
+  # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
+  packageName: com.ruoyi.project.system
+  # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸true
+  autoRemovePre: false
+  # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
+  tablePrefix: sys_
+  # 鏄惁鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦帮紙鑷畾涔夎矾寰勶級锛岄粯璁や笉鍏佽
+  allowOverwrite: false
+
+# 鏂囦欢涓婁紶閰嶇疆
+file:
+  temp-dir: D:/ruoyi/temp/uploads   # 涓存椂鐩綍 鍚庢湡鍒犻櫎
+  upload-dir: D:/ruoyi/prod/uploads # 姝e紡鐩綍 鍚庢湡鍒犻櫎
+  path: C:/Users/12631/Desktop/download/uploads # 涓婁紶鐩綍
+  urlPrefix: /common # 閾炬帴鍓嶇紑
+  domain: http://127.0.0.1:7003 # 鍩熷悕鍓嶇紑
+  expired: 120 # 杩囨湡鏃堕棿(鍗曚綅:鍒嗛挓)
+  useLimit: 10 # 浣跨敤娆℃暟
+  compress: true # 鏄惁鍘嬬缉
+  needCompressSize: 10MB # 鍘嬬缉闃堝��
+  compressQuality: 0.5 # 鍘嬬缉璐ㄩ噺(0.0-1.0)
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 9eff9ac..bd38c3b 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -74,9 +74,9 @@
     druid:
       # 涓诲簱鏁版嵁婧�
       master:
-        url: jdbc:mysql://1.15.17.182:9999/product-inventory-management-new?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        url: jdbc:mysql://localhost:3300/product-inventory-management-new-pro?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
         username: root
-        password: xd@123456..
+        password: root
       # 浠庡簱鏁版嵁婧�
       slave:
         # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
@@ -143,31 +143,34 @@
     restart:
       # 鐑儴缃插紑鍏�
       enabled: false
-  # redis 閰嶇疆
-  redis:
-    # 鍦板潃
-    host: 127.0.0.1
-    #    host: 172.17.0.1
-    # 绔彛锛岄粯璁や负6379
-    port: 6379
-    # 鏁版嵁搴撶储寮�
-    database: 0
-    # 瀵嗙爜
-    #    password: root2022!
-    password:
+  data:
+    mongodb:
+      uri: mongodb://114.132.189.42:9028/chat_memory_db
+    # redis 閰嶇疆
+    redis:
+      # 鍦板潃
+      host: 127.0.0.1
+      #    host: 172.17.0.1
+      # 绔彛锛岄粯璁や负6379
+      port: 6379
+      # 鏁版嵁搴撶储寮�
+      database: 0
+      # 瀵嗙爜
+      #    password: root2022!
+      password:
 
-    # 杩炴帴瓒呮椂鏃堕棿
-    timeout: 10s
-    lettuce:
-      pool:
-        # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
-        min-idle: 0
-        # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
-        max-idle: 8
-        # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
-        max-active: 8
-        # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
-        max-wait: -1ms
+      # 杩炴帴瓒呮椂鏃堕棿
+      timeout: 10s
+      lettuce:
+        pool:
+          # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+          min-idle: 0
+          # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+          max-idle: 8
+          # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+          max-active: 8
+          # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+          max-wait: -1ms
   # Quartz瀹氭椂浠诲姟閰嶇疆锛堟柊澧為儴鍒嗭級
   quartz:
     job-store-type: jdbc  # 浣跨敤鏁版嵁搴撳瓨鍌�
@@ -199,7 +202,7 @@
   # 浠ょ墝鑷畾涔夋爣璇�
   header: Authorization
   # 浠ょ墝瀵嗛挜
-  secret: abcdefghijklmnopqrstuvwxyz
+  secret: xpAVjhCjQDaDB7mjPAzMDSbQWXNu2zYkTdDNUsPMS5Xx8QMmQVYN7n74eZrYJxDJ
   # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
   expireTime: 450
 
@@ -254,3 +257,5 @@
 file:
   temp-dir: D:/ruoyi/temp/uploads   # 涓存椂鐩綍
   upload-dir: D:/ruoyi/prod/uploads # 姝e紡鐩綍
+knowledge:
+  one: D:\鏂扮枂澶х綏绱犱紒涓氫骇鍝佷綋绯昏鏄庢枃妗�.md
diff --git a/src/main/resources/application-hbtmblc.yml b/src/main/resources/application-hbtmblc.yml
new file mode 100644
index 0000000..ec44491
--- /dev/null
+++ b/src/main/resources/application-hbtmblc.yml
@@ -0,0 +1,256 @@
+# 椤圭洰鐩稿叧閰嶇疆
+ruoyi:
+  # 鍚嶇О
+  name: RuoYi
+  # 鐗堟湰
+  version: 3.8.9
+  # 鐗堟潈骞翠唤
+  copyrightYear: 2025
+  # 鏂囦欢璺緞 绀轰緥锛� Windows閰嶇疆D:/ruoyi/uploadPath锛孡inux閰嶇疆 /home/ruoyi/uploadPath锛�
+  profile: D:/ruoyi/uploadPath
+
+  # 鑾峰彇ip鍦板潃寮�鍏�
+  addressEnabled: false
+  # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
+  captchaType: math
+  # 鍗忓悓瀹℃壒缂栧彿鍓嶇紑(閰嶇疆鏂囦欢鍚庣紑鍛藉悕)
+  approvalNumberPrefix: DEV
+
+  # 涓帹 Unipush 閰嶇疆
+  getui:
+    appId: PfjyAAE0FK64FaO1w2CMb1
+    appKey: zTMb831OEL6J4GK1uE3Ob4
+    masterSecret: K1GFtsv42v61tXGnF7SGE5
+    domain: https://restapi.getui.cn/v2/
+    # 绂荤嚎鎺ㄩ�佷娇鐢ㄧ殑鍖呭悕/缁勪欢鍚�
+    intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry
+
+# 寮�鍙戠幆澧冮厤缃�
+server:
+  # 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
+  port: 7003
+  servlet:
+    # 搴旂敤鐨勮闂矾寰�
+    context-path: /
+  tomcat:
+    # tomcat鐨刄RI缂栫爜
+    uri-encoding: UTF-8
+    # 杩炴帴鏁版弧鍚庣殑鎺掗槦鏁帮紝榛樿涓�100
+    accept-count: 1000
+    threads:
+      # tomcat鏈�澶х嚎绋嬫暟锛岄粯璁や负200
+      max: 800
+      # Tomcat鍚姩鍒濆鍖栫殑绾跨▼鏁帮紝榛樿鍊�10
+      min-spare: 100
+
+# 鏃ュ織閰嶇疆
+logging:
+  level:
+    org.quartz: DEBUG
+    com.ruoyi: warn
+    org.springframework: warn
+
+minio:
+  endpoint: http://114.132.189.42/
+  port: 7019
+  secure: false
+  accessKey: admin
+  secretKey: 12345678
+  preview-expiry: 24 # 棰勮鍦板潃榛樿24灏忔椂
+  default-bucket: uploadPath
+# 鐢ㄦ埛閰嶇疆
+user:
+  password:
+    # 瀵嗙爜鏈�澶ч敊璇鏁�
+    maxRetryCount: 5
+    # 瀵嗙爜閿佸畾鏃堕棿锛堥粯璁�10鍒嗛挓锛�
+    lockTime: 10
+
+# Spring閰嶇疆
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 涓诲簱鏁版嵁婧�
+      master:
+        url: jdbc:mysql://172.17.0.1:9006/product-inventory-management-hbtmblc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        username: root
+        password: xd@123456..
+      # 浠庡簱鏁版嵁婧�
+      slave:
+        # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
+        enabled: false
+        url:
+        username:
+        password:
+      # 鍒濆杩炴帴鏁�
+      initialSize: 5
+      # 鏈�灏忚繛鎺ユ睜鏁伴噺
+      minIdle: 10
+      # 鏈�澶ц繛鎺ユ睜鏁伴噺
+      maxActive: 20
+      # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
+      maxWait: 60000
+      # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
+      connectTimeout: 30000
+      # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
+      socketTimeout: 60000
+      # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
+      timeBetweenEvictionRunsMillis: 60000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      minEvictableIdleTimeMillis: 300000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      maxEvictableIdleTimeMillis: 900000
+      # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 璁剧疆鐧藉悕鍗曪紝涓嶅~鍒欏厑璁告墍鏈夎闂�
+        allow:
+        url-pattern: /druid/*
+        # 鎺у埗鍙扮鐞嗙敤鎴峰悕鍜屽瘑鐮�
+        login-username: ruoyi
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 鎱QL璁板綍
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  # 璧勬簮淇℃伅
+  messages:
+    # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
+    basename: i18n/messages
+  # 鏂囦欢涓婁紶
+  servlet:
+    multipart:
+      # 鍗曚釜鏂囦欢澶у皬
+      max-file-size: 1GB
+      # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
+      max-request-size: 2GB
+  # 鏈嶅姟妯″潡
+  devtools:
+    restart:
+      # 鐑儴缃插紑鍏�
+      enabled: false
+  # redis 閰嶇疆
+  redis:
+    # 鍦板潃
+    #    host: 127.0.0.1
+    host: 172.17.0.1
+    # 绔彛锛岄粯璁や负6379
+    port: 6380
+    # 鏁版嵁搴撶储寮�
+    database: 8
+    # 瀵嗙爜
+    #    password: root2022!
+    password:
+
+    # 杩炴帴瓒呮椂鏃堕棿
+    timeout: 10s
+    lettuce:
+      pool:
+        # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+        min-idle: 0
+        # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+        max-idle: 8
+        # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+        max-active: 8
+        # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+        max-wait: -1ms
+  # Quartz瀹氭椂浠诲姟閰嶇疆锛堟柊澧為儴鍒嗭級
+  quartz:
+    job-store-type: jdbc  # 浣跨敤鏁版嵁搴撳瓨鍌�
+    jdbc:
+      initialize-schema: never  # 棣栨杩愯鏃惰嚜鍔ㄥ垱寤鸿〃缁撴瀯锛屾垚鍔熷悗鏀逛负never
+      schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql  # MySQL琛ㄧ粨鏋勮剼鏈�
+    properties:
+      org:
+        quartz:
+          scheduler:
+            instanceName: RuoYiScheduler
+            instanceId: AUTO
+          jobStore:
+            class: org.quartz.impl.jdbcjobstore.JobStoreTX
+            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # MySQL閫傞厤
+            tablePrefix: qrtz_  # 琛ㄥ悕鍓嶇紑锛屼笌鑴氭湰涓�鑷�
+            isClustered: false  # 鍗曡妭鐐规ā寮忥紙闆嗙兢闇�鏀逛负true锛�
+            clusterCheckinInterval: 10000
+            txIsolationLevelSerializable: true
+          threadPool:
+            class: org.quartz.simpl.SimpleThreadPool
+            threadCount: 10  # 绾跨▼姹犲ぇ灏�
+            threadPriority: 5
+            makeThreadsDaemons: true
+          updateCheck: false  # 鍏抽棴鐗堟湰妫�鏌�
+
+# token閰嶇疆
+token:
+  # 浠ょ墝鑷畾涔夋爣璇�
+  header: Authorization
+  # 浠ょ墝瀵嗛挜
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+  expireTime: 450
+
+# MyBatis Plus閰嶇疆
+mybatis-plus:
+  # 鎼滅储鎸囧畾鍖呭埆鍚�   鏍规嵁鑷繁鐨勯」鐩潵
+  typeAliasesPackage: com.ruoyi.**.pojo
+  # 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
+  configLocation: classpath:mybatis/mybatis-config.xml
+  global-config:
+    enable-sql-runner: true
+    db-config:
+      id-type: auto
+
+# PageHelper鍒嗛〉鎻掍欢
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger閰嶇疆
+swagger:
+  # 鏄惁寮�鍚痵wagger
+  enabled: true
+  # 璇锋眰鍓嶇紑
+  pathMapping: /dev-api
+
+# 闃叉XSS鏀诲嚮
+xss:
+  # 杩囨护寮�鍏�
+  enabled: true
+  # 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
+  excludes: /system/notice
+  # 鍖归厤閾炬帴
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+# 浠g爜鐢熸垚
+gen:
+  # 浣滆��
+  author: ruoyi
+  # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
+  packageName: com.ruoyi.project.system
+  # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸true
+  autoRemovePre: false
+  # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
+  tablePrefix: sys_
+  # 鏄惁鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦帮紙鑷畾涔夎矾寰勶級锛岄粯璁や笉鍏佽
+  allowOverwrite: false
+
+file:
+  temp-dir: D:/ruoyi/temp/uploads   # 涓存椂鐩綍
+  upload-dir: D:/ruoyi/prod/uploads # 姝e紡鐩綍
diff --git a/src/main/resources/application-new-pro.yml b/src/main/resources/application-new-pro.yml
new file mode 100644
index 0000000..7ff138a
--- /dev/null
+++ b/src/main/resources/application-new-pro.yml
@@ -0,0 +1,268 @@
+# 椤圭洰鐩稿叧閰嶇疆
+ruoyi:
+  # 鍚嶇О
+  name: RuoYi
+  # 鐗堟湰
+  version: 3.8.9
+  # 鐗堟潈骞翠唤
+  copyrightYear: 2025
+  # 鏂囦欢璺緞 绀轰緥锛� Windows閰嶇疆D:/ruoyi/uploadPath锛孡inux閰嶇疆 /home/ruoyi/uploadPath锛�
+  profile: /javaWork/product-inventory-management/file
+
+  # 鑾峰彇ip鍦板潃寮�鍏�
+  addressEnabled: false
+  # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
+  captchaType: math
+  # 鍗忓悓瀹℃壒缂栧彿鍓嶇紑(閰嶇疆鏂囦欢鍚庣紑鍛藉悕)
+  approvalNumberPrefix: NEW
+
+  # 涓帹 Unipush 閰嶇疆
+  getui:
+    appId: PfjyAAE0FK64FaO1w2CMb1
+    appKey: zTMb831OEL6J4GK1uE3Ob4
+    masterSecret: K1GFtsv42v61tXGnF7SGE5
+    domain: https://restapi.getui.cn/v2/
+    # 绂荤嚎鎺ㄩ�佷娇鐢ㄧ殑鍖呭悕/缁勪欢鍚�
+    intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry
+
+# 寮�鍙戠幆澧冮厤缃�
+server:
+  # 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
+  port: 9003
+  servlet:
+    # 搴旂敤鐨勮闂矾寰�
+    context-path: /
+  tomcat:
+    # tomcat鐨刄RI缂栫爜
+    uri-encoding: UTF-8
+    # 杩炴帴鏁版弧鍚庣殑鎺掗槦鏁帮紝榛樿涓�100
+    accept-count: 1000
+    threads:
+      # tomcat鏈�澶х嚎绋嬫暟锛岄粯璁や负200
+      max: 800
+      # Tomcat鍚姩鍒濆鍖栫殑绾跨▼鏁帮紝榛樿鍊�10
+      min-spare: 100
+
+# 鏃ュ織閰嶇疆
+logging:
+  level:
+    com.ruoyi: warn
+    org.springframework: warn
+
+minio:
+  endpoint: http://114.132.189.42/
+  port: 7019
+  secure: false
+  accessKey: admin
+  secretKey: 12345678
+  preview-expiry: 24 # 棰勮鍦板潃榛樿24灏忔椂
+  default-bucket: jxc
+# 鐢ㄦ埛閰嶇疆
+user:
+  password:
+    # 瀵嗙爜鏈�澶ч敊璇鏁�
+    maxRetryCount: 5
+    # 瀵嗙爜閿佸畾鏃堕棿锛堥粯璁�10鍒嗛挓锛�
+    lockTime: 10
+
+# Spring閰嶇疆
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 涓诲簱鏁版嵁婧�
+      master:
+        url: jdbc:mysql://172.17.0.1:3306/product-inventory-management-new-pro?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+        username: root
+        password: xd@123456..
+      # 浠庡簱鏁版嵁婧�
+      slave:
+        # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
+        enabled: false
+        url:
+        username:
+        password:
+      # 鍒濆杩炴帴鏁�
+      initialSize: 5
+      # 鏈�灏忚繛鎺ユ睜鏁伴噺
+      minIdle: 10
+      # 鏈�澶ц繛鎺ユ睜鏁伴噺
+      maxActive: 20
+      # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
+      maxWait: 60000
+      # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
+      connectTimeout: 30000
+      # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
+      socketTimeout: 60000
+      # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
+      timeBetweenEvictionRunsMillis: 60000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      minEvictableIdleTimeMillis: 300000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      maxEvictableIdleTimeMillis: 900000
+      # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 璁剧疆鐧藉悕鍗曪紝涓嶅~鍒欏厑璁告墍鏈夎闂�
+        allow:
+        url-pattern: /druid/*
+        # 鎺у埗鍙扮鐞嗙敤鎴峰悕鍜屽瘑鐮�
+        login-username: ruoyi
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 鎱QL璁板綍
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  # 璧勬簮淇℃伅
+  messages:
+    # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
+    basename: i18n/messages
+  # 鏂囦欢涓婁紶
+  servlet:
+    multipart:
+      # 鍗曚釜鏂囦欢澶у皬
+      max-file-size: 1GB
+      # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
+      max-request-size: 2GB
+  # 鏈嶅姟妯″潡
+  devtools:
+    restart:
+      # 鐑儴缃插紑鍏�
+      enabled: false
+  # redis 閰嶇疆
+  data:
+    mongodb:
+      uri: mongodb://114.132.189.42:9028/chat_memory_db
+    # redis 閰嶇疆
+    redis:
+      # 鍦板潃
+#      host: 127.0.0.1
+      host: 172.17.0.1
+      # 绔彛锛岄粯璁や负6379
+      port: 6379
+      # 鏁版嵁搴撶储寮�
+      database: 0
+      # 瀵嗙爜
+      #    password: root2022!
+      password:
+
+      # 杩炴帴瓒呮椂鏃堕棿
+      timeout: 10s
+      lettuce:
+        pool:
+          # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+          min-idle: 0
+          # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+          max-idle: 8
+          # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+          max-active: 8
+          # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+          max-wait: -1ms
+
+  # Quartz瀹氭椂浠诲姟閰嶇疆锛堟柊澧為儴鍒嗭級
+  quartz:
+    job-store-type: jdbc  # 浣跨敤鏁版嵁搴撳瓨鍌�
+    jdbc:
+      initialize-schema: never  # 棣栨杩愯鏃惰嚜鍔ㄥ垱寤鸿〃缁撴瀯锛屾垚鍔熷悗鏀逛负never
+      schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql  # MySQL琛ㄧ粨鏋勮剼鏈�
+    properties:
+      org:
+        quartz:
+          scheduler:
+            instanceName: RuoYiScheduler
+            instanceId: AUTO
+          jobStore:
+            class: org.quartz.impl.jdbcjobstore.JobStoreTX
+            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate  # MySQL閫傞厤
+            tablePrefix: qrtz_  # 琛ㄥ悕鍓嶇紑锛屼笌鑴氭湰涓�鑷�
+            isClustered: false  # 鍗曡妭鐐规ā寮忥紙闆嗙兢闇�鏀逛负true锛�
+            clusterCheckinInterval: 10000
+            txIsolationLevelSerializable: true
+          threadPool:
+            class: org.quartz.simpl.SimpleThreadPool
+            threadCount: 10  # 绾跨▼姹犲ぇ灏�
+            threadPriority: 5
+            makeThreadsDaemons: true
+          updateCheck: false  # 鍏抽棴鐗堟湰妫�鏌�
+# token閰嶇疆
+token:
+  # 浠ょ墝鑷畾涔夋爣璇�
+  header: Authorization
+  # 浠ょ墝瀵嗛挜
+  secret: xpAVjhCjQDaDB7mjPAzMDSbQWXNu2zYkTdDNUsPMS5Xx8QMmQVYN7n74eZrYJxDJ
+  # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+  expireTime: 450
+
+# MyBatis Plus閰嶇疆
+mybatis-plus:
+  # 鎼滅储鎸囧畾鍖呭埆鍚�   鏍规嵁鑷繁鐨勯」鐩潵
+  typeAliasesPackage: com.ruoyi.**.pojo
+  # 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
+  configLocation: classpath:mybatis/mybatis-config.xml
+  global-config:
+    enable-sql-runner: true
+    db-config:
+      id-type: auto
+
+# PageHelper鍒嗛〉鎻掍欢
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger閰嶇疆
+swagger:
+  # 鏄惁寮�鍚痵wagger
+  enabled: true
+  # 璇锋眰鍓嶇紑
+  pathMapping: /dev-api
+
+# 闃叉XSS鏀诲嚮
+xss:
+  # 杩囨护寮�鍏�
+  enabled: true
+  # 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
+  excludes: /system/notice
+  # 鍖归厤閾炬帴
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+# 浠g爜鐢熸垚
+gen:
+  # 浣滆��
+  author: ruoyi
+  # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
+  packageName: com.ruoyi.project.system
+  # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸true
+  autoRemovePre: false
+  # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
+  tablePrefix: sys_
+  # 鏄惁鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦帮紙鑷畾涔夎矾寰勶級锛岄粯璁や笉鍏佽
+  allowOverwrite: false
+
+# 鏂囦欢涓婁紶閰嶇疆
+file:
+  temp-dir: /javaWork/product-inventory-management/file/temp/uploads   # 涓存椂鐩綍
+  upload-dir: /javaWork/product-inventory-management/file/prod/uploads # 姝e紡鐩綍
+  path: /javaWork/product-inventory-management/file # 涓婁紶鐩綍
+  urlPrefix: /prod-api/common # 閾炬帴鍓嶇紑
+  domain: http://1.15.17.182:9049 # 鍩熷悕鍓嶇紑
+  expired: 120 # 杩囨湡鏃堕棿(鍗曚綅:鍒嗛挓)
+  useLimit: 10 # 浣跨敤娆℃暟
+  compress: true # 鏄惁鍘嬬缉
+  needCompressSize: 10MB # 鍘嬬缉闃堝��
+  compressQuality: 0.5 # 鍘嬬缉璐ㄩ噺(0.0-1.0)
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index c79d967..70324c6 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,4 +1,42 @@
 # Spring閰嶇疆
 spring:
+  main:
+    allow-circular-references: true
   profiles:
     active: dev
+langchain4j:
+  mcp:
+    # MCP 鏈嶅姟绔湴鍧�锛堟牴鎹疄闄呴儴缃茬殑 MCP 鏈嶅姟璋冩暣锛�
+    server-url: http://114.132.189.42:8093/ocr
+    # 璇锋眰瓒呮椂鏃堕棿锛堟绉掞級
+    timeout: 30000
+    # 鍙�夛細MCP 鍗忚鐗堟湰
+    version: 1.0
+  community:
+    dashscope:
+      streaming-chat-model:
+        api-key: sk-bd235cc13cd74e2388aa8984c84f691f
+        model-name: "qwen-max"
+      embedding-model:
+        api-key: sk-9748859926b94096b920baaa12c343f5
+        model-name: "text-embedding-v3"
+      chat-model:
+        api-key: sk-9748859926b94096b920baaa12c343f5
+        model-name: "qwen-max"
+  open-ai:
+    chat-model:
+      api-key: sk-9748859926b94096b920baaa12c343f5
+      base-url: "https://dashscope.aliyuncs.com/compatible-mode/v1"
+      model-name: "deepseek-v3"
+      log-requests: true
+      log-responses: true
+      temperature: 0.9
+
+  ollama:
+    chat-model:
+      base-url: "http://localhost:11434"
+      model-name: "deepseek-r1:1.5b"
+      log-requests: true
+      log-responses: true
+knowledge:
+  one: D:\鏂扮枂澶х綏绱犱紒涓氫骇鍝佷綋绯昏鏄庢枃妗�.md
diff --git a/src/main/resources/approve-todo-agent-prompt.txt b/src/main/resources/approve-todo-agent-prompt.txt
new file mode 100644
index 0000000..c309da8
--- /dev/null
+++ b/src/main/resources/approve-todo-agent-prompt.txt
@@ -0,0 +1,18 @@
+浣犳槸涓�涓鎵瑰緟鍔炲姪鎵嬶紝璐熻矗鍗忓悓鍔炲叕瀹℃壒寰呭姙鐨勬煡璇€�佸鏍搞�佸彇娑堝鏍搞�佷慨鏀广�佸垹闄ゅ拰缁熻鍒嗘瀽銆�
+
+宸ヤ綔瑕佹眰锛�
+1. 鐢ㄦ埛闂緟鍔炲垪琛ㄣ�佸鎵硅繘搴︺�佸鎵硅鎯呫�佺粺璁℃暟鎹椂锛屼紭鍏堣皟鐢ㄥ伐鍏凤紝涓嶈鑷嗛�犳暟鎹��
+2. 鐢ㄦ埛瑕佹眰鎵ц瀹℃牳銆佸彇娑堝鏍搞�佷慨鏀广�佸垹闄ゆ椂锛屽厛纭鍏抽敭鍙傛暟榻愬叏鍐嶈皟鐢ㄥ伐鍏枫��
+3. 瀹℃牳鍔ㄤ綔閲岋紝`approve` 琛ㄧず閫氳繃锛宍reject` 琛ㄧず椹冲洖銆�
+4. 淇敼瀹℃壒鍗曟椂锛屽鏋滅敤鎴锋病鏈夋槑纭淇敼鍝簺瀛楁锛岃鍏堣拷闂己澶卞瓧娈碉紝涓嶈鐚溿��
+5. 鍒犻櫎銆佸鏍搞�佸彇娑堝鏍歌繖绫诲姩浣滃睘浜庣姸鎬佸彉鏇达紝鎵ц鍚庤鏄庣‘鍙嶉缁撴灉銆�
+6. 鐢ㄦ埛璇粹�滃崟鎹�濃�滄祦绋嬧�濃�滃鎵规壒鈥濃�滃緟鍔炩�濓紝閮芥寜瀹℃壒寰呭姙鐞嗚В锛涚敤鎴疯鈥滃崱鍦ㄥ摢涓妭鐐光�濃�滃綋鍓嶅鎵逛汉鈥濃�滄祦杞褰曗�濓紝璋冪敤鈥滄煡璇㈠鎵规祦杞褰曗�濄��
+7. 鐢ㄦ埛璇粹�滄垜鍙戣捣鐨勨�濃�滄垜鎻愪氦鐨勨�濃�滄垜鐢宠鐨勨�濓紝鏌ヨ鑼冨洿浣跨敤 `applicant`锛涚敤鎴疯鈥滃緟鎴戝鎵光�濃�滃綋鍓嶅緟鎴戝鐞嗏�濃�滈渶瑕佹垜澶勭悊鈥濓紝鏌ヨ鑼冨洿浣跨敤 `approver`锛涙病鏈夋槑纭寖鍥存椂浣跨敤 `related`銆�
+8. 鐢ㄦ埛璇粹�滃鐞嗕腑鈥濃�滃姙鐞嗕腑鈥濓紝鐘舵�佷娇鐢� `processing`锛涜鈥滃緟瀹℃壒鈥濃�滃緟瀹℃牳鈥濓紝鐘舵�佷娇鐢� `pending`锛涜鈥滈�氳繃鈥濃�滃凡閫氳繃鈥濓紝鐘舵�佷娇鐢� `approved`锛涜鈥滈┏鍥炩�濃�滄嫆缁濃�濃�滄湭閫氳繃鈥濓紝鐘舵�佷娇鐢� `rejected`銆�
+9. 鐢ㄦ埛瑕佹眰鈥滆繎7澶┾�濃�滄湰鏈堚�濃�滆繎30澶┾�濃�滃悇绫诲瀷鍒嗗竷鈥濃�滈�氳繃/椹冲洖/澶勭悊涓悇鏈夊灏戔�濈瓑缁熻鍙e緞鏃讹紝璋冪敤缁熻宸ュ叿銆�
+10. 鐢ㄦ埛璇粹�滃娉ㄥ悓鎰忊�濃�滃娉ㄨ姹傝ˉ鍏呰鏄庘�濇椂锛屾妸澶囨敞鍐呭浼犵粰瀹℃牳宸ュ叿鐨� remark锛涢┏鍥炴椂濡傛灉娌℃湁鈥滃師鍥犫�濅絾鏈夆�滃娉ㄢ�濓紝涔熶娇鐢ㄥ娉ㄣ��
+11. 闄も�滄煡璇㈠鎵瑰緟鍔炶鎯呪�濆锛屽叾浠栧伐鍏烽粯璁よ繑鍥� JSON銆�
+12. 瀵逛簬杩欎簺 JSON 宸ュ叿锛屼綘蹇呴』鐩存帴杈撳嚭鍘熷 JSON 瀛楃涓叉湰韬紝涓嶈鏀瑰啓锛屼笉瑕侀澶栬В閲婏紝涓嶈鍖呰9 Markdown 浠g爜鍧楋紝涓嶈鍦� JSON 鍓嶅悗鍔犱换浣曟枃瀛椼��
+13. 鍙湁鈥滄煡璇㈠鎵瑰緟鍔炶鎯呪�濊繖涓伐鍏峰厑璁歌緭鍑鸿嚜鐒惰瑷�鏂囨湰銆�
+14. 濡傛灉宸ュ叿杩斿洖鐨勬槸缁熻 JSON锛屼篃鍚屾牱鐩存帴杈撳嚭鍘熷 JSON锛涘叾涓� `description`銆乣summary`銆乣charts` 宸茬粡渚涘墠绔娇鐢ㄣ��
+15. 鍥炵瓟浣跨敤涓枃锛涗絾鍦� JSON 鍦烘櫙涓嬶紝鏈�缁堣緭鍑哄繀椤绘槸鍚堟硶 JSON 鏈綋銆�
diff --git a/src/main/resources/mapper/account/AccountExpenseMapper.xml b/src/main/resources/mapper/account/AccountExpenseMapper.xml
index 1a8d34b..f4039c8 100644
--- a/src/main/resources/mapper/account/AccountExpenseMapper.xml
+++ b/src/main/resources/mapper/account/AccountExpenseMapper.xml
@@ -10,6 +10,12 @@
         <if test="accountExpense.entryDateStart != null and accountExpense.entryDateStart != '' ">
             AND expense_date &gt;= DATE_FORMAT(#{accountExpense.entryDateStart},'%Y-%m-%d')
         </if>
+        <if test=" accountExpense.supplierName != null and accountExpense.supplierName != ''">
+            AND supplier_name like CONCAT('%',#{accountExpense.supplierName},'%')
+        </if>
+        <if test=" accountExpense.invoiceNumber != null and accountExpense.invoiceNumber != ''">
+            AND invoice_number like CONCAT('%',#{accountExpense.invoiceNumber},'%')
+        </if>
         <if test="accountExpense.entryDateEnd != null and accountExpense.entryDateEnd != '' ">
             AND  expense_date &lt;= DATE_FORMAT(#{accountExpense.entryDateEnd},'%Y-%m-%d')
         </if>
@@ -53,7 +59,7 @@
         <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
             AND expense_date &lt;= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
         </if>
-        group by expense_type
+        group by sdd.dict_label, ae.expense_type
     </select>
 
     <select id="report1" resultType="java.math.BigDecimal">
diff --git a/src/main/resources/mapper/account/AccountIncomeMapper.xml b/src/main/resources/mapper/account/AccountIncomeMapper.xml
index e4f3361..9becd41 100644
--- a/src/main/resources/mapper/account/AccountIncomeMapper.xml
+++ b/src/main/resources/mapper/account/AccountIncomeMapper.xml
@@ -11,13 +11,39 @@
         <if test="accountIncome.entryDateStart != null and accountIncome.entryDateStart != '' ">
             AND income_date &gt;= DATE_FORMAT(#{accountIncome.entryDateStart},'%Y-%m-%d')
         </if>
+        <if test="accountIncome.customerName != null and accountIncome.customerName != '' ">
+            AND customer_name like CONCAT('%',#{accountIncome.customerName},'%')
+        </if>
+
+        <if test="accountIncome.invoiceNumber != null and accountIncome.invoiceNumber != '' ">
+            AND invoice_number like CONCAT('%',#{accountIncome.invoiceNumber},'%')
+        </if>
         <if test="accountIncome.entryDateEnd != null and accountIncome.entryDateEnd != '' ">
             AND income_date &lt;= DATE_FORMAT(#{accountIncome.entryDateEnd},'%Y-%m-%d')
         </if>
         <if test="accountIncome.incomeType != null and accountIncome.incomeType != '' ">
             AND income_type = #{accountIncome.incomeType}
         </if>
-        <if test="accountIncome.incomeMethod != null and accountIncome.incomeMethod != '' ">
+        <if test="accountIncome.incomeMethodLabel != null and accountIncome.incomeMethodLabel != ''">
+            AND (
+            (
+            business_type = 1
+            AND income_method in
+            <foreach collection="accountIncome.receiptPaymentMethodList" item="method" open="(" separator="," close=")">
+                #{method}
+            </foreach>
+            )
+            OR
+            (
+            business_type is null
+            AND income_method in
+            <foreach collection="accountIncome.paymentMethodList" item="method" open="(" separator="," close=")">
+                #{method}
+            </foreach>
+            )
+            )
+        </if>
+        <if test="(accountIncome.incomeMethodLabel == null or accountIncome.incomeMethodLabel == '') and accountIncome.incomeMethod != null and accountIncome.incomeMethod != '' ">
             AND income_method = #{accountIncome.incomeMethod}
         </if>
     </select>
@@ -54,7 +80,7 @@
         <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
             AND income_date &lt;= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
         </if>
-        group by income_type
+        GROUP BY sdd.dict_label, ai.income_type
     </select>
     <select id="report1" resultType="java.math.BigDecimal">
         SELECT
diff --git a/src/main/resources/mapper/account/SalesRefundAmountOrderMapper.xml b/src/main/resources/mapper/account/SalesRefundAmountOrderMapper.xml
index a58e90f..355151a 100644
--- a/src/main/resources/mapper/account/SalesRefundAmountOrderMapper.xml
+++ b/src/main/resources/mapper/account/SalesRefundAmountOrderMapper.xml
@@ -27,7 +27,7 @@
         from sales_refund_amount_order srao
         left join return_management rm on srao.return_management_id = rm.id
         left join return_sale_product rs on rm.id = rs.return_management_id
-        left join sales_ledger_product slp on rs.return_sale_ledger_product_id = slp.id
+        left join sales_ledger_product slp on rs.return_sales_ledger_product_id = slp.id
         left join sales_ledger sl on slp.sales_ledger_id = sl.id
         <where>
             <if test="ew.salesContractNo != null and ew.salesContractNo !=''">
diff --git a/src/main/resources/mapper/approve/ApproveProcessConfigNodeMapper.xml b/src/main/resources/mapper/approve/ApproveProcessConfigNodeMapper.xml
new file mode 100644
index 0000000..7e88ba4
--- /dev/null
+++ b/src/main/resources/mapper/approve/ApproveProcessConfigNodeMapper.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.approve.mapper.ApproveProcessConfigNodeMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.approve.pojo.ApproveProcessConfigNode">
+        <id column="id" property="id" />
+        <result column="node_order" property="nodeOrder" />
+        <result column="approver_type" property="approverType" />
+        <result column="is_required" property="isRequired" />
+        <result column="timeout_hours" property="timeoutHours" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="delete_flag" property="deleteFlag" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/approve/ApproveProcessMapper.xml b/src/main/resources/mapper/approve/ApproveProcessMapper.xml
index 33b29a9..fef06f7 100644
--- a/src/main/resources/mapper/approve/ApproveProcessMapper.xml
+++ b/src/main/resources/mapper/approve/ApproveProcessMapper.xml
@@ -27,7 +27,7 @@
         approve_user_names,approve_reason,approve_time,approve_over_time,approve_status,
         approve_delete,tenant_id,approve_type,approve_remark
     </sql>
-    <select id="listPage" resultType="com.ruoyi.approve.pojo.ApproveProcess">
+    <select id="listPage" resultType="com.ruoyi.approve.vo.ApproveProcessVo">
         select * from approve_process where approve_delete = 0
         <if test="req.approveId != null and req.approveId != ''">
             and approve_id like concat('%',#{req.approveId},'%')
diff --git a/src/main/resources/mapper/basic/CustomerMapper.xml b/src/main/resources/mapper/basic/CustomerMapper.xml
new file mode 100644
index 0000000..57dea6c
--- /dev/null
+++ b/src/main/resources/mapper/basic/CustomerMapper.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.CustomerMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.Customer">
+        <id column="id" property="id" />
+    </resultMap>
+    <select id="listPage" resultType="com.ruoyi.basic.vo.CustomerVo">
+        select
+        c.*,
+        u.user_name usage_user_name,
+        (
+        select group_concat(u2.user_name separator ', ')
+        from customer_user cu
+        left join sys_user u2 on cu.user_id = u2.user_id
+        where cu.customer_id = c.id
+        and cu.user_id != c.usage_user
+        ) as together_user_names,
+        (
+        select group_concat(cu.user_id separator ',')
+        from customer_user cu
+        where cu.customer_id = c.id
+        and cu.user_id != c.usage_user
+        ) as user_ids_str
+        from customer c
+        left join sys_user u on c.usage_user = u.user_id
+        <where>
+            <if test="c.customerName != null and c.customerName != ''">
+                and customer_name like concat('%', #{c.customerName}, '%')
+            </if>
+            <if test="c.customerType != null and c.customerType != ''">
+                and customer_type = #{c.customerType}
+            </if>
+            <!-- 鍏捣鏌ヨ锛歵ype = 1锛堝叕娴峰鎴凤級-->
+            <if test="c.type != null and c.type == 1">
+                and type = #{c.type}
+            </if>
+            <!-- 绉佹捣鏌ヨ锛歵ype = 0锛堢娴峰鎴凤級鎴栬�� type = 1锛堝叕娴峰鎴凤級涓斿凡琚垎閰嶏紝骞朵笖鏄嚜宸遍鐢ㄣ�佽嚜宸卞垱寤烘垨鑰呭叡浜粰鑷繁鐨勫鎴� -->
+            <if test="c.type != null and c.type == 0">
+                and (
+                    (type = #{c.type} or (type = 1 and is_assigned = 1))
+                    and (
+                        c.usage_user = #{loginUserId}
+                        or c.create_user = #{loginUserId}
+                        or exists (
+                            select 1 from customer_user cu
+                            where cu.customer_id = c.id
+                            and cu.user_id = #{loginUserId}
+                        )
+                    )
+                )
+            </if>
+        </where>
+    </select>
+
+    <select id="list" resultType="com.ruoyi.basic.vo.CustomerVo">
+        select
+        c.*,
+        u.user_name usage_user_name,
+        (
+        select group_concat(u2.user_name separator ', ')
+        from customer_user cu
+        left join sys_user u2 on cu.user_id = u2.user_id
+        where cu.customer_id = c.id
+        and cu.user_id != c.usage_user
+        ) as together_user_names,
+        (
+        select group_concat(cu.user_id separator ',')
+        from customer_user cu
+        where cu.customer_id = c.id
+        and cu.user_id != c.usage_user
+        ) as user_ids_str
+        from customer c
+        left join sys_user u on c.usage_user = u.user_id
+        <where>
+            <if test="c.ids != null and c.ids.length > 0">
+                and c.id in
+                <foreach collection="c.ids" item="id" open="(" separator="," close=")">
+                    #{id}
+                </foreach>
+            </if>
+            <if test="c.customerName != null and c.customerName != ''">
+                and customer_name like concat('%', #{c.customerName}, '%')
+            </if>
+            <if test="c.customerType != null and c.customerType != ''">
+                and customer_type = #{c.customerType}
+            </if>
+            <!-- 鍏捣鏌ヨ锛歵ype = 1锛堝叕娴峰鎴凤級-->
+            <if test="c.type != null and c.type == 1">
+                and type = #{c.type}
+            </if>
+            <!-- 绉佹捣鏌ヨ锛歵ype = 0锛堢娴峰鎴凤級鎴栬�� type = 1锛堝叕娴峰鎴凤級涓斿凡琚垎閰嶏紝骞朵笖鏄嚜宸遍鐢ㄣ�佽嚜宸卞垱寤烘垨鑰呭叡浜粰鑷繁鐨勫鎴� -->
+            <if test="c.type != null and c.type == 0">
+                and (
+                    (type = #{c.type} or (type = 1 and is_assigned = 1))
+                    and (
+                        c.usage_user = #{loginUserId}
+                        or c.create_user = #{loginUserId}
+                        or exists (
+                            select 1 from customer_user cu
+                            where cu.customer_id = c.id
+                            and cu.user_id = #{loginUserId}
+                        )
+                    )
+                )
+            </if>
+        </where>
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/basic/ProductModelMapper.xml b/src/main/resources/mapper/basic/ProductModelMapper.xml
index 317f5d9..0a540bf 100644
--- a/src/main/resources/mapper/basic/ProductModelMapper.xml
+++ b/src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -14,7 +14,16 @@
         <result column="product_name" property="productName" />
         <result column="product_id" property="productId" />
     </resultMap>
-    <select id="listPageProductModel" resultType="com.ruoyi.basic.pojo.ProductModel">
+
+    <resultMap id="ProductModelVoResultMap" type="com.ruoyi.basic.vo.ProductModelVo" extends="BaseResultMap">
+        <result column="create_time" property="createTime" />
+        <collection property="batchNoList"
+                    ofType="java.lang.String"
+                    column="{productModelId=id}"
+                    select="selectBatchNoListByProductModelId"/>
+    </resultMap>
+
+    <select id="listPageProductModel" resultMap="ProductModelVoResultMap">
         select pm.*,p.product_name
         from product_model pm
         left join product p on pm.product_id = p.id
@@ -25,8 +34,33 @@
             <if test="c.productName != null and c.productName != ''">
                 and p.product_name  like  concat('%',#{c.productName},'%')
             </if>
+            <if test="c.topProductParentId != null and c.topProductParentId > 0">
+                and p.id in (
+                    WITH RECURSIVE product_tree AS (
+                        SELECT id
+                        FROM product
+                        WHERE id = #{c.topProductParentId}
+
+                        UNION ALL
+
+                        SELECT p.id
+                        FROM product p
+                        INNER JOIN product_tree pt ON p.parent_id = pt.id
+                    )
+                    select id from product_tree
+                )
+            </if>
         </where>
         order by  pm.id
+    </select>
+
+    <select id="selectBatchNoListByProductModelId" resultType="java.lang.String">
+        select distinct si.batch_no
+        from stock_inventory si
+        where si.product_model_id = #{productModelId}
+          and si.batch_no is not null
+          and si.batch_no != ''
+        order by si.batch_no
     </select>
     <select id="selectLatestRecord" resultType="com.ruoyi.basic.pojo.ProductModel">
             SELECT * FROM product_model
@@ -107,4 +141,4 @@
         order by p.id,pm.id desc
     </select>
 
-</mapper>
\ No newline at end of file
+</mapper>
diff --git a/src/main/resources/mapper/basic/StorageAttachmentMapper.xml b/src/main/resources/mapper/basic/StorageAttachmentMapper.xml
index a2cc6cf..d2b7b92 100644
--- a/src/main/resources/mapper/basic/StorageAttachmentMapper.xml
+++ b/src/main/resources/mapper/basic/StorageAttachmentMapper.xml
@@ -10,13 +10,9 @@
                     <result column="deleted" property="deleted" />
                     <result column="record_type" property="recordType" />
                     <result column="record_id" property="recordId" />
-                    <result column="name" property="name" />
+                    <result column="application" property="application" />
                     <result column="storage_blob_id" property="storageBlobId" />
         </resultMap>
 
-        <!-- 閫氱敤鏌ヨ缁撴灉鍒� -->
-        <sql id="Base_Column_List">
-            id, create_time, update_time, deleted, record_type, record_id, name, storage_blob_id
-        </sql>
 
-</mapper>
\ No newline at end of file
+</mapper>
diff --git a/src/main/resources/mapper/basic/StorageBlobMapper.xml b/src/main/resources/mapper/basic/StorageBlobMapper.xml
index 84e3b00..d8a03fa 100644
--- a/src/main/resources/mapper/basic/StorageBlobMapper.xml
+++ b/src/main/resources/mapper/basic/StorageBlobMapper.xml
@@ -2,21 +2,50 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.basic.mapper.StorageBlobMapper">
 
-        <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-        <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StorageBlob">
-                    <id column="id" property="id" />
-                    <result column="create_time" property="createTime" />
-                    <result column="key" property="key" />
-                    <result column="content_type" property="contentType" />
-                    <result column="original_filename" property="originalFilename" />
-                    <result column="bucket_filename" property="bucketFilename" />
-                    <result column="bucket_name" property="bucketName" />
-                    <result column="byte_size" property="byteSize" />
-        </resultMap>
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StorageBlob">
+        <id column="id" property="id"/>
+        <result column="resource_key" property="resourceKey"/>
+        <result column="content_type" property="contentType"/>
+        <result column="original_filename" property="originalFilename"/>
+        <result column="uid_filename" property="uidFilename"/>
+        <result column="byte_size" property="byteSize"/>
+        <result column="path" property="path"/>
+    </resultMap>
 
-        <!-- 閫氱敤鏌ヨ缁撴灉鍒� -->
-        <sql id="Base_Column_List">
-            id, create_time, key, content_type, original_filename,bucket_filename,bucket_name,  byte_size
-        </sql>
+    <!-- 閫氱敤鏌ヨ缁撴灉鍒� -->
+    <sql id="Base_Column_List">
+        id, resource_key, content_type, original_filename, uid_filename, byte_size, path
+    </sql>
 
-</mapper>
\ No newline at end of file
+    <select id="selectOrphanBlobsByIdRange" resultMap="BaseResultMap">
+        SELECT
+        <include refid="Base_Column_List"/>
+        FROM storage_blob sb
+        LEFT JOIN storage_attachment sa
+        ON sa.storage_blob_id = sb.id
+        AND sa.deleted = 0
+        WHERE sb.id <![CDATA[>]]> #{lastId}
+        AND sa.id IS NULL
+        ORDER BY sb.id ASC
+        LIMIT #{limit}
+    </select>
+
+    <delete id="deleteByIdList">
+        DELETE FROM storage_blob
+        WHERE id IN
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <select id="selectExistingUidFilenames" resultType="java.lang.String">
+        SELECT uid_filename
+        FROM storage_blob
+        WHERE uid_filename IN
+        <foreach collection="fileNames" item="fileName" open="(" separator="," close=")">
+            #{fileName}
+        </foreach>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml b/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
index 2ed16a4..e21669f 100644
--- a/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
+++ b/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
@@ -19,6 +19,7 @@
         dm.tenant_id,
         dm.maintenance_actually_name,
         dl.device_name,
+        dm.machinery_category,
         dl.device_model,
         su.nick_name as create_user_name
         from device_maintenance dm
@@ -50,7 +51,7 @@
             </if>
         </where>
     </select>
-    <select id="detailById" resultType="com.ruoyi.device.dto.DeviceMaintenanceDto">
+    <select id="detailById" resultType="com.ruoyi.device.vo.DeviceMaintenanceVo">
         select dm.id,
                dm.device_ledger_id,
                dm.maintenance_plan_time,
@@ -62,6 +63,7 @@
                dm.create_user,
                dm.update_user,
                dm.tenant_id,
+               dm.machinery_category,
                dm.maintenance_actually_name,
                dl.device_name,
                dl.device_model,
diff --git a/src/main/resources/mapper/device/DeviceRepairMapper.xml b/src/main/resources/mapper/device/DeviceRepairMapper.xml
index d093980..2eb1d29 100644
--- a/src/main/resources/mapper/device/DeviceRepairMapper.xml
+++ b/src/main/resources/mapper/device/DeviceRepairMapper.xml
@@ -5,7 +5,7 @@
 
 <mapper namespace="com.ruoyi.device.mapper.DeviceRepairMapper">
 
-    <select id="queryPage" resultType="com.ruoyi.device.dto.DeviceRepairDto">
+    <select id="queryPage" resultType="com.ruoyi.device.vo.DeviceRepairVo">
         select dr.id,
                dr.device_ledger_id,
                 dr.repair_time,
@@ -21,7 +21,8 @@
                 dr.update_user,
                dr.tenant_id,
                dl.device_name,
-               dl.device_model
+               dl.device_model,
+               dr.machinery_category
         from device_repair dr
         left join device_ledger dl on dr.device_ledger_id = dl.id
         <where>
@@ -50,7 +51,7 @@
             </if>
         </where>
     </select>
-    <select id="detailById" resultType="com.ruoyi.device.dto.DeviceRepairDto">
+    <select id="detailById" resultType="com.ruoyi.device.vo.DeviceRepairVo">
         select dr.id,
                dr.device_ledger_id,
                dr.repair_time,
@@ -66,6 +67,7 @@
                dr.update_user,
                dr.tenant_id,
                dl.device_name,
+               dr.machinery_category,
                dl.device_model
         from device_repair dr
                  left join device_ledger dl on dr.device_ledger_id = dl.id
diff --git a/src/main/resources/mapper/measuringinstrumentledger/SparePartsRequisitionRecordMapper.xml b/src/main/resources/mapper/measuringinstrumentledger/SparePartsRequisitionRecordMapper.xml
new file mode 100644
index 0000000..9851e59
--- /dev/null
+++ b/src/main/resources/mapper/measuringinstrumentledger/SparePartsRequisitionRecordMapper.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.measuringinstrumentledger.mapper.SparePartsRequisitionRecordMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord">
+        <id column="id" property="id" />
+        <result column="source_type" property="sourceType" />
+        <result column="source_id" property="sourceId" />
+        <result column="device_ledger_id" property="deviceLedgerId" />
+        <result column="spare_parts_id" property="sparePartsId" />
+        <result column="quantity" property="quantity" />
+        <result column="create_user" property="createUser" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+
+    <select id="listPage" resultType="com.ruoyi.measuringinstrumentledger.dto.SparePartsRequisitionRecordDto">
+        select sprr.*,sp.name as sparePartsName, dl.device_name as deviceName, su.nick_name as operator
+        from spare_parts_requisition_record sprr
+        left join spare_parts sp on sp.id = sprr.spare_parts_id
+        left join device_ledger dl on dl.id = sprr.device_ledger_id
+        left join sys_user su on su.user_id = sprr.create_user
+        <where>
+            <if test="params.sparePartsName != null and params.sparePartsName != ''">
+                and sp.name like concat('%',#{params.sparePartsName},'%')
+            </if>
+
+            <if test="params.sourceType != null and params.sourceType != ''">
+                and sprr.source_type = #{params.sourceType}
+            </if>
+        </where>
+    </select>
+</mapper>
diff --git a/src/main/resources/mapper/procurementrecord/ReturnSaleProductMapper.xml b/src/main/resources/mapper/procurementrecord/ReturnSaleProductMapper.xml
index 71d38ea..55cba43 100644
--- a/src/main/resources/mapper/procurementrecord/ReturnSaleProductMapper.xml
+++ b/src/main/resources/mapper/procurementrecord/ReturnSaleProductMapper.xml
@@ -6,7 +6,7 @@
     <resultMap id="BaseResultMap" type="com.ruoyi.procurementrecord.pojo.ReturnSaleProduct">
         <id column="id" property="id" />
         <result column="return_management_id" property="returnManagementId" />
-        <result column="return_sale_ledger_product_id" property="returnSaleLedgerProductId" />
+        <result column="return_sales_ledger_product_id" property="returnsalesLedgerProductId" />
         <result column="num" property="num" />
         <result column="status" property="status" />
     </resultMap>
@@ -21,18 +21,18 @@
                  LEFT JOIN return_management rm ON rm.id = rsp.return_management_id
                  LEFT JOIN shipping_info si ON si.id = rm.shipping_id
                  LEFT JOIN sales_ledger_product slp ON si.sales_ledger_product_id = slp.id and slp.type = 1
-                 LEFT JOIN (SELECT return_sale_ledger_product_id,
+                 LEFT JOIN (SELECT return_sales_ledger_product_id,
 
                                    SUM(num) AS total_return_num
                             FROM return_sale_product
                             WHERE 1 = 1 and return_management_id != #{returnManagementId}
-                            GROUP BY return_sale_ledger_product_id) rs ON rs.return_sale_ledger_product_id = slp.id
+                            GROUP BY return_sales_ledger_product_id) rs ON rs.return_sales_ledger_product_id = slp.id
         where rm.id =#{returnManagementId}
     </select>
     <select id="listReturnSaleProduct" resultType="com.ruoyi.procurementrecord.dto.ReturnSaleProductDto">
         select rsp.*,slp.tax_inclusive_unit_price ,slp.tax_inclusive_total_price*rsp.num as price
         from return_sale_product rsp
-                 left join sales_ledger_product slp on slp.id = rsp.return_sale_ledger_product_id
+                 left join sales_ledger_product slp on slp.id = rsp.return_sales_ledger_product_id
         where rsp.return_management_id = #{returnManagementId}
     </select>
 
diff --git a/src/main/resources/mapper/production/ProcessRouteItemMapper.xml b/src/main/resources/mapper/production/ProcessRouteItemMapper.xml
deleted file mode 100644
index 1b5e2b4..0000000
--- a/src/main/resources/mapper/production/ProcessRouteItemMapper.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProcessRouteItemMapper">
-
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProcessRouteItem">
-        <id property="id" column="id"/>
-        <result property="routeId" column="route_id"/>
-        <result property="processId" column="process_id"/>
-        <result property="productModelId" column="product_model_id"/>
-        <result property="tenantId" column="tenant_id"/>
-        <result property="createTime" column="create_time"/>
-        <result property="updateTime" column="update_time"/>
-        <result property="dragSort" column="drag_sort"/>
-    </resultMap>
-
-    <select id="listProcessRouteItemDto" resultType="com.ruoyi.production.dto.ProcessRouteItemDto">
-        select pri.*,
-               pr.description ,
-               pp.name as process_name,
-               pm.speculative_trading_name,
-               pm.product_id,
-               pm.model,
-               p.product_name,
-               pm.unit
-        from
-            process_route_item pri
-                left join product_model pm on pri.product_model_id = pm.id
-                left join product_process pp on pp.id = pri.process_id
-                left join product p on p.id = pm.product_id
-                left join process_route pr on pr.id = pri.route_id
-        where
-            pri.route_id = #{c.routeId}
-        order by pri.drag_sort
-    </select>
-</mapper>
diff --git a/src/main/resources/mapper/production/ProcessRouteMapper.xml b/src/main/resources/mapper/production/ProcessRouteMapper.xml
deleted file mode 100644
index 51c11b4..0000000
--- a/src/main/resources/mapper/production/ProcessRouteMapper.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProcessRouteMapper">
-
-
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProcessRoute">
-            <id property="id" column="id"/>
-            <result property="productModelId" column="product_model_id"/>
-            <result property="description" column="description"/>
-            <result property="tenantId" column="tenant_id"/>
-            <result property="createTime" column="create_time"/>
-            <result property="updateTime" column="update_time"/>
-    </resultMap>
-
-    <select id="pageProcessRouteDto" resultType="com.ruoyi.production.dto.ProcessRouteDto">
-        select ps.*, p.product_name,pm.product_id,pm.model,pb.bom_no
-        from process_route ps
-        left join product_bom pb on ps.bom_id = pb.id
-        left join product_model pm on ps.product_model_id = pm.id
-        left join product p on pm.product_id = p.id
-        <where>
-            <if test="c.model != null and c.model != ''">
-                and pm.model like concat('%',#{c.model},'%')
-            </if>
-        </where>
-        order by ps.id asc
-    </select>
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductBomMapper.xml b/src/main/resources/mapper/production/ProductBomMapper.xml
deleted file mode 100644
index ec06cd3..0000000
--- a/src/main/resources/mapper/production/ProductBomMapper.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductBomMapper">
-
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductBom">
-        <id column="id" property="id"/>
-        <result column="product_model_id" property="productModelId"/>
-        <result column="bom_no" property="bomNo"/>
-        <result column="remark" property="remark"/>
-        <result column="version" property="version"/>
-        <result column="create_time" property="createTime"/>
-        <result column="update_time" property="updateTime"/>
-        <result column="create_user" property="createUser"/>
-        <result column="update_user" property="updateUser"/>
-        <result column="tenant_id" property="tenantId"/>
-    </resultMap>
-    <select id="listPage" resultType="com.ruoyi.production.dto.ProductBomDto">
-        select * from (select pb.*,
-        pm.model productModelName,
-        p.product_name productName
-        from product_bom pb
-        left join product_model pm on pb.product_model_id = pm.id
-        left join product p on pm.product_id = p.id)A
-        where 1=1
-        <if test="c.productModelName != null">
-            and productModelName = #{c.productModelName}
-        </if>
-        <if test="c.productName != null">
-            and productName = #{c.productName}
-        </if>
-        <if test="c.bomNo != null">
-            and bom_no = #{c.bomNo}
-        </if>
-        <if test="c.version != null">
-            and version = #{c.version}
-        </if>
-    </select>
-    <select id="getById" resultType="com.ruoyi.production.dto.ProductBomDto">
-        select pb.*,
-               pm.model productModelName,
-               p.product_name productName
-        from product_bom pb
-                 left join product_model pm on pb.product_model_id = pm.id
-                 left join product p on pm.product_id = p.id
-    </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductOrderMapper.xml b/src/main/resources/mapper/production/ProductOrderMapper.xml
deleted file mode 100644
index 6b993bf..0000000
--- a/src/main/resources/mapper/production/ProductOrderMapper.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductOrderMapper">
-
-
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProductOrder">
-        <id property="id" column="id"/>
-        <result property="productModelId" column="product_model_id"/>
-        <result property="tenantId" column="tenant_id"/>
-        <result property="salesLedgerId" column="sales_ledger_id"/>
-        <result property="routeId" column="route_id"/>
-        <result property="npsNo" column="nps_no"/>
-        <result property="createTime" column="create_time"/>
-        <result property="updateTime" column="update_time"/>
-    </resultMap>
-    <select id="pageProductOrder" resultType="com.ruoyi.production.dto.ProductOrderDto">
-        select po.*,
-        sl.sales_contract_no,
-        sl.customer_name,
-        p.product_name as product_category,
-        pm.model as specification_model,
-        pm.unit,
-        ppr.process_route_code,
-        pb.bom_no,
-        ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus,
-        DATEDIFF(sl.delivery_date, CURDATE()) AS delivery_days_diff,
-        sl.delivery_date,
-        CASE
-        WHEN shipping_status_counts.total_count = 0 THEN false
-        WHEN shipping_status_counts.unshipped_count = 0 THEN true
-        ELSE false
-        END AS is_fh
-        from product_order po
-        left join sales_ledger sl on po.sales_ledger_id = sl.id
-        LEFT JOIN (
-        SELECT sales_ledger_id,
-        COUNT(*) as total_count,
-        SUM(CASE WHEN status != '宸插彂璐�' THEN 1 ELSE 0 END) as unshipped_count
-        FROM shipping_info
-        GROUP BY sales_ledger_id
-        ) shipping_status_counts ON sl.id = shipping_status_counts.sales_ledger_id
-            left join product_model pm on po.product_model_id = pm.id
-            left join product p on pm.product_id = p.id
-        left join sales_ledger_product slp on po.sale_ledger_product_id = slp.id and slp.type = 1
-        left join product_process_route ppr on po.id = ppr.product_order_id
-        left join product_bom pb on pb.id = ppr.bom_id
-        <where>
-            <if test="c.npsNo != null and c.npsNo != ''">
-                and po.nps_no like concat('%',#{c.npsNo},'%')
-            </if>
-            <if test="c.salesContractNo != null and c.salesContractNo != ''">
-                and sl.sales_contract_no like concat('%',#{c.salesContractNo},'%')
-            </if>
-            <if test="c.customerName != null and c.customerName != ''">
-                and sl.customer_name like concat('%',#{c.customerName},'%')
-            </if>
-            <if test="c.productCategory != null and c.productCategory != ''">
-                and slp.product_category like concat('%',#{c.productCategory},'%')
-            </if>
-            <if test="c.specificationModel != null and c.specificationModel != ''">
-                and slp.specification_model like concat('%',#{c.specificationModel},'%')
-            </if>
-            <if test="c.startTime != null and c.endTime != null">
-                and po.create_time between #{c.startTime} and #{c.endTime}
-            </if>
-        </where>
-    </select>
-    <select id="listProcessRoute" resultType="com.ruoyi.production.pojo.ProcessRoute">
-        select pr.*
-        from process_route pr
-                 left join product_model pm on pr.product_model_id = pm.id
-        where pm.id = #{productModelId}
-    </select>
-    <select id="listProcessBom" resultType="com.ruoyi.production.dto.ProductStructureDto">
-        select ps.id,
-               ps.product_model_id,
-               ps.process_id,
-               ps.unit_quantity,
-               ps.unit_quantity * po.quantity as demandedQuantity,
-               ps.unit,
-               p.product_name,
-               pp.name as  process_name,
-               pm.product_id,
-               pm.model
-        from
-            product_structure ps
-                left join product_model pm on ps.product_model_id = pm.id
-                left join product p on pm.product_id = p.id
-                left join product_process pp on ps.process_id = pp.id
-                left join product_process_route ppr on ps.bom_id = ppr.bom_id
-                left join product_order po on po.id = ppr.product_order_id
-        where ppr.product_order_id = #{orderId}
-        order by ps.id
-    </select>
-
-
-    <select id="countCreated" resultType="java.lang.Integer">
-        SELECT count(1) FROM product_order
-        WHERE create_time &gt;= #{startDate} AND create_time &lt;= #{endDate}
-    </select>
-
-    <select id="countCompleted" resultType="java.lang.Integer">
-        SELECT count(1) FROM product_order
-        WHERE end_time &gt;= #{startDate} AND end_time &lt;= #{endDate}
-          AND complete_quantity &gt;= quantity
-    </select>
-
-    <select id="countPending" resultType="java.lang.Integer">
-        SELECT count(1) FROM product_order
-        WHERE create_time &gt;= #{startDate} AND create_time &lt;= #{endDate}
-          AND complete_quantity &lt; quantity
-    </select>
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductProcessMapper.xml b/src/main/resources/mapper/production/ProductProcessMapper.xml
deleted file mode 100644
index 5b1ac18..0000000
--- a/src/main/resources/mapper/production/ProductProcessMapper.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductProcessMapper">
-
-    <select id="listPage" resultType="com.ruoyi.production.dto.ProductProcessDto">
-        SELECT
-        *
-        FROM
-        product_process p
-        <where>
-            <if test="productProcessDto.name != null and productProcessDto.name != '' ">
-                AND  p.name LIKE CONCAT('%',#{productProcessDto.name},'%')
-            </if>
-            <if test="productProcessDto.no != null and productProcessDto.no != '' ">
-                AND  p.no LIKE CONCAT('%',#{productProcessDto.no},'%')
-            </if>
-        </where>
-        order by p.id asc
-    </select>
-
-    <select id="calculateProductionStatistics" resultType="com.ruoyi.home.dto.processDataProductionStatisticsDto">
-        SELECT
-        pp.name AS processName,
-        SUM(pi.quantity) AS totalInput,
-        SUM(distinct ppo.scrap_qty) AS totalScrap,
-        SUM(distinct (ppo.quantity - ppo.scrap_qty)) AS totalOutput
-        FROM
-        production_product_output ppo
-        INNER JOIN production_product_main ppm ON ppo.product_main_id = ppm.id
-        INNER JOIN product_process_route_item ppri ON ppm.product_process_route_item_id = ppri.id
-        INNER JOIN product_process pp ON ppri.process_id = pp.id
-        INNER JOIN production_product_input pi ON pi.product_main_id = ppm.id
-        <where>
-            <if test="startDateTime != null">
-                AND ppo.create_time &gt;= #{startDateTime}
-            </if>
-            <if test="endDateTime != null">
-                AND ppo.create_time &lt;= #{endDateTime}
-            </if>
-            <if test="userId != null">
-                AND ppm.user_id = #{userId}
-            </if>
-            <if test="processIds != null and processIds.size() > 0">
-                AND pp.id IN
-                <foreach collection="processIds" item="id" open="(" separator="," close=")">
-                    #{id}
-                </foreach>
-            </if>
-        </where>
-        GROUP BY
-        pp.id,
-        pp.name
-    </select>
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml b/src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml
deleted file mode 100644
index 302a0fb..0000000
--- a/src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductProcessRouteItemMapper">
-
-
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProductProcessRouteItem">
-        <id property="id" column="id"/>
-        <result property="productModelId" column="product_model_id"/>
-        <result property="tenantId" column="tenant_id"/>
-        <result property="createTime" column="create_time"/>
-        <result property="updateTime" column="update_time"/>
-    </resultMap>
-    <select id="listItem" resultType="com.ruoyi.production.dto.ProductProcessRouteItemDto">
-        select ppri.*,
-               pp.name as process_name,
-               pm.model,
-               pm.unit,
-               p.product_name,
-               case when pwo.complete_quantity>0 then true else false end as is_complete
-        from product_process_route_item ppri
-                 left join product_model pm on ppri.product_model_id = pm.id
-                 left join product p on pm.product_id = p.id
-                 left join product_process pp on pp.id = ppri.process_id
-                 left join product_work_order pwo on pwo.product_process_route_item_id = ppri.id
-        where ppri.product_order_id = #{orderId}
-        order by ppri.drag_sort
-    </select>
-
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductProcessRouteMapper.xml b/src/main/resources/mapper/production/ProductProcessRouteMapper.xml
deleted file mode 100644
index dd4809f..0000000
--- a/src/main/resources/mapper/production/ProductProcessRouteMapper.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductProcessRouteMapper">
-
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductProcessRoute">
-        <id column="id" property="id"/>
-        <result column="product_model_id" property="productModelId"/>
-        <result column="description" property="description"/>
-        <result column="tenant_id" property="tenantId"/>
-        <result column="create_time" property="createTime"/>
-        <result column="update_time" property="updateTime"/>
-        <result column="bom_id" property="bomId"/>
-        <result column="process_route_code" property="processRouteCode"/>
-        <result column="product_order_id" property="productOrderId"/>
-    </resultMap>
-    <select id="listMain" resultType="com.ruoyi.production.dto.ProcessRouteDto">
-        select ppr.*, p.product_name, pm.product_id, pm.model, pb.bom_no
-        from product_process_route ppr
-                 left join product_bom pb on ppr.bom_id = pb.id
-                 left join product_model pm on ppr.product_model_id = pm.id
-                 left join product p on pm.product_id = p.id
-        where ppr.product_order_id = #{orderId}
-    </select>
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductStructureMapper.xml b/src/main/resources/mapper/production/ProductStructureMapper.xml
deleted file mode 100644
index e4a0795..0000000
--- a/src/main/resources/mapper/production/ProductStructureMapper.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductStructureMapper">
-
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProductStructure">
-        <id property="id" column="id"/>
-        <result property="productModelId" column="product_model_id"/>
-        <result property="processId" column="process_id"/>
-        <result property="unitQuantity" column="unit_quantity"/>
-        <result property="demandedQuantity" column="demanded_quantity"/>
-        <result property="unit" column="unit"/>
-        <result property="tenantId" column="tenant_id"/>
-    </resultMap>
-    <select id="listBybomId" resultType="com.ruoyi.production.dto.ProductStructureDto">
-        select ps.*,
-               p.product_name,
-               pp.name as  process_name,
-               pm.product_id,
-               pm.model
-        from
-            product_structure ps
-                left join product_model pm on ps.product_model_id = pm.id
-                left join product p on pm.product_id = p.id
-                left join product_process pp on ps.process_id = pp.id
-        where ps.bom_id = #{bomId}
-        order by ps.id
-    </select>
-    <select id="listBybomAndProcess" resultType="com.ruoyi.production.dto.ProductStructureDto">
-        select ps.*,
-               p.product_name,
-               pp.name as  process_name,
-               pm.product_id,
-               pm.model
-        from
-            product_structure ps
-                left join product_model pm on ps.product_model_id = pm.id
-                left join product p on pm.product_id = p.id
-                left join product_process pp on ps.process_id = pp.id
-        where ps.bom_id = #{bomId}
-        and ps.process_id=#{processId}
-        order by ps.id
-    </select>
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductWorkOrderFileMapper.xml b/src/main/resources/mapper/production/ProductWorkOrderFileMapper.xml
deleted file mode 100644
index ae5686b..0000000
--- a/src/main/resources/mapper/production/ProductWorkOrderFileMapper.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductWorkOrderFileMapper">
-
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductWorkOrderFile">
-        <id column="id" property="id" />
-        <result column="work_order_id" property="workOrderId" />
-        <result column="name" property="name" />
-        <result column="url" property="url" />
-        <result column="file_size" property="fileSize" />
-        <result column="create_time" property="createTime" />
-        <result column="create_user" property="createUser" />
-        <result column="update_time" property="updateTime" />
-        <result column="update_user" property="updateUser" />
-        <result column="tenant_id" property="tenantId" />
-    </resultMap>
-
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductWorkOrderMapper.xml b/src/main/resources/mapper/production/ProductWorkOrderMapper.xml
deleted file mode 100644
index 14b883e..0000000
--- a/src/main/resources/mapper/production/ProductWorkOrderMapper.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper
-        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.ProductWorkOrderMapper">
-
-    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductWorkOrder">
-        <result column="id" property="id"/>
-        <result column="product_process_route_item_id" property="productProcessRouteItemId"/>
-        <result column="create_time" property="createTime"/>
-        <result column="update_time" property="updateTime"/>
-        <result column="work_order_no" property="workOrderNo"/>
-        <result column="status" property="status"/>
-        <result column="tenant_id" property="tenantId"/>
-        <result column="actual_end_time" property="planStartTime"/>
-        <result column="plan_end_time" property="planEndTime"/>
-        <result column="actual_start_time" property="actualStartTime"/>
-        <result column="actualEndTime" property="actualEndTime"/>
-    </resultMap>
-
-    <select id="pageProductWorkOrder" resultType="com.ruoyi.production.dto.ProductWorkOrderDto">
-        SELECT
-        pwo.*,
-        pp.NAME as processName,
-        pm.model,
-        pm.unit,
-        p.product_name AS productName,
-        po.nps_no AS productOrderNpsNo,
-        ROUND(pwo.complete_quantity / pwo.plan_quantity * 100, 2) AS completionStatus,
-        CASE
-        WHEN pwo.work_order_no LIKE 'FG%' THEN '杩斿伐杩斾慨'
-        ELSE '姝e父'
-        END AS work_order_type
-        FROM
-        product_work_order pwo
-        LEFT JOIN product_process_route_item ppri ON ppri.id = pwo.product_process_route_item_id
-        LEFT JOIN product_order po ON po.id = pwo.product_order_id
-        LEFT JOIN product_process pp ON pp.id = ppri.process_id
-        LEFT JOIN product_model pm ON pm.id = ppri.product_model_id
-        LEFT JOIN product p ON p.id = pm.product_id
-        where 1=1
-            <if test="c.workOrderNo != null and c.workOrderNo != ''">
-               and pwo.work_order_no like concat('%',#{c.workOrderNo},'%')
-            </if>
-            <if test="c.planStartTime != null and c.planEndTime != null">
-                and DATE(pwo.create_time) between #{c.planStartTime} and #{c.planEndTime}
-            </if>
-            <if test="c.productOrderId != null and c.productOrderId != ''">
-               and pwo.product_order_id = #{c.productOrderId}
-            </if>
-    </select>
-    <select id="getProductWorkOrderFlowCard" resultType="com.ruoyi.production.dto.ProductWorkOrderDto">
-        SELECT
-        pwo.*,
-        pp.NAME as processName,
-        pm.model,
-        pm.unit,
-        p.product_name AS productName,
-        po.nps_no AS productOrderNpsNo,
-        ROUND(pwo.complete_quantity / pwo.plan_quantity * 100, 2) AS completionStatus,
-        sum(ppo.scrap_qty) scrapQty
-        FROM
-        product_work_order pwo
-        LEFT JOIN product_process_route_item ppri ON ppri.id = pwo.product_process_route_item_id
-        LEFT JOIN production_product_main ppm ON ppm.work_order_id = pwo.id
-        LEFT JOIN production_product_output ppo ON ppo.product_main_id = ppm.id
-        LEFT JOIN product_order po ON po.id = pwo.product_order_id
-        LEFT JOIN product_process pp ON pp.id = ppri.process_id
-        LEFT JOIN product_model pm ON pm.id = ppri.product_model_id
-        LEFT JOIN product p ON p.id = pm.product_id
-        WHERE pwo.id = #{id}
-        GROUP BY pwo.id, pwo.product_process_route_item_id, pwo.create_time, pwo.update_time, pwo.work_order_no, pwo.plan_start_time, pwo.plan_end_time, pwo.actual_start_time, pwo.actual_end_time, pwo.status, pwo.tenant_id, pwo.plan_quantity, pwo.product_order_id, pwo.complete_quantity,
-                 pp.NAME ,
-                pm.model,
-                pm.unit,
-                p.product_name,
-                po.nps_no
-    </select>
-    <select id="selectWorkOrderStartStats" resultType="com.ruoyi.production.dto.ProductWorkOrderDto">
-        SELECT
-            id,
-            actual_start_time AS planStartTime,
-            plan_quantity
-        FROM
-            product_work_order
-        WHERE
-            actual_start_time &gt;= #{startDate}
-            AND actual_start_time &lt;= #{endDate}
-    </select>
-    <select id="selectMax" resultType="com.ruoyi.production.pojo.ProductWorkOrder">
-        SELECT SUBSTRING(work_order_no, 3) as work_order_no
-        FROM product_work_order
-        WHERE SUBSTRING(work_order_no, 3) like concat(#{datePrefix},'%')
-        order by work_order_no  desc
-        limit 1
-        ;
-    </select>
-</mapper>
diff --git a/src/main/resources/mapper/production/ProductionAccountMapper.xml b/src/main/resources/mapper/production/ProductionAccountMapper.xml
new file mode 100644
index 0000000..2841854
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionAccountMapper.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionAccountMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionAccount">
+        <id column="id" property="id" />
+        <result column="sales_ledger_id" property="salesLedgerId" />
+        <result column="sales_ledger_product_id" property="salesLedgerProductId" />
+        <result column="production_product_main_id" property="productionProductMainId" />
+        <result column="scheduling_user_id" property="schedulingUserId" />
+        <result column="scheduling_user_name" property="schedulingUserName" />
+        <result column="finished_num" property="finishedNum" />
+        <result column="work_hours" property="workHours" />
+        <result column="technology_operation_name" property="technologyOperationName" />
+        <result column="scheduling_date" property="schedulingDate" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listPage" resultType="com.ruoyi.production.bean.vo.ProductionAccountVo">
+        select
+        group_concat(distinct p_parent.product_name order by p_parent.product_name separator ',') as productCategory,
+        group_concat(distinct pm.model order by pm.model separator ',') as specificationModel,
+        group_concat(distinct pm.unit order by pm.unit separator ',') as unit,
+        pa.scheduling_user_id as schedulingUserId,
+        pa.scheduling_user_name as schedulingUserName,
+        cast(sum(
+            ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) *
+            case
+                when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$'
+                then cast(substring_index(pm.model, '*', -1) as decimal(18,4))
+                else 1
+            end
+        ) as decimal(18,4)) as wages,
+        cast(sum(ifnull(pa.finished_num, 0)) as decimal(18,4)) as finishedNum,
+        cast(sum(ifnull(pa.work_hours, 0)) as decimal(18,4)) as workHours,
+        case
+            when sum(ifnull(ppo.quantity, 0) + ifnull(ppo.scrapQty, 0)) = 0 then '0%'
+            else concat(
+                cast(
+                    round(
+                        sum(ifnull(ppo.quantity, 0)) /
+                        sum(ifnull(ppo.quantity, 0) + ifnull(ppo.scrapQty, 0)) * 100, 2
+                    ) as char
+                ),
+                '%'
+            )
+        end as outputRate,
+        group_concat(distinct pa.technology_operation_name order by pa.technology_operation_name separator ',') as process,
+        case
+            when count(distinct date(pa.scheduling_date)) = 1 then min(date(pa.scheduling_date))
+            else null
+        end as schedulingDate,
+        case
+            when count(distinct date_format(pa.scheduling_date, '%Y-%m')) = 1 then min(date_format(pa.scheduling_date, '%Y-%m'))
+            else null
+        end as schedulingMonth
+        from production_account pa
+        left join production_product_main ppm on ppm.id = pa.production_product_main_id
+        left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+        left join production_order po on pot.production_order_id = po.id
+        left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+        left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
+        left join product p on pm.product_id = p.id
+        left join product p_parent on p_parent.id = p.parent_id
+        left join (
+            select production_product_main_id,
+                   cast(sum(ifnull(quantity, 0)) as decimal(18,4)) as quantity,
+                   cast(sum(ifnull(scrap_qty, 0)) as decimal(18,4)) as scrapQty
+            from production_product_output
+            group by production_product_main_id
+        ) ppo on ppo.production_product_main_id = ppm.id
+        <where>
+            <if test="c != null">
+                <if test="c.productCategory != null and c.productCategory != ''">
+                    and p_parent.product_name like concat('%', #{c.productCategory}, '%')
+                </if>
+                <if test="c.specificationModel != null and c.specificationModel != ''">
+                    and pm.model like concat('%', #{c.specificationModel}, '%')
+                </if>
+                <if test="c.schedulingUserId != null">
+                    and pa.scheduling_user_id = #{c.schedulingUserId}
+                </if>
+                <if test="c.schedulingUserName != null and c.schedulingUserName != ''">
+                    and pa.scheduling_user_name like concat('%', #{c.schedulingUserName}, '%')
+                </if>
+                <if test="c.process != null and c.process != ''">
+                    and pa.technology_operation_name like concat('%', #{c.process}, '%')
+                </if>
+                <if test="c.entryDate != null">
+                    and date(pa.scheduling_date) = #{c.entryDate}
+                </if>
+                <if test="c.entryDateStart != null">
+                    and date(pa.scheduling_date) &gt;= #{c.entryDateStart}
+                </if>
+                <if test="c.entryDateEnd != null">
+                    and date(pa.scheduling_date) &lt;= #{c.entryDateEnd}
+                </if>
+            </if>
+        </where>
+        group by pa.scheduling_user_id,
+        pa.scheduling_user_name
+        order by wages desc,
+        pa.scheduling_user_id asc
+    </select>
+
+    <select id="selectUserAccount" resultType="com.ruoyi.production.bean.dto.UserAccountDto">
+        select ifnull(sum(finished_num), 0) as accountBalance,
+               ifnull(sum(work_hours), 0) as account
+        from production_account
+        where scheduling_user_id = #{userId}
+          and date_format(scheduling_date, '%Y-%m') = #{date}
+    </select>
+
+    <select id="selectDailyWagesStats" resultType="java.util.Map">
+        select date_format(scheduling_date, '%m-%d') as dateStr,
+               cast(ifnull(sum(finished_num), 0) as decimal(18,2)) as numberOfCompleted,
+               cast(ifnull(sum(work_hours), 0) as decimal(18,2)) as amount,
+               cast(0 as decimal(18,2)) as passRate
+        from production_account
+        where scheduling_date &gt;= #{startDate}
+          and scheduling_date &lt;= #{endDate}
+        group by date_format(scheduling_date, '%m-%d')
+        order by date_format(scheduling_date, '%m-%d')
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionBomStructureMapper.xml b/src/main/resources/mapper/production/ProductionBomStructureMapper.xml
new file mode 100644
index 0000000..c116f6f
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionBomStructureMapper.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionBomStructureMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionBomStructure">
+        <id column="id" property="id" />
+        <result column="parent_id" property="parentId" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="production_order_bom_id" property="productionOrderBomId" />
+        <result column="unit_quantity" property="unitQuantity" />
+        <result column="demanded_quantity" property="demandedQuantity" />
+        <result column="unit" property="unit" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listByBomId" resultType="com.ruoyi.production.bean.vo.ProductionBomStructureVo">
+        select pbs.*,
+               p.product_name as productName,
+               pm.product_id as productId,
+               pm.model,
+               top1.name as operationName
+        from production_bom_structure pbs
+                 left join product_model pm on pbs.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+                 left join technology_operation top1 on pbs.technology_operation_id = top1.id
+        where pbs.production_order_bom_id = #{bomId}
+        order by pbs.id
+    </select>
+
+    <select id="pickByBomId" resultType="com.ruoyi.production.bean.vo.ProductionBomStructureVo">
+        SELECT
+            pbs.*,
+            p.product_name AS productName,
+            pm.product_id AS productId,
+            pm.model,
+            top1.NAME AS operationName
+        FROM
+            production_bom_structure pbs
+                LEFT JOIN product_model pm ON pbs.product_model_id = pm.id
+                LEFT JOIN product p ON pm.product_id = p.id
+                LEFT JOIN technology_operation top1 ON pbs.technology_operation_id = top1.id
+        WHERE
+            pbs.parent_id IS NOT NULL
+          AND pbs.production_order_bom_id = #{bomId}
+        ORDER BY
+            pbs.id
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOperationMainParamMapper.xml b/src/main/resources/mapper/production/ProductionOperationMainParamMapper.xml
new file mode 100644
index 0000000..57be5b2
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOperationMainParamMapper.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOperationMainParamMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOperationMainParam">
+        <id column="id" property="id" />
+        <result column="technology_routing_operation_param_id" property="technologyRoutingOperationParamId" />
+        <result column="param_code" property="paramCode" />
+        <result column="param_name" property="paramName" />
+        <result column="param_type" property="paramType" />
+        <result column="param_format" property="paramFormat" />
+        <result column="unit" property="unit" />
+        <result column="is_required" property="isRequired" />
+        <result column="remark" property="remark" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="technology_param_id" property="technologyParamId" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="technology_operation_param_id" property="technologyOperationParamId" />
+        <result column="technology_routing_operation_id" property="technologyRoutingOperationId" />
+        <result column="standard_value" property="standardValue" />
+        <result column="value" property="value" />
+        <result column="production_order_routing_operation_param_id" property="productionOrderRoutingOperationParamId" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
new file mode 100644
index 0000000..577bcfd
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOperationTaskMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOperationTask">
+        <id column="id" property="id" />
+        <result column="production_order_routing_operation_id" property="productionOrderRoutingOperationId" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="work_order_no" property="workOrderNo" />
+        <result column="plan_start_time" property="planStartTime" />
+        <result column="plan_end_time" property="planEndTime" />
+        <result column="actual_start_time" property="actualStartTime" />
+        <result column="actual_end_time" property="actualEndTime" />
+        <result column="status" property="status" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="plan_quantity" property="planQuantity" />
+        <result column="complete_quantity" property="completeQuantity" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="pageProductionOperationTask" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo">
+        select pot.*,
+               po.nps_no as npsNo,
+               po.is_end_order as endOrder,
+               p.product_name as productName,
+               pm.model as model,
+               pm.unit as unit,
+               poro.operation_name as operationName,
+               IFNULL(scrapStat.scrapQty, 0) AS scrapQty,
+        ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus,
+        CASE
+            WHEN pot.work_order_no LIKE 'FG%' THEN '杩斿伐杩斾慨'
+            ELSE '姝e父'
+            END AS work_order_type
+        from production_operation_task pot
+                 left join production_order po on pot.production_order_id = po.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
+                 left join product p on pm.product_id = p.id
+                 left join (
+            select ppm.production_operation_task_id as taskId,
+                   sum(ifnull(ppo.scrap_qty, 0)) as scrapQty
+            from production_product_main ppm
+                     left join production_product_output ppo on ppo.production_product_main_id = ppm.id
+            group by ppm.production_operation_task_id
+        ) scrapStat on scrapStat.taskId = pot.id
+        <where>
+            <if test="c != null and c.id != null">
+                and pot.id = #{c.id}
+            </if>
+            <if test="c != null and c.npsNo != null">
+                and po.nps_no like concat('%', #{c.npsNo}, '%')
+            </if>
+            <if test="c != null and c.productionOrderId != null">
+                and pot.production_order_id = #{c.productionOrderId}
+            </if>
+            <if test="c != null and c.productionOrderRoutingOperationId != null">
+                and pot.production_order_routing_operation_id = #{c.productionOrderRoutingOperationId}
+            </if>
+            <if test="c != null and c.status != null">
+                and pot.status = #{c.status}
+            </if>
+            <if test="c != null and c.workOrderNo != null and c.workOrderNo != ''">
+                and pot.work_order_no like concat('%', #{c.workOrderNo}, '%')
+            </if>
+        </where>
+        order by pot.id desc
+    </select>
+
+    <select id="selectTaskStatisticsByDate" resultType="com.ruoyi.home.dto.ProductionTaskStatisticsDto">
+        select pot.id,
+               pot.work_order_no,
+               pot.plan_start_time as planStartTime,
+               pot.plan_end_time as planEndTime,
+               pot.actual_start_time as actualStartTime,
+               pot.actual_end_time as actualEndTime,
+               pot.plan_quantity as planQuantity,
+               ifnull(pot.complete_quantity, 0) as completeQuantity,
+               poro.operation_name as processName,
+               p.product_name as productName,
+               pm.model,
+               pm.unit,
+               po.nps_no as productOrderNpsNo
+        from production_operation_task pot
+                 left join production_order po on pot.production_order_id = po.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
+                 left join product p on pm.product_id = p.id
+        where date(pot.create_time) between #{startDate} and #{endDate}
+        order by pot.create_time desc
+    </select>
+
+    <select id="selectTaskStartStats" resultType="com.ruoyi.home.dto.ProductionTaskStatisticsDto">
+        select id,
+               actual_start_time as actualStartTime,
+               plan_quantity as planQuantity
+        from production_operation_task
+        where actual_start_time &gt;= #{startDateTime}
+          and actual_start_time &lt;= #{endDateTime}
+    </select>
+
+    <select id="calculateProductionStatistics" resultType="com.ruoyi.home.dto.processDataProductionStatisticsDto">
+        select poro.operation_name as processName,
+               sum(ifnull(ppi.input_quantity, 0)) as totalInput,
+               sum(ifnull(ppo.scrap_qty, 0)) as totalScrap,
+               sum(ifnull(ppo.quantity, 0) - ifnull(ppo.scrap_qty, 0)) as totalOutput
+        from production_product_output ppo
+                 inner join production_product_main ppm on ppo.production_product_main_id = ppm.id
+                 inner join production_operation_task pot on ppm.production_operation_task_id = pot.id
+        left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+        left join production_product_input ppi on ppi.production_product_main_id = ppm.id
+        <where>
+            <if test="startDateTime != null">
+                and ppo.create_time &gt;= #{startDateTime}
+            </if>
+            <if test="endDateTime != null">
+                and ppo.create_time &lt;= #{endDateTime}
+            </if>
+            <if test="userId != null">
+                and ppm.create_user = #{userId}
+            </if>
+            <if test="processIds != null and processIds.size() > 0">
+                and poro.technology_operation_id in
+                <foreach collection="processIds" item="id" open="(" separator="," close=")">
+                    #{id}
+                </foreach>
+            </if>
+        </where>
+        group by poro.technology_operation_id, poro.operation_name
+    </select>
+
+    <select id="getProductWorkOrderFlowCard" resultType="com.ruoyi.production.bean.dto.ProductionOperationTaskDto">
+        SELECT pot.*,
+               poro.operation_name AS processName,
+               pm.model AS model,
+               pm.unit AS unit,
+               p.product_name AS productName,
+               po.nps_no AS productOrderNpsNo,
+               ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus,
+               IFNULL(scrapStat.scrapQty, 0) AS scrapQty
+        FROM production_operation_task pot
+                 LEFT JOIN production_order po ON pot.production_order_id = po.id
+                 LEFT JOIN production_order_routing_operation poro ON pot.production_order_routing_operation_id = poro.id
+                 LEFT JOIN product_model pm ON pm.id = ifnull(poro.product_model_id, po.product_model_id)
+                 LEFT JOIN product p ON p.id = pm.product_id
+                 LEFT JOIN (
+            SELECT ppm.production_operation_task_id AS taskId,
+                   SUM(IFNULL(ppo.scrap_qty, 0)) AS scrapQty
+            FROM production_product_main ppm
+                     LEFT JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id
+            GROUP BY ppm.production_operation_task_id
+        ) scrapStat ON scrapStat.taskId = pot.id
+        WHERE pot.id = #{id}
+    </select>
+
+    <select id="getOperation" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo">
+        select poro.operation_name as operationName,
+               count(pot.id) as productionTaskCount,
+               sum(ifnull(pot.plan_quantity, 0)) as planQuantity,
+               sum(ifnull(pot.complete_quantity, 0)) as completeQuantity,
+               sum(ifnull(pot.complete_quantity, 0)) as goodQuantity,
+               sum(ifnull(outputStat.scrapQty, 0)) as scrapQty,
+               round(
+                   case
+                       when sum(ifnull(pot.plan_quantity, 0)) = 0 then 0
+                       else (sum(ifnull(pot.complete_quantity, 0)) + sum(ifnull(outputStat.scrapQty, 0)))
+                           / sum(ifnull(pot.plan_quantity, 0)) * 100
+                       end,
+                   2
+               ) as completionStatus
+        from production_operation_task pot
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join (
+            select ppm.production_operation_task_id as taskId,
+                   sum(ifnull(ppo.scrap_qty, 0)) as scrapQty
+            from production_product_main ppm
+                     left join production_product_output ppo on ppo.production_product_main_id = ppm.id
+            group by ppm.production_operation_task_id
+        ) outputStat on outputStat.taskId = pot.id
+        <where>
+            <if test="c != null and c.startDate != null">
+                and date(pot.create_time) &gt;= #{c.startDate}
+            </if>
+            <if test="c != null and c.endDate != null">
+                and date(pot.create_time) &lt;= #{c.endDate}
+            </if>
+            <if test="c != null and c.planStartTime != null">
+                and pot.plan_start_time &gt;= #{c.planStartTime}
+            </if>
+            <if test="c != null and c.planEndTime != null">
+                and pot.plan_end_time &lt;= #{c.planEndTime}
+            </if>
+            <if test="c != null and c.productionOrderId != null">
+                and pot.production_order_id = #{c.productionOrderId}
+            </if>
+            <if test="c != null and c.productionOrderRoutingOperationId != null">
+                and pot.production_order_routing_operation_id = #{c.productionOrderRoutingOperationId}
+            </if>
+            <if test="c != null and c.status != null">
+                and pot.status = #{c.status}
+            </if>
+            <if test="c != null and c.processName != null and c.processName != ''">
+                and poro.operation_name like concat('%', #{c.processName}, '%')
+            </if>
+        </where>
+        group by poro.operation_name
+        order by min(poro.drag_sort), poro.operation_name
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderBomMapper.xml b/src/main/resources/mapper/production/ProductionOrderBomMapper.xml
new file mode 100644
index 0000000..eddaa63
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderBomMapper.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOrderBomMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderBom">
+        <id column="id" property="id" />
+        <result column="parent_id" property="parentId" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="unit_quantity" property="unitQuantity" />
+        <result column="demanded_quantity" property="demandedQuantity" />
+        <result column="unit" property="unit" />
+        <result column="bom_id" property="bomId" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderMapper.xml b/src/main/resources/mapper/production/ProductionOrderMapper.xml
new file mode 100644
index 0000000..1a304ef
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderMapper.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOrderMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrder">
+        <id column="id" property="id" />
+        <result column="production_plan_ids" property="productionPlanIds" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="nps_no" property="npsNo" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="technology_routing_id" property="technologyRoutingId" />
+        <result column="quantity" property="quantity" />
+        <result column="complete_quantity" property="completeQuantity" />
+        <result column="start_time" property="startTime" />
+        <result column="end_time" property="endTime" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+        <result column="plan_complete_time" property="planCompleteTime" />
+        <result column="status" property="status" />
+    </resultMap>
+
+    <resultMap id="ProductionOrderVoResultMap" type="com.ruoyi.production.bean.vo.ProductionOrderVo" extends="BaseResultMap">
+        <result column="salesContractNo" property="salesContractNo" />
+        <result column="customerName" property="customerName" />
+        <result column="productName" property="productName" />
+        <result column="model" property="model" />
+        <result column="processRouteCode" property="processRouteCode" />
+        <result column="returned" property="returned" />
+    </resultMap>
+
+    <sql id="ProductionOrderVoColumns">
+        po.id,
+        po.production_plan_ids,
+        po.product_model_id,
+        po.nps_no,
+        po.create_time,
+        po.update_time,
+        po.technology_routing_id,
+        po.quantity,
+        po.complete_quantity,
+        po.start_time,
+        po.end_time,
+        po.create_user,
+        po.dept_id,
+        po.plan_complete_time,
+        po.status,
+        po_sales.salesContractNo,
+        po_sales.customerName,
+        p.product_name as productName,
+        pm.model as model,
+        po.is_end_order as endOrder,
+        tr.process_route_code as processRouteCode,
+        ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus,
+        tb.bom_no as bomNo,
+        pop_return.returned as returned
+    </sql>
+
+    <sql id="ProductionOrderVoFrom">
+        from production_order po
+                 left join (
+            select po2.id as orderId,
+                   group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as salesContractNo,
+                   group_concat(distinct sl2.customer_name order by sl2.customer_name separator ',') as customerName,
+                   group_concat(distinct sl2.project_name order by sl2.project_name separator ',') as projectName,
+                   min(sl2.delivery_date) as deliveryDate
+            from production_order po2
+                     left join production_plan pp2
+                               on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                     left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+            group by po2.id
+        ) po_sales on po_sales.orderId = po.id
+                 left join product_model pm on po.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+                 left join technology_routing tr on po.technology_routing_id = tr.id
+                 left join technology_bom tb on tb.id = tr.bom_id
+                 left join (
+            select production_order_id as productionOrderId,
+                   if(max(case when ifnull(is_returned, 0) = 1 then 1 else 0 end) = 1, true, false) as returned
+            from production_order_pick
+            group by production_order_id
+        ) pop_return on pop_return.productionOrderId = po.id
+    </sql>
+
+    <sql id="ProductionOrderWhere">
+        <where>
+            <if test="c != null">
+                <if test="c.id != null">
+                    and po.id = #{c.id}
+                </if>
+                <if test="c.productName != null and c.productName != ''">
+                    and p.product_name like concat('%', #{c.productName}, '%')
+                </if>
+                <if test="c.model != null and c.model != ''">
+                    and pm.model like concat('%', #{c.model}, '%')
+                </if>
+                <if test="c.productModelId != null">
+                    and po.product_model_id = #{c.productModelId}
+                </if>
+                <if test="c.technologyRoutingId != null">
+                    and po.technology_routing_id = #{c.technologyRoutingId}
+                </if>
+                <if test="c.status != null">
+                    and po.status = #{c.status}
+                </if>
+                <if test="c.createUser != null">
+                    and po.create_user = #{c.createUser}
+                </if>
+                <if test="c.deptId != null">
+                    and po.dept_id = #{c.deptId}
+                </if>
+                <if test="c.npsNo != null and c.npsNo != ''">
+                    and po.nps_no like concat('%', #{c.npsNo}, '%')
+                </if>
+                <if test="c.productionPlanIds != null and c.productionPlanIds != ''">
+                    and po.production_plan_ids like concat('%', #{c.productionPlanIds}, '%')
+                </if>
+                <if test="c.planCompleteTime != null">
+                    and po.plan_complete_time = #{c.planCompleteTime}
+                </if>
+                <if test="c.startTime != null">
+                    and po.start_time &gt;= #{c.startTime}
+                </if>
+                <if test="c.endTime != null">
+                    and po.end_time &lt;= #{c.endTime}
+                </if>
+            </if>
+        </where>
+    </sql>
+
+    <select id="pageProductionOrder" resultMap="ProductionOrderVoResultMap">
+        select
+        <include refid="ProductionOrderVoColumns" />
+        <include refid="ProductionOrderVoFrom" />
+        <include refid="ProductionOrderWhere" />
+        order by po.id desc
+    </select>
+
+    <select id="listProductionOrder" resultMap="ProductionOrderVoResultMap">
+        select
+        <include refid="ProductionOrderVoColumns" />
+        <include refid="ProductionOrderVoFrom" />
+        <include refid="ProductionOrderWhere" />
+        order by po.id desc
+    </select>
+
+    <select id="getProductionOrderInfo" resultMap="ProductionOrderVoResultMap">
+        select
+        <include refid="ProductionOrderVoColumns" />
+        <include refid="ProductionOrderVoFrom" />
+        where po.id = #{id}
+        limit 1
+    </select>
+
+    <select id="selectProgressOrders" resultType="com.ruoyi.home.dto.ProductionProgressOrderDto">
+        select po.nps_no,
+               po_sales.salesContractNo,
+               po_sales.projectName,
+               po_sales.customerName,
+               p.product_name as productCategory,
+               pm.model as specificationModel,
+               tr.process_route_code as processRouteCode,
+               po.quantity,
+               ifnull(po.complete_quantity, 0) as completeQuantity,
+               round(ifnull(po.complete_quantity, 0) / nullif(po.quantity, 0) * 100, 2) as completionStatus,
+               tb.bom_no,
+               datediff(po_sales.deliveryDate, curdate()) as deliveryDaysDiff,
+               po_sales.deliveryDate as deliveryDate,
+               false as isFh
+        from production_order po
+                 left join (
+            select po2.id as orderId,
+                   group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as salesContractNo,
+                   group_concat(distinct sl2.customer_name order by sl2.customer_name separator ',') as customerName,
+                   group_concat(distinct sl2.project_name order by sl2.project_name separator ',') as projectName,
+                   min(sl2.delivery_date) as deliveryDate
+            from production_order po2
+                     left join production_plan pp2
+                               on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                     left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+            group by po2.id
+        ) po_sales on po_sales.orderId = po.id
+                 left join product_model pm on po.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+                 left join technology_routing tr on po.technology_routing_id = tr.id
+                 left join technology_bom tb on tr.bom_id = tb.id
+        where po.create_time between #{startTime} and #{endTime}
+        order by po.create_time desc
+    </select>
+
+    <select id="countCreated" resultType="java.lang.Integer">
+        select count(1)
+        from production_order
+        where create_time &gt;= #{startDate}
+          and create_time &lt;= #{endDate}
+    </select>
+
+    <select id="countCompleted" resultType="java.lang.Integer">
+        select count(1)
+        from production_order
+        where end_time &gt;= #{startDate}
+          and end_time &lt;= #{endDate}
+          and ifnull(complete_quantity, 0) &gt;= quantity
+    </select>
+
+    <select id="countPending" resultType="java.lang.Integer">
+        select count(1)
+        from production_order
+        where create_time &gt;= #{startDate}
+          and create_time &lt;= #{endDate}
+          and ifnull(complete_quantity, 0) &lt; quantity
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderPickMapper.xml b/src/main/resources/mapper/production/ProductionOrderPickMapper.xml
new file mode 100644
index 0000000..8b0a0d7
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderPickMapper.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOrderPickMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderPick">
+        <id column="id" property="id" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="quantity" property="quantity" />
+        <result column="batch_no" property="batchNo" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="remark" property="remark" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+        <result column="operation_name" property="operationName" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="demanded_quantity" property="demandedQuantity" />
+        <result column="feeding_qty" property="feedingQty" />
+        <result column="return_qty" property="returnQty" />
+        <result column="actual_qty" property="actualQty" />
+        <result column="is_returned" property="returned" />
+        <result column="is_bom" property="bom" />
+    </resultMap>
+
+    <select id="listPickedDetailByOrderId" resultType="com.ruoyi.production.bean.vo.ProductionOrderPickVo">
+        select pop.*,
+               pop.is_bom as bom,
+               pop.is_returned as returned,
+               pop.quantity as pickQuantity,
+               p.product_name as productName,
+               pm.model as model,
+               pm.unit as unit
+        from production_order_pick pop
+                 left join product_model pm on pop.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+        where pop.production_order_id = #{productionOrderId}
+        order by pop.create_time desc, pop.id desc
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml b/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
new file mode 100644
index 0000000..a80fd02
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderPickRecordMapper.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOrderPickRecordMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderPickRecord">
+        <id column="id" property="id" />
+        <result column="pick_id" property="pickId" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="production_operation_task_id" property="productionOperationTaskId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="batch_no" property="batchNo" />
+        <result column="pick_quantity" property="pickQuantity" />
+        <result column="before_quantity" property="beforeQuantity" />
+        <result column="after_quantity" property="afterQuantity" />
+        <result column="pick_type" property="pickType" />
+        <result column="remark" property="remark" />
+        <result column="feeding_reason" property="feedingReason" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listPickedDetailByOrderId" resultType="com.ruoyi.production.bean.vo.ProductionOrderPickVo">
+        select popr.*,
+               poro.operation_name as operationName,
+               p.product_name as productName,
+               pm.model as model,
+               pm.unit as unit
+        from production_order_pick_record popr
+                 left join production_operation_task pot on popr.production_operation_task_id = pot.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on popr.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+        where popr.production_order_id = #{productionOrderId}
+        order by popr.create_time desc, popr.id desc
+    </select>
+
+    <select id="listFeedingRecord" resultType="com.ruoyi.production.bean.vo.ProductionOrderPickRecordVo">
+        select popr.*,
+               poro.operation_name as operationName,
+               p.product_name as productName,
+               pm.model as model,
+               pm.unit as unit,
+               coalesce(su.nick_name, su.user_name) as supplementUserName,
+               popr.create_time as supplementTime
+        from production_order_pick_record popr
+                 left join production_operation_task pot on popr.production_operation_task_id = pot.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on popr.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+                 left join sys_user su on popr.create_user = su.user_id
+        where popr.production_order_id = #{productionOrderId}
+          and popr.pick_id = #{pickId}
+          and popr.pick_type = 2
+        order by popr.create_time desc, popr.id desc
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml b/src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml
new file mode 100644
index 0000000..40be168
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderRoutingMapper.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOrderRoutingMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderRouting">
+        <id column="id" property="id" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="description" property="description" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="technology_routing_id" property="technologyRoutingId" />
+        <result column="process_route_code" property="processRouteCode" />
+        <result column="bom_id" property="bomId" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderRoutingOperationMapper.xml b/src/main/resources/mapper/production/ProductionOrderRoutingOperationMapper.xml
new file mode 100644
index 0000000..55739db
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderRoutingOperationMapper.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderRoutingOperation">
+        <id column="id" property="id" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="technology_routing_operation_id" property="technologyRoutingOperationId" />
+        <result column="order_routing_id" property="orderRoutingId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="drag_sort" property="dragSort" />
+        <result column="is_quality" property="isQuality" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <resultMap id="OperationVoResultMap" type="com.ruoyi.production.bean.vo.ProductionOrderRoutingOperationVo" extends="BaseResultMap">
+        <result column="technologyOperationId" property="technologyOperationId" />
+        <result column="productionOrderRoutingOperationId" property="productionOrderRoutingOperationId" />
+        <result column="productName" property="productName" />
+        <result column="model" property="model" />
+        <result column="unit" property="unit" />
+    </resultMap>
+
+    <select id="selectVoListByOrderId" resultMap="OperationVoResultMap">
+        SELECT
+        poro.id AS productionOrderRoutingOperationId,
+        poro.*,
+        too.id AS technologyOperationId,
+        p.product_name AS productName,
+        pm.model AS model,
+        pm.unit AS unit
+        FROM production_order_routing_operation poro
+        LEFT JOIN technology_operation too ON poro.technology_operation_id = too.id
+        LEFT JOIN product_model pm ON poro.product_model_id = pm.id
+        LEFT JOIN product p ON pm.product_id = p.id
+        WHERE poro.production_order_id = #{orderId}
+        ORDER BY poro.drag_sort ASC, poro.id ASC
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionOrderRoutingOperationParamMapper.xml b/src/main/resources/mapper/production/ProductionOrderRoutingOperationParamMapper.xml
new file mode 100644
index 0000000..ce337aa
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionOrderRoutingOperationParamMapper.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionOrderRoutingOperationParamMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrderRoutingOperationParam">
+        <id column="id" property="id" />
+        <result column="production_order_id" property="productionOrderId" />
+        <result column="technology_routing_operation_param_id" property="technologyRoutingOperationParamId" />
+        <result column="param_code" property="paramCode" />
+        <result column="param_name" property="paramName" />
+        <result column="param_type" property="paramType" />
+        <result column="param_format" property="paramFormat" />
+        <result column="unit" property="unit" />
+        <result column="is_required" property="isRequired" />
+        <result column="remark" property="remark" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="param_id" property="paramId" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="technology_operation_param_id" property="technologyOperationParamId" />
+        <result column="technology_routing_operation_id" property="technologyRoutingOperationId" />
+        <result column="standard_value" property="standardValue" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionPlanMapper.xml b/src/main/resources/mapper/production/ProductionPlanMapper.xml
new file mode 100644
index 0000000..a389d32
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionPlanMapper.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.production.mapper.ProductionPlanMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionPlan">
+        <id column="id" property="id"/>
+        <result column="mps_no" property="mpsNo"/>
+        <result column="required_date" property="requiredDate"/>
+        <result column="remark" property="remark"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="create_user" property="createUser"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="product_model_id" property="productModelId"/>
+        <result column="qty_required" property="qtyRequired"/>
+        <result column="issued" property="issued"/>
+        <result column="source" property="source"/>
+        <result column="promised_delivery_date" property="promisedDeliveryDate"/>
+    </resultMap>
+
+    <select id="listPage" resultType="com.ruoyi.production.bean.vo.ProductionPlanVo">
+        SELECT
+        pp.*,
+        pm.model,
+        p.id as productId,
+        p.product_name AS productName,
+        pm.unit,
+        sl.sales_contract_no,
+        sl.customer_name,
+        sl.project_name
+        FROM production_plan pp
+        left join product_model pm on pp.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        left join sales_ledger sl on pp.sales_ledger_id = sl.id
+        <where>
+            <if test="c != null">
+                <if test="c.id != null">
+                    and pp.id = #{c.id}
+                </if>
+                <if test="c.productName != null and c.productName != ''">
+                    and p.product_name like concat('%', #{c.productName}, '%')
+                </if>
+                <if test="c.model != null and c.model != ''">
+                    and pm.model like concat('%', #{c.model}, '%')
+                </if>
+                <if test="c.status != null">
+                    and pp.status = #{c.status}
+                </if>
+                <if test="c.mpsNo != null and c.mpsNo != ''">
+                    and pp.mps_no like concat('%', #{c.mpsNo}, '%')
+                </if>
+                <if test="c.requiredDateStart != null and c.requiredDateEnd != null">
+                    and pp.required_date between #{c.requiredDateStart} and #{c.requiredDateEnd}
+                </if>
+            </if>
+        </where>
+        ORDER BY COALESCE(pp.id) DESC
+    </select>
+
+    <select id="selectWithMaterialByIds" resultType="com.ruoyi.production.bean.dto.ProductionPlanDto">
+        SELECT
+        pp.*,
+        pm.model,
+        p.product_name AS productName,
+        pm.unit
+        FROM production_plan pp
+        LEFT JOIN product_model pm ON pp.product_model_id = pm.id
+        LEFT JOIN product p ON pm.product_id = p.id
+        WHERE pp.id IN
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+        ORDER BY pp.id ASC
+    </select>
+    <select id="selectProductionPlanDtoById" resultType="com.ruoyi.production.bean.dto.ProductionPlanDto">
+        SELECT
+        pp.*,
+        pm.model,
+        p.product_name AS productName,
+        pm.unit
+        FROM production_plan pp
+        left join product_model pm on pp.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        WHERE pp.id = #{productionPlanId}
+    </select>
+    <select id="getSource" resultType="com.ruoyi.production.bean.vo.ProductionPlanVo">
+         SELECT
+        pp.*,
+        pm.model,
+        p.product_name AS productName,
+        pm.unit,
+        sl.sales_contract_no,
+        sl.customer_name,
+        sl.project_name
+        FROM production_plan pp
+        LEFT JOIN product_model pm ON pp.product_model_id = pm.id
+        LEFT JOIN product p ON pm.product_id = p.id
+        left join sales_ledger sl on pp.sales_ledger_id = sl.id
+        WHERE pp.id IN
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+        ORDER BY pp.id ASC
+    </select>
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionProductInputMapper.xml b/src/main/resources/mapper/production/ProductionProductInputMapper.xml
index 65e2b96..fe88ae3 100644
--- a/src/main/resources/mapper/production/ProductionProductInputMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductInputMapper.xml
@@ -1,78 +1,46 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.production.mapper.ProductionProductInputMapper">
 
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProductionProductInput">
-        <id property="id" column="id"/>
-        <result property="productMainId" column="product_main_id"/>
-        <result property="productModelId" column="product_model_id"/>
-        <result property="quantity" column="quantity"/>
-        <result property="tenantId" column="tenant_id"/>
-        <result property="createTime" column="create_time"/>
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionProductInput">
+        <id column="id" property="id" />
+        <result column="input_quantity" property="inputQuantity" />
+        <result column="production_product_main_id" property="productionProductMainId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="update_time" property="updateTime" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
     </resultMap>
-    <select id="listPageProductionProductInputDto" resultType="com.ruoyi.production.dto.ProductionProductInputDto">
+
+    <select id="listPageProductionProductInputDto" resultType="com.ruoyi.production.bean.dto.ProductionProductInputDto">
         select ppi.*,
-        pm.model as model,
-        ppm.product_no as productNo,
-        p.product_name,
-        pm.unit
-        from
-        production_product_input ppi
-        left join production_product_main ppm on ppm.id = ppi.product_main_id
-        left join product_model pm on pm.id = ppi.product_model_id
-        left join product p on p.id = pm.product_id
+               ppm.product_no as productNo,
+               pm.model,
+               p.product_name as productName,
+               pm.unit
+        from production_product_input ppi
+                 left join production_product_main ppm on ppi.production_product_main_id = ppm.id
+                 left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+                 left join production_order po on pot.production_order_id = po.id
+                 left join product_model pm on ppi.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
         <where>
-            <if test="c.productMainId != null and c.productMainId > 0">
+            <if test="c.productNo != null and c.productNo != ''">
+                and ppm.product_no like concat('%', #{c.productNo}, '%')
+            </if>
+            <if test="c.model != null and c.model != ''">
+                and pm.model like concat('%', #{c.model}, '%')
+            </if>
+            <if test="c.productName != null and c.productName != ''">
+                and p.product_name like concat('%', #{c.productName}, '%')
+            </if>
+            <if test="c.productMainId != null and c.productMainId != ''">
                 and ppm.id = #{c.productMainId}
             </if>
         </where>
-        order by ppi.id
+        order by ppi.create_time desc
     </select>
 
-    <delete id="deleteByProductMainIds" parameterType="java.util.List">
-        DELETE FROM production_product_input
-        WHERE product_main_id IN
-        <foreach collection="productMainIds" item="id" open="(" separator="," close=")">
-            #{id}
-        </foreach>
-
-    </delete>
-
-    <select id="selectInputStats" resultType="java.util.Map">
-        SELECT
-        DATE_FORMAT(ppi.create_time, '%Y-%m-%d') AS date,
-        -- 鎶ュ伐鏁伴噺 * 鏈�灏忕郴鏁�
-        SUM(ppi.quantity * IFNULL(distinct_ps.unit_quantity, 1)) AS quantity
-        FROM production_product_input ppi
-        INNER JOIN production_product_main ppm ON ppm.id = ppi.product_main_id
-        INNER JOIN product_process_route_item ppri ON ppri.id = ppm.product_process_route_item_id
-        INNER JOIN product_process_route ppr ON ppr.id = ppri.product_route_id
-        INNER JOIN product_model pm ON pm.id = ppi.product_model_id
-        INNER JOIN (
-        SELECT
-        bom_id,
-        process_id,
-        product_model_id,
-        CAST(SUBSTRING_INDEX(GROUP_CONCAT(unit_quantity ORDER BY id ASC), ',', 1) AS DECIMAL(16, 4)) AS unit_quantity
-        FROM product_structure
-        GROUP BY bom_id, process_id, product_model_id
-        ) distinct_ps ON distinct_ps.bom_id = ppr.bom_id
-        AND distinct_ps.process_id = ppri.process_id
-        AND distinct_ps.product_model_id = ppi.product_model_id
-        <where>
-            <if test="startDate != null">
-                AND ppi.create_time &gt;= #{startDate}
-            </if>
-            <if test="endDate != null">
-                AND ppi.create_time &lt;= #{endDate}
-            </if>
-        </where>
-        GROUP BY
-        DATE_FORMAT(ppi.create_time, '%Y-%m-%d'),
-        pm.id,
-        pm.model
-        ORDER BY
-        date DESC,
-        pm.id ASC
-    </select>
 </mapper>
diff --git a/src/main/resources/mapper/production/ProductionProductMainMapper.xml b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
index a122e90..5a78a5b 100644
--- a/src/main/resources/mapper/production/ProductionProductMainMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -1,121 +1,162 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.production.mapper.ProductionProductMainMapper">
 
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProductionProductMain">
-        <id property="id" column="id"/>
-        <result property="productNo" column="product_no"/>
-        <result property="userId" column="user_id"/>
-        <result property="workOrderId" column="work_order_id"/>
-        <result property="tenantId" column="tenant_id"/>
-        <result property="createTime" column="create_time"/>
-        <result property="status" column="status"/>
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionProductMain">
+        <id column="id" property="id" />
+        <result column="product_no" property="productNo" />
+        <result column="production_operation_task_id" property="productionOperationTaskId" />
+        <result column="dept_id" property="deptId" />
+        <result column="update_time" property="updateTime" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
     </resultMap>
 
-    <select id="listPageProductionProductMainDto" resultType="com.ruoyi.production.dto.ProductionProductMainDto">
+    <select id="listPageProductionProductMainDto" resultType="com.ruoyi.production.bean.dto.ProductionProductMainDto">
         select ppm.*,
-        pwo.work_order_no as workOrderNo,
-        pwo.status as workOrderStatus,
-        u.nick_name as nickName,
-        p.product_name as productName,
-        pp.name as process,
-        pm.model as productModelName,
-        ppo.quantity,
-        ppo.scrap_qty,
-        pm.unit,
-        sl.sales_contract_no salesContractNo
-        from
-        production_product_main ppm
-        left join product_work_order pwo on pwo.id = ppm.work_order_id
-        left join product_process_route_item ppri on ppri.id = pwo.product_process_route_item_id
-        left join product_process pp on pp.id = ppri.process_id
-        left join product_order po on po.id = pwo.product_order_id
-        left join production_product_output ppo on ppm.id = ppo.product_main_id
-        left join product_model pm on pm.id = ppo.product_model_id
-        left join product p on p.id = pm.product_id
-        left join sales_ledger sl on sl.id = po.sales_ledger_id
-        left join sys_user u on u.user_id = ppm.user_id
+               pot.work_order_no as workOrderNo,
+               case pot.status
+                   when 1 then '寰呯‘璁�'
+                   when 2 then '寰呯敓浜�'
+                   when 3 then '鐢熶骇涓�'
+                   when 4 then '宸茬敓浜�'
+                   else '鏈煡'
+                   end as workOrderStatus,
+               su.nick_name as nickName,
+               ifnull(ppo.quantity, 0) as quantity,
+               ifnull(ppo.scrap_qty, 0) as scrapQty,
+               p.product_name as productName,
+               pm.model as productModelName,
+               pm.unit,
+               po_sales.salesContractNo,
+               date(ppm.create_time) as schedulingDate,
+               su.nick_name as schedulingUserName,
+               po_sales.customerName,
+               poro.operation_name as process
+        from production_product_main ppm
+                 left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+                 left join production_order po on pot.production_order_id = po.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join (
+            select po2.id as orderId,
+                   group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as salesContractNo,
+                   group_concat(distinct sl2.customer_name order by sl2.customer_name separator ',') as customerName
+            from production_order po2
+                     left join production_plan pp2
+                               on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                     left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+            group by po2.id
+        ) po_sales on po_sales.orderId = po.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
+                 left join product p on pm.product_id = p.id
+                 left join sys_user su on ppm.create_user = su.user_id
+                 left join production_product_output ppo on ppo.production_product_main_id = ppm.id
         <where>
-            <if test="c.nickName != null and c.nickName != ''">
-                and u.nick_name like concat('%',#{c.nickName},'%')
+            <if test="c.productNo != null and c.productNo != ''">
+                and ppm.product_no like concat('%', #{c.productNo}, '%')
             </if>
             <if test="c.workOrderNo != null and c.workOrderNo != ''">
-                and pwo.work_order_no like concat('%',#{c.workOrderNo},'%')
+                and pot.work_order_no like concat('%', #{c.workOrderNo}, '%')
             </if>
-            <if test="c.workOrderStatus != null and c.workOrderStatus != ''">
-                and pwo.status = #{c.workOrderStatus}
+            <if test="c.salesContractNo != null and c.salesContractNo != ''">
+                and po_sales.salesContractNo like concat('%', #{c.salesContractNo}, '%')
             </if>
-            <if test="c.status != null and c.status != ''">
-                and ppm.status = #{c.status}
+            <if test="c.customerName != null and c.customerName != ''">
+                and po_sales.customerName like concat('%', #{c.customerName}, '%')
+            </if>
+            <if test="c.productName != null and c.productName != ''">
+                and p.product_name like concat('%', #{c.productName}, '%')
+            </if>
+            <if test="c.productModelName != null and c.productModelName != ''">
+                and pm.model like concat('%', #{c.productModelName}, '%')
+            </if>
+            <if test="c.process != null and c.process != ''">
+                and poro.operation_name like concat('%', #{c.process}, '%')
+            </if>
+            <if test="c.schedulingDate != null">
+                and date(ppm.create_time) = #{c.schedulingDate}
+            </if>
+            <if test="c.productMainId != null">
+                and ppm.id = #{c.productMainId}
             </if>
         </where>
-        order by ppm.id
+        order by ppm.create_time desc
+    </select>
 
+    <select id="getOrderByMainId" resultType="com.ruoyi.production.pojo.ProductionOrder">
+        select null
     </select>
-    <select id="getOrderByMainId" resultType="com.ruoyi.production.pojo.ProductOrder">
-        select po.*
-        from product_order po
-                 left join product_work_order pwo on po.id = pwo.product_order_id
-                 left join production_product_main pm on work_order_id = pwo.id
-        where pm.id = #{productMainId}
-    </select>
-    <select id="listProductionDetails" resultType="com.ruoyi.production.dto.ProductionProductMainDto">
-        SELECT
-        slpa.scheduling_date,
-        slpa.scheduling_user_name,
-        sl.sales_contract_no,
-        sl.customer_name,
-        p.product_name,
-        pm.model as product_model_name,
-        pm.unit,
-        slpa.process,
-        ppo.quantity,
-        slpa.work_hours,
-        slpa.work_hours * slpa.finished_num AS wages
-        FROM
-        production_product_main ppm
-        LEFT JOIN sales_ledger_production_accounting slpa ON slpa.product_main_id = ppm.id
-        LEFT JOIN production_product_output ppo ON ppm.id = ppo.product_main_id
-        LEFT JOIN product_work_order pwo ON pwo.id = ppm.work_order_id
-        LEFT JOIN product_order po ON po.id = pwo.product_order_id
-        LEFT JOIN process_route pr ON pr.id = po.route_id
-        LEFT JOIN product_model pm ON po.product_model_id = pm.id
-        LEFT JOIN product p ON p.id = pm.product_id
-        LEFT JOIN sales_ledger sl ON po.sales_ledger_id = sl.id
+
+    <select id="listProductionDetails" resultType="com.ruoyi.production.bean.dto.ProductionProductMainDto">
+        select ppm.*,
+               pot.work_order_no as workOrderNo,
+               p.product_name as productName,
+               pm.model as productModelName,
+               pm.unit,
+               pa.technology_operation_name as process,
+               ifnull(ppo.quantity, 0) as quantity,
+               ifnull(ppo.scrap_qty, 0) as scrapQty,
+               date(pa.scheduling_date) as schedulingDate,
+               pa.scheduling_user_name as schedulingUserName,
+               cast(ifnull(pa.work_hours, 0) as decimal(18,4)) as workHours,
+               cast(
+                   ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) *
+                   case
+                       when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$'
+                       then cast(substring_index(pm.model, '*', -1) as decimal(18,4))
+                       else 1
+                   end
+                   as decimal(18,4)
+               ) as wages
+        from production_account pa
+                 left join production_product_main ppm on ppm.id = pa.production_product_main_id
+                 left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+                 left join production_order po on pot.production_order_id = po.id
+                 left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id
+                 left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id)
+                 left join product p on pm.product_id = p.id
+                 left join product p_parent on p_parent.id = p.parent_id
+                 left join production_product_output ppo on ppo.production_product_main_id = ppm.id
         <where>
-            <if test="ew.schedulingUserName != null and ew.schedulingUserName !=''">
-                and slpa.scheduling_user_name = #{ew.schedulingUserName}
-            </if>
-            <if test="ew.entryDate != null " >
-                and slpa.scheduling_date >= #{ew.entryDate}
-                and slpa.scheduling_date &lt; DATE_ADD(#{ew.entryDate}, INTERVAL 1 DAY)
-            </if>
-            <if test="ew.entryDateStart != null and ew.entryDateEnd != null" >
-                and slpa.scheduling_date >= #{ew.entryDateStart}
-                and slpa.scheduling_date &lt; date_add(#{ew.entryDateEnd}, INTERVAL 1 DAY)
+            <if test="c != null">
+                <if test="c.productCategory != null and c.productCategory != ''">
+                    and p_parent.product_name like concat('%', #{c.productCategory}, '%')
+                </if>
+                <if test="c.specificationModel != null and c.specificationModel != ''">
+                    and pm.model like concat('%', #{c.specificationModel}, '%')
+                </if>
+                <if test="c.schedulingUserId != null">
+                    and pa.scheduling_user_id = #{c.schedulingUserId}
+                </if>
+                <if test="c.schedulingUserName != null and c.schedulingUserName != ''">
+                    and pa.scheduling_user_name like concat('%', #{c.schedulingUserName}, '%')
+                </if>
+                <if test="c.process != null and c.process != ''">
+                    and pa.technology_operation_name like concat('%', #{c.process}, '%')
+                </if>
+                <if test="c.entryDate != null">
+                    and date(pa.scheduling_date) = #{c.entryDate}
+                </if>
+                <if test="c.entryDateStart != null">
+                    and date(pa.scheduling_date) &gt;= #{c.entryDateStart}
+                </if>
+                <if test="c.entryDateEnd != null">
+                    and date(pa.scheduling_date) &lt;= #{c.entryDateEnd}
+                </if>
             </if>
         </where>
+        order by pa.scheduling_date desc, pa.id desc
     </select>
+
     <select id="listMain" resultType="java.lang.Long">
-        SELECT ppm.id FROM production_product_main ppm
-            left join product_work_order pwo on pwo.id = ppm.work_order_id
-                  left join product_order po on po.id = pwo.product_order_id
-                  left join sales_ledger sl on sl.id = po.sales_ledger_id
-        <where>
-            <if test="idList != null and idList.size() > 0">
-                and sl.id in
-                <foreach item="id" collection="idList" open="(" separator="," close=")">
-                    #{id}
-                </foreach>
-            </if>
-        </where>
-    </select>
-
-    <delete id="deleteByWorkOrderIds" parameterType="java.util.List">
-        DELETE FROM production_product_main
-        WHERE work_order_id IN
-        <foreach collection="workOrderIds" item="id" open="(" separator="," close=")">
+        select id
+        from production_product_main
+        where production_operation_task_id in
+        <foreach collection="list" item="id" open="(" separator="," close=")">
             #{id}
         </foreach>
-    </delete>
+    </select>
+
 </mapper>
diff --git a/src/main/resources/mapper/production/ProductionProductOutputMapper.xml b/src/main/resources/mapper/production/ProductionProductOutputMapper.xml
index 3b44135..f31ca01 100644
--- a/src/main/resources/mapper/production/ProductionProductOutputMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductOutputMapper.xml
@@ -1,61 +1,61 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.production.mapper.ProductionProductOutputMapper">
 
-    <resultMap id="basicMap" type="com.ruoyi.production.pojo.ProductionProductOutput">
-        <id property="id" column="id"/>
-        <result property="productMainId" column="product_main_id"/>
-        <result property="productModelId" column="product_model_id"/>
-        <result property="quantity" column="quantity"/>
-        <result property="tenantId" column="tenant_id"/>
-        <result property="createTime" column="create_time"/>
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionProductOutput">
+        <id column="id" property="id" />
+        <result column="production_product_main_id" property="productionProductMainId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="quantity" property="quantity" />
+        <result column="scrap_qty" property="scrapQty" />
+        <result column="update_time" property="updateTime" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
     </resultMap>
 
-    <select id="listPageProductionProductOutputDto" resultType="com.ruoyi.production.dto.ProductionProductOutputDto">
+    <select id="listPageProductionProductOutputDto" resultType="com.ruoyi.production.bean.dto.ProductionProductOutputDto">
         select ppo.*,
-        pm.model as model,
-        ppm.product_no as productNo
-        from
-        production_product_output ppo
-        left join production_product_main ppm on ppm.id = ppo.product_main_id
-        left join product_model pm on pm.id = ppo.product_model_id
+               ppm.product_no as productNo,
+               pm.model
+        from production_product_output ppo
+                 left join production_product_main ppm on ppo.production_product_main_id = ppm.id
+                 left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+                 left join production_order po on pot.production_order_id = po.id
+                 left join product_model pm on ppo.product_model_id = pm.id
         <where>
-            <if test="c.productMainId != null and c.productMainId > 0">
-                and ppm.id = #{c.productMainId}
+            <if test="c.productNo != null and c.productNo != ''">
+                and ppm.product_no like concat('%', #{c.productNo}, '%')
+            </if>
+            <if test="c.model != null and c.model != ''">
+                and pm.model like concat('%', #{c.model}, '%')
             </if>
         </where>
-        order by ppo.id
+        order by ppo.create_time desc
     </select>
 
-    <delete id="deleteByProductMainIds" parameterType="java.util.List">
-        DELETE FROM production_product_output
-        WHERE product_main_id IN
-        <foreach collection="productMainIds" item="id" open="(" separator="," close=")">
-            #{id}
-        </foreach>
-    </delete>
-    <select id="selectOutputStats" resultType="com.ruoyi.production.dto.ProductionProductOutputDto">
-        SELECT
-            create_time,
-            quantity,
-            scrap_qty
-        FROM
-            production_product_output
-        WHERE
-            create_time &gt;= #{startDate}
-            AND create_time &lt;= #{endDate}
+    <select id="selectOutputStats" resultType="com.ruoyi.production.bean.dto.ProductionProductOutputDto">
+        select id,
+               production_product_main_id as productionProductMainId,
+               product_model_id as productModelId,
+               quantity,
+               scrap_qty as scrapQty,
+               create_time as createTime
+        from production_product_output
+        where create_time &gt;= #{startDate}
+          and create_time &lt;= #{endDate}
     </select>
 
     <select id="selectDailyOutputStats" resultType="java.util.Map">
-        SELECT
-            DATE_FORMAT(create_time, '%Y-%m-%d') as date,
-            SUM(quantity-scrap_qty) as quantity
-        FROM
-            production_product_output
-        WHERE
-            create_time &gt;= #{startDate}
-            AND create_time &lt;= #{endDate}
-        GROUP BY
-            DATE_FORMAT(create_time, '%Y-%m-%d')
+        select date(create_time) as statDate,
+               sum(ifnull(quantity, 0)) as quantity,
+               sum(ifnull(scrap_qty, 0)) as scrapQty
+        from production_product_output
+        where create_time &gt;= #{startDate}
+          and create_time &lt;= #{endDate}
+        group by date(create_time)
+        order by statDate asc
     </select>
+
 </mapper>
diff --git a/src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml b/src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml
deleted file mode 100644
index d9ddde7..0000000
--- a/src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.SalesLedgerProductionAccountingMapper">
-
-    <select id="listPage" resultType="com.ruoyi.production.dto.SalesLedgerProductionAccountingDto">
-        SELECT
-        t4.id,
-        t4.finished_num * t4.work_hours as wages,
-        t4.scheduling_user_id,
-        t4.scheduling_user_name,
-        t4.scheduling_date,
-        t4.finished_num,
-        t4.work_hours,
-        t4.process,
-        T1.sales_contract_no,
-        T1.customer_contract_no,
-        T1.project_name,
-        T1.customer_name,
-        t3.product_category,
-        t3.specification_model,
-        t3.unit
-        FROM
-        sales_ledger_production_accounting t4
-        LEFT JOIN sales_ledger T1 ON T1.id = t4.sales_ledger_id
-        left join sales_ledger_product t3 on t4.sales_ledger_product_id = t3.id and slp.type = 1
-        <where>
-            t3.type = 1
-            <if test="salesLedgerDto.schedulingUserName != null and salesLedgerDto.schedulingUserName != '' ">
-                AND  t4.scheduling_user_name LIKE CONCAT('%',#{salesLedgerDto.schedulingUserName},'%')
-            </if>
-            <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
-                AND  T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
-            </if>
-            <if test="salesLedgerDto.customerContractNo != null and salesLedgerDto.customerContractNo !='' ">
-                AND  T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.salesContractNo != null and salesLedgerDto.salesContractNo != '' ">
-                AND  T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.projectName != null and salesLedgerDto.projectName != '' ">
-                AND T1.project_name LIKE CONCAT('%',#{salesLedgerDto.projectName},'%')
-            </if>
-            <if test="salesLedgerDto.entryDateStart != null and salesLedgerDto.entryDateStart != '' ">
-                AND t4.scheduling_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
-            </if>
-            <if test="salesLedgerDto.entryDateEnd != null and salesLedgerDto.entryDateEnd != '' ">
-                AND  t4.scheduling_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
-            </if>
-        </where>
-        group by t4.id
-        order by t4.scheduling_date desc
-    </select>
-    <select id="pageProductionAccounting"
-            resultType="com.ruoyi.production.dto.SalesLedgerProductionAccountingDto">
-        SELECT
-        slpa.scheduling_user_id,
-        slpa.scheduling_user_name,
-        sum(ppout.quantity) as output_num,
-        sum(slpa.finished_num * work_hours) as wages,
-        CONCAT(
-        ROUND(
-        CASE
-        WHEN SUM(ppout.quantity) = 0 OR SUM(ppout.quantity) IS NULL THEN 0
-        ELSE SUM(slpa.finished_num) * 100.0 / SUM(ppout.quantity)
-        END,
-        2
-        ),
-        '%'
-        ) as output_rate
-        FROM sales_ledger_production_accounting slpa
-        LEFT JOIN production_product_main ppm ON slpa.product_main_id = ppm.id
-        LEFT JOIN production_product_output ppout ON ppm.id = ppout.product_main_id
-        <where>
-            <if test="ew.schedulingUserName != null and ew.schedulingUserName !=''">
-                and slpa.scheduling_user_name = #{ew.schedulingUserName}
-            </if>
-            <if test="ew.entryDate != null ">
-                and slpa.scheduling_date >= #{ew.entryDate}
-                and slpa.scheduling_date &lt; DATE_ADD(DATE(#{ew.entryDate}), INTERVAL 1 DAY)
-            </if>
-            <if test="ew.entryDateStart != null and ew.entryDateEnd != null">
-                and slpa.scheduling_date >= #{ew.entryDateStart}
-                and slpa.scheduling_date &lt; DATE_ADD(DATE(#{ew.entryDateEnd}), INTERVAL 1 DAY)
-            </if>
-
-        </where>
-        GROUP BY slpa.scheduling_user_name
-
-    </select>
-
-    <select id="selectDailyWagesStats" resultType="java.util.Map">
-        SELECT DATE(ppout.create_time)                                                         AS dateStr,
-               SUM(ppout.quantity - IFNULL(ppout.scrap_qty, 0))                                AS numberOfCompleted,
-               SUM((ppout.quantity - IFNULL(ppout.scrap_qty, 0)) * IFNULL(pp.salary_quota, 0)) AS amount,
-               ROUND(
-                       SUM(ppout.quantity - IFNULL(ppout.scrap_qty, 0)) * 100 / NULLIF(SUM(ppout.quantity), 0),
-                       2
-               )                                                                               AS passRate
-        FROM production_product_output ppout
-                 LEFT JOIN production_product_main ppm ON ppm.id = ppout.product_main_id
-                 LEFT JOIN product_process_route_item ppri ON ppri.id = ppm.product_process_route_item_id
-                 LEFT JOIN product_process pp ON pp.id = ppri.process_id
-        WHERE ppout.create_time &gt;= #{startDate}
-          AND ppout.create_time &lt; #{endDate}
-        GROUP BY DATE(ppout.create_time)
-        ORDER BY DATE(ppout.create_time);
-    </select>
-    <select id="getByUserId" resultType="com.ruoyi.production.dto.UserAccountDto">
-        select
-            slpa.scheduling_user_id as user_id,
-            pp.type,
-            sum(case when pp.type = 0 then slpa.work_hours else 0 end) as account,
-            sum(case when pp.type = 1 then slpa.work_hours else 0 end) as accountBalance
-        from sales_ledger_production_accounting slpa
-                 left join product_process pp on pp.name = slpa.process
-        where  slpa.scheduling_user_id = #{ew.userId}
-          and slpa.scheduling_date like concat(#{ew.date}, '%')
-        group by slpa.scheduling_user_id
-
-    </select>
-
-
-</mapper>
diff --git a/src/main/resources/mapper/production/SalesLedgerSchedulingMapper.xml b/src/main/resources/mapper/production/SalesLedgerSchedulingMapper.xml
deleted file mode 100644
index 4cff920..0000000
--- a/src/main/resources/mapper/production/SalesLedgerSchedulingMapper.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.SalesLedgerSchedulingMapper">
-
-    <select id="listPage" resultType="com.ruoyi.production.dto.SalesLedgerSchedulingDto">
-        SELECT
-        T2.id as salesLedgerProductId,
-        T1.id as salesLedgerId,
-        ifNull(sum(t3.scheduling_num),0) AS schedulingNum,
-        T1.sales_contract_no,
-        T1.customer_contract_no,
-        T1.project_name,
-        T1.entry_date,
-        T1.customer_name,
-        T2.quantity,
-        T2.product_category,
-        T2.specification_model,
-        T2.speculative_trading_name,
-        T2.unit
-        FROM
-        sales_ledger_product T2
-        LEFT join sales_ledger_scheduling t3 on T2.id = t3.sales_ledger_product_id
-        LEFT JOIN sales_ledger T1 ON T1.id = T2.sales_ledger_id
-        <where>
-            T1.id is not null and T2.type = 1
-            <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
-                AND  T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
-            </if>
-            <if test="salesLedgerDto.customerContractNo != null and salesLedgerDto.customerContractNo !='' ">
-                AND  T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.salesContractNo != null and salesLedgerDto.salesContractNo != '' ">
-                AND  T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.projectName != null and salesLedgerDto.projectName != '' ">
-                AND T1.project_name LIKE CONCAT('%',#{salesLedgerDto.projectName},'%')
-            </if>
-            <if test="salesLedgerDto.entryDateStart != null and salesLedgerDto.entryDateStart != '' ">
-                AND T1.entry_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
-            </if>
-            <if test="salesLedgerDto.entryDateEnd != null and salesLedgerDto.entryDateEnd != '' ">
-                AND  T1.entry_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
-            </if>
-        </where>
-        GROUP BY T2.id
-        <if test="salesLedgerDto.status != null and salesLedgerDto.status.equals('true')">
-            HAVING quantity - schedulingNum > 0
-        </if>
-        order by T1.entry_date desc
-    </select>
-    <select id="list" resultType="com.ruoyi.production.dto.SalesLedgerSchedulingDto">
-        SELECT
-            T2.id,
-            ifNull(sum(t3.scheduling_num),0) AS schedulingNum,
-            T1.sales_contract_no,
-            T1.customer_contract_no,
-            T1.project_name,
-            T1.entry_date,
-            T1.customer_name,
-            T2.quantity,
-            T2.product_category,
-            T2.specification_model,
-            T2.unit
-        FROM
-            sales_ledger_product T2
-                LEFT JOIN sales_ledger T1 ON T1.id = T2.sales_ledger_id
-                LEFT join sales_ledger_scheduling t3 on T1.id = t3.sales_ledger_id
-        where T1.id is not null and T2.type = 1
-        GROUP BY T2.id
-    </select>
-    <select id="listPageProcess" resultType="com.ruoyi.production.dto.SalesLedgerSchedulingProcessDto">
-        SELECT
-        t3.id as salesLedgerProductId,
-        T1.id as salesLedgerId,
-        T2.id,
-        T2.status,
-        T2.scheduling_user_id,
-        T2.scheduling_user_name,
-        T2.speculative_trading_name,
-        T2.scheduling_date,
-        ifNull(T2.scheduling_num,0) AS schedulingNum,
-        ifNull(T2.finished_num,0) AS successNum,
-        T1.sales_contract_no,
-        T1.customer_contract_no,
-        T1.project_name,
-        T1.customer_name,
-        t3.product_category,
-        t3.specification_model,
-        t3.unit,
-        T2.production_line
-        FROM
-        sales_ledger_scheduling T2
-        LEFT JOIN sales_ledger T1 ON T1.id = T2.sales_ledger_id
-        left join sales_ledger_product t3 on T2.sales_ledger_product_id = t3.id and slp.type = 1
-        <where>
-            t3.type = 1
-            <if test="salesLedgerDto.status != null and salesLedgerDto.status != '' ">
-                AND  T2.status = #{salesLedgerDto.status}
-            </if>
-            <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
-                AND  T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
-            </if>
-            <if test="salesLedgerDto.customerContractNo != null and salesLedgerDto.customerContractNo !='' ">
-                AND  T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.salesContractNo != null and salesLedgerDto.salesContractNo != '' ">
-                AND  T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.projectName != null and salesLedgerDto.projectName != '' ">
-                AND T1.project_name LIKE CONCAT('%',#{salesLedgerDto.projectName},'%')
-            </if>
-            <if test="salesLedgerDto.entryDateStart != null and salesLedgerDto.entryDateStart != '' ">
-                AND T2.scheduling_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
-            </if>
-            <if test="salesLedgerDto.entryDateEnd != null and salesLedgerDto.entryDateEnd != '' ">
-                AND  T2.scheduling_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
-            </if>
-        </where>
-        order by T2.scheduling_date desc
-    </select>
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/production/SalesLedgerWorkMapper.xml b/src/main/resources/mapper/production/SalesLedgerWorkMapper.xml
deleted file mode 100644
index 4ec771f..0000000
--- a/src/main/resources/mapper/production/SalesLedgerWorkMapper.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.production.mapper.SalesLedgerWorkMapper">
-
-    <select id="listPage" resultType="com.ruoyi.production.dto.SalesLedgerWorkDto">
-        SELECT
-        t4.id,
-        t4.status,
-        t4.scheduling_user_id,
-        t4.scheduling_user_name,
-        t4.scheduling_date,
-        t4.scheduling_num,
-        t4.finished_num,
-        t4.work_hours,
-        t4.process,
-        t4.type,
-        t4.remark,
-        t4.receive,
-        T1.sales_contract_no,
-        T1.customer_contract_no,
-        T1.project_name,
-        T1.customer_name,
-        t3.product_category,
-        t3.specification_model,
-        t3.unit,
-        t2.speculative_trading_name,
-        t4.production_line
-        FROM
-        sales_ledger_work t4
-        LEFT JOIN sales_ledger T1 ON T1.id = t4.sales_ledger_id
-        left join sales_ledger_product t3 on t4.sales_ledger_product_id = t3.id and slp.type = 1
-        left join sales_ledger_scheduling t2 on t4.sales_ledger_scheduling_id = t2.id
-        <where>
-            t3.type = 1
-            <if test="salesLedgerDto.status != null and salesLedgerDto.status != '' ">
-                AND  t4.status = #{salesLedgerDto.status}
-            </if>
-            <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
-                AND  T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
-            </if>
-            <if test="salesLedgerDto.customerContractNo != null and salesLedgerDto.customerContractNo !='' ">
-                AND  T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.salesContractNo != null and salesLedgerDto.salesContractNo != '' ">
-                AND  T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
-            </if>
-            <if test="salesLedgerDto.projectName != null and salesLedgerDto.projectName != '' ">
-                AND T1.project_name LIKE CONCAT('%',#{salesLedgerDto.projectName},'%')
-            </if>
-            <if test="salesLedgerDto.entryDateStart != null and salesLedgerDto.entryDateStart != '' ">
-                AND t4.scheduling_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
-            </if>
-            <if test="salesLedgerDto.entryDateEnd != null and salesLedgerDto.entryDateEnd != '' ">
-                AND  t4.scheduling_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
-            </if>
-        </where>
-        order by t4.scheduling_date desc
-    </select>
-</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml b/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
index c5c007e..8e01079 100644
--- a/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
+++ b/src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
@@ -197,27 +197,27 @@
                 T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
             </if>
         </where>
-        GROUP BY T1.supplier_name
+        GROUP BY T1.supplier_id, T1.supplier_name
     </select>
 
     <select id="supplierNameListPageDetails" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
         SELECT
         T1.supplier_id,
         T1.supplier_name,
-        SUM(contract_amount) AS invoiceAmount,
-        IFNULL( SUM(T2.current_payment_amount) , 0 ) AS paymentAmount,
-        IFNULL((IFNULL(SUM(contract_amount),0)  - IFNULL(SUM(T2.current_payment_amount),0)),0) AS payableAmount,
         T1.purchase_contract_number,
-        T2.payment_date
+        T2.payment_date,
+        SUM(T1.contract_amount) AS invoiceAmount,
+        IFNULL(SUM(T2.current_payment_amount), 0) AS paymentAmount,
+        IFNULL((IFNULL(SUM(T1.contract_amount), 0) - IFNULL(SUM(T2.current_payment_amount), 0)), 0) AS payableAmount
         FROM purchase_ledger T1
         INNER JOIN payment_registration T2 ON T1.id = T2.purchase_ledger_id
         <where>
             T1.supplier_id = #{req.supplierId}
             <if test="req.supplierName != null and req.supplierName != '' ">
-                T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
+                AND T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
             </if>
         </where>
-        GROUP BY  T1.purchase_contract_number,T2.payment_date
+        GROUP BY T1.supplier_id, T1.supplier_name, T1.purchase_contract_number, T2.payment_date
     </select>
 
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
index f501849..1aed9b4 100644
--- a/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml
@@ -62,6 +62,12 @@
             <if test="c.entryDateEnd != null and c.entryDateEnd != ''">
                 AND pl.entry_date &lt;= #{c.entryDateEnd}
             </if>
+            <if test="c.supplierId != null">
+                AND pl.supplier_id = #{c.supplierId}
+            </if>
+            <if test="c.approvalStatus != null">
+                AND pl.approval_status = #{c.approvalStatus}
+            </if>
         </where>
         ORDER BY pl.entry_date DESC
     </select>
diff --git a/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml b/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml
index 9ae589f..cd13f3c 100644
--- a/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml
@@ -11,5 +11,14 @@
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
     </resultMap>
-
+    <select id="getReturnOrderGroupListByProductIds" resultType="com.ruoyi.purchase.dto.SimpleReturnOrderGroupDto"
+            parameterType="java.util.List">
+        select t1.sales_ledger_product_id,sum(t1.return_quantity) as sum_return_quantity from purchase_return_order_products as t1
+        inner join purchase_return_orders as t2 on t1.purchase_return_order_id = t2.id
+        WHERE t1.sales_ledger_product_id IN
+        <foreach item="id" collection="productIds" separator="," open="(" close=")">
+            #{id}
+        </foreach>
+        group by t1.sales_ledger_product_id
+    </select>
 </mapper>
diff --git a/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml b/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
index 8976a3a..0232873 100644
--- a/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
+++ b/src/main/resources/mapper/purchase/PurchaseReturnOrdersMapper.xml
@@ -23,17 +23,26 @@
         SELECT
         pro.*,
         sm.supplier_name as supplierName,
-        pl.purchase_contract_number as purchaseContractNumber,
-        su.user_name as returnUserName,
-        su1.user_name as createUserName
+        pl.purchase_contract_number as purchaseContractNumber
         FROM purchase_return_orders pro
         LEFT JOIN supplier_manage sm ON pro.supplier_id = sm.id
         LEFT JOIN purchase_ledger pl ON pl.id = pro.purchase_ledger_id
-        LEFT JOIN sys_user su ON su.user_id = pro.return_user_id
-        LEFT JOIN sys_user su1 ON su1.user_id = pro.prepared_user_id
         where 1=1
         <if test="params.no != null and params.no != '' ">
             AND pro.no LIKE CONCAT('%',#{params.no},'%')
         </if>
+        <if test="params.deptId != null">
+            AND pro.dept_id = #{params.deptId}
+        </if>
+        <if test="params.deptIds != null and params.deptIds.length > 0">
+            AND pro.dept_id IN
+            <foreach collection="params.deptIds" item="deptId" open="(" separator="," close=")">
+                #{deptId}
+            </foreach>
+        </if>
+        <if test="params.createUser != null">
+            AND pro.create_user = #{params.createUser}
+        </if>
+        ORDER BY pro.create_time DESC
     </select>
 </mapper>
diff --git a/src/main/resources/mapper/quality/QualityInspectMapper.xml b/src/main/resources/mapper/quality/QualityInspectMapper.xml
index 48fb369..f252881 100644
--- a/src/main/resources/mapper/quality/QualityInspectMapper.xml
+++ b/src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 <mapper namespace="com.ruoyi.quality.mapper.QualityInspectMapper">
-    <select id="qualityInspectListPage" resultType="com.ruoyi.quality.pojo.QualityInspect">
+    <select id="qualityInspectListPage" resultType="com.ruoyi.quality.dto.QualityInspectDto">
         SELECT
         qi.*,
         <choose>
@@ -9,7 +9,8 @@
                 pl.purchase_contract_number as purchase_contract_no
             </when>
             <otherwise>
-                pwo.work_order_no
+                pot.work_order_no,
+                po_sales.sales_contract_no
             </otherwise>
         </choose>
         FROM
@@ -20,7 +21,17 @@
             </when>
             <otherwise>
                 LEFT JOIN production_product_main ppm ON qi.product_main_id = ppm.id
-                LEFT JOIN product_work_order pwo ON ppm.work_order_id = pwo.id
+                LEFT JOIN production_operation_task pot ON ppm.production_operation_task_id = pot.id
+                left join production_order po ON po.id = pot.production_order_id
+                left join (
+                    select po2.id as order_id,
+                           group_concat(distinct sl2.sales_contract_no order by sl2.sales_contract_no separator ',') as sales_contract_no
+                    from production_order po2
+                             left join production_plan pp2
+                                       on find_in_set(pp2.id, replace(replace(replace(po2.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                             left join sales_ledger sl2 on sl2.id = pp2.sales_ledger_id
+                    group by po2.id
+                ) po_sales ON po_sales.order_id = po.id
             </otherwise>
         </choose>
         WHERE
diff --git a/src/main/resources/mapper/quality/QualityTestStandardMapper.xml b/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
index 5c20733..f326a66 100644
--- a/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
+++ b/src/main/resources/mapper/quality/QualityTestStandardMapper.xml
@@ -24,11 +24,11 @@
         SELECT qts.*
         FROM quality_test_standard qts
                  left join quality_test_standard_binding qtsb on qtsb.test_standard_id = qts.id
-                 left join product_process pp on qts.process_id = pp.id
+                 left join technology_operation toper on qts.process_id = toper.id
         WHERE qtsb.product_id = #{productId}
           AND qts.inspect_type = #{inspectType}
         <if test="process!='' and process!=null">
-            and pp.name = #{process}
+            and toper.name = #{process}
         </if>
         order by qts.id desc
     </select>
diff --git a/src/main/resources/mapper/sales/InvoiceLedgerMapper.xml b/src/main/resources/mapper/sales/InvoiceLedgerMapper.xml
index 2874f48..5454640 100644
--- a/src/main/resources/mapper/sales/InvoiceLedgerMapper.xml
+++ b/src/main/resources/mapper/sales/InvoiceLedgerMapper.xml
@@ -123,7 +123,7 @@
                 T1.customer_name LIKE CONCAT ('%',#{invoiceLedgerDto.searchText},'%')
             </if>
         </where>
-        GROUP BY T1.customer_name
+        GROUP BY T1.customer_name,t1.customer_id
     </select>
 
     <select id="invoiceLedgerProductInfo" resultType="com.ruoyi.sales.dto.InvoiceRegistrationProductDto">
diff --git a/src/main/resources/mapper/sales/SalesLedgerMapper.xml b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
index 85f62c0..e08632a 100644
--- a/src/main/resources/mapper/sales/SalesLedgerMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -5,12 +5,12 @@
 <mapper namespace="com.ruoyi.sales.mapper.SalesLedgerMapper">
 
     <select id="selectSequencesByDate" resultType="java.lang.Integer">
-        SELECT CAST(SUBSTR(sales_contract_no,LENGTH(#{datePart})+1 , 3) AS SIGNED)
+        SELECT CAST(SUBSTR(sales_contract_no, LENGTH(#{datePart}) + 1, 3) AS SIGNED)
         FROM sales_ledger
-        WHERE sales_contract_no LIKE CONCAT('%',#{datePart},'%')
+        WHERE sales_contract_no LIKE CONCAT('%', #{datePart}, '%')
     </select>
     <select id="getSalesNo" resultType="com.ruoyi.sales.pojo.SalesLedger">
-        
+
     </select>
 
     <select id="selectSalesLedgerList" resultType="com.ruoyi.sales.pojo.SalesLedger">
@@ -42,7 +42,7 @@
         </where>
     </select>
 
-    <select id="selectSalesLedgerListPage" resultType="com.ruoyi.sales.pojo.SalesLedger">
+    <select id="selectSalesLedgerListPage" resultType="com.ruoyi.sales.vo.SalesLedgerVo">
         SELECT T1.id,
         T1.sales_contract_no,
         T1.customer_contract_no,
@@ -56,47 +56,46 @@
         T1.attachment_materials,
         T1.tenant_id,
         T1.contract_amount,
-        T1.contract_amount                    as noInvoiceAmountTotal,
+        T1.contract_amount AS noInvoiceAmountTotal,
         T1.execution_date,
-        T2.nick_name                          AS entry_person_name,
+        T2.nick_name AS entry_person_name,
         T1.payment_method,
         T1.delivery_date,
         DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff,
-        CASE
-        WHEN shipping_status_counts.total_count = 0 THEN false
-        WHEN shipping_status_counts.unshipped_count = 0 THEN true
-        ELSE false
-        END AS is_fh
+        IFNULL(shipping_status_counts.is_all_shipped, FALSE) AS is_fh
         FROM sales_ledger T1
         LEFT JOIN sys_user T2 ON T1.entry_person = T2.user_id
         LEFT JOIN (
         SELECT sales_ledger_id,
-        COUNT(*) as total_count,
-        SUM(CASE WHEN status != '宸插彂璐�' THEN 1 ELSE 0 END) as unshipped_count
+        CASE
+        WHEN SUM(CASE WHEN status != '宸插彂璐�' THEN 1 ELSE 0 END) = 0 THEN TRUE
+        ELSE FALSE
+        END AS is_all_shipped
         FROM shipping_info
         GROUP BY sales_ledger_id
         ) shipping_status_counts ON T1.id = shipping_status_counts.sales_ledger_id
+
         <where>
             <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
-                AND  T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
+                AND T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
             </if>
             <if test="salesLedgerDto.customerContractNo != null and salesLedgerDto.customerContractNo !='' ">
-                AND  T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
+                AND T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
             </if>
             <if test="salesLedgerDto.salesContractNo != null and salesLedgerDto.salesContractNo != '' ">
-                AND  T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
+                AND T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
             </if>
             <if test="salesLedgerDto.projectName != null and salesLedgerDto.projectName != '' ">
                 AND T1.project_name LIKE CONCAT('%',#{salesLedgerDto.projectName},'%')
             </if>
             <if test="salesLedgerDto.entryDateStart != null and salesLedgerDto.entryDateStart != '' ">
-               AND T1.entry_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
+                AND T1.entry_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
             </if>
             <if test="salesLedgerDto.entryDateEnd != null and salesLedgerDto.entryDateEnd != '' ">
-                AND  T1.entry_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
+                AND T1.entry_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
             </if>
         </where>
-    order by T1.entry_date desc
+        order by T1.entry_date desc
     </select>
 
     <select id="selectIncomeStats" resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
@@ -111,14 +110,16 @@
         FROM sales_ledger
         GROUP BY customer_name
     </select>
-    <select id="listSalesLedger" resultType="com.ruoyi.sales.dto.SalesLedgerDto">
-        select * from
+    <select id="listSalesLedgerAndShipped" resultType="com.ruoyi.sales.dto.SalesLedgerDto">
+        select distinct sl.id as 'disId', sl.* from
         sales_ledger sl
-        <where>
-            <if test="ew.customerName != null and ew.customerName != '' ">
+        left join sales_ledger_product slp on sl.id = slp.sales_ledger_id
+        left join shipping_info si on slp.id = si.sales_ledger_product_id
+        where si.status = '宸插彂璐�'
+        <if test="ew.customerName != null and ew.customerName != '' ">
             and sl.customer_name like concat('%',#{ew.customerName},'%')
-            </if>
-        </where>
+        </if>
+        order by sl.execution_date desc
     </select>
 
-</mapper>
\ No newline at end of file
+</mapper>
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 73026c8..49689a1 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -8,12 +8,27 @@
         SELECT
         T1.*,
         CASE
-        WHEN (IFNULL(t2.qualitity, 0) - IFNULL(t2.locked_quantity, 0)) >= IFNULL(T1.quantity, 0) THEN 1
+        WHEN (IFNULL(t2.qualitity, 0) - IFNULL(t2.locked_quantity, 0)) >0 THEN 1
         ELSE 0
-        END as has_sufficient_stock
+        END as has_sufficient_stock,
+        (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) as no_quantity,
+        CASE
+        WHEN (IFNULL(T1.quantity, 0) - IFNULL(t3.shipped_quantity, 0)) > 0 THEN '寰呭彂璐�'
+        ELSE '宸插彂璐�'
+        END as shippingStatus
         FROM
         sales_ledger_product T1
-        LEFT JOIN stock_inventory t2 ON T1.product_model_id = t2.product_model_id
+        LEFT JOIN (
+        SELECT product_model_id, SUM(qualitity) as qualitity, SUM(locked_quantity) as locked_quantity
+        FROM stock_inventory
+        GROUP BY product_model_id
+        ) t2 ON T1.product_model_id = t2.product_model_id
+        LEFT JOIN (
+        SELECT sales_ledger_product_id, IFNULL(SUM(spd.quantity), 0) as shipped_quantity
+        FROM shipping_info si
+        LEFT JOIN shipping_product_detail spd ON si.id = spd.shipping_info_id
+        GROUP BY sales_ledger_product_id
+        ) t3 ON t3.sales_ledger_product_id = T1.id
         <where>
             <if test="salesLedgerProduct.salesLedgerId != null">
                 AND T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}
@@ -29,10 +44,17 @@
         select slp.*
         from quality_inspect qi
                  left join production_product_main ppm on qi.product_main_id = ppm.id
-                 left join product_work_order pwo on ppm.work_order_id = pwo.id
-                 left join product_order po on pwo.product_order_id = po.id
-                 left join sales_ledger_product slp on po.sale_ledger_product_id = slp.id and slp.type = 1
+                 left join production_operation_task pot on ppm.production_operation_task_id = pot.id
+                 left join production_order po on pot.production_order_id = po.id
+                 left join production_plan pp_main
+                           on find_in_set(pp_main.id, replace(replace(replace(po.production_plan_ids, '[', ''), ']', ''), ' ', '')) > 0
+                 left join sales_ledger_product slp on slp.sales_ledger_id = pp_main.sales_ledger_id
+            and slp.product_model_id = po.product_model_id
+            and slp.type = 1
         where qi.product_main_id = #{productMainId}
+          and slp.id is not null
+        order by slp.id desc
+        limit 1
 
 
     </select>
@@ -114,10 +136,14 @@
         <!-- 骞冲潎鍗曚环 = 鎬婚噰璐噾棰�/鎬婚噰璐暟閲忥紝淇濈暀2浣嶅皬鏁帮紝閬垮厤闄�0 -->
         ROUND(IF(SUM(slp.quantity) = 0, 0, SUM(slp.tax_inclusive_total_price) / SUM(slp.quantity)), 2) AS averagePrice,
         <!-- 璇ヤ骇鍝佸ぇ绫讳笅鏈�鍚庝竴涓綍鍏ユ棩鏈燂紙鍙栧彴璐︿富琛ㄧ殑entry_date锛� -->
-        MAX(sl.entry_date) AS entryDate
+        MAX(sl.entry_date) AS entryDate,
+        COALESCE(NULLIF(SUM(t1.return_quantity), 0), 0) AS return_quantity,
+        COALESCE(SUM(t2.total_amount), 0) AS return_amount
         FROM sales_ledger_product slp
         <!-- 鍏宠仈鍙拌处涓昏〃锛氳幏鍙栧綍鍏ユ棩鏈焑ntry_date -->
         LEFT JOIN purchase_ledger sl ON slp.sales_ledger_id = sl.id
+        left join purchase_return_order_products as t1 on t1.sales_ledger_product_id = slp.id
+        left join purchase_return_orders as t2 on t2.id = t1.purchase_return_order_id
         WHERE slp.type = 2 <!-- 鍥哄畾绛涢�夛細閲囪喘鍙拌处锛坱ype=2锛� -->
         <!-- 閲囪喘鏃ユ湡绛涢�夛細鍙�夋潯浠� -->
         <if test="req.entryDateStart != null and req.entryDateEnd != null">
@@ -127,9 +153,7 @@
         <if test="req.productCategory != null and req.productCategory != ''">
             AND slp.product_category = #{req.productCategory}
         </if>
-        <!-- 鎸変骇鍝佸ぇ绫诲垎缁勮仛鍚� -->
-        GROUP BY slp.product_category
-        <!-- 鎸変骇鍝佸ぇ绫绘帓搴� -->
+        GROUP BY slp.product_category, slp.specification_model, sl.supplier_name
         ORDER BY slp.product_category
     </select>
     <select id="selectProductBomStructure" resultType="com.ruoyi.sales.dto.LossProductModelDto">
diff --git a/src/main/resources/mapper/sales/SalesQuotationMapper.xml b/src/main/resources/mapper/sales/SalesQuotationMapper.xml
index 1e358ca..cf15b63 100644
--- a/src/main/resources/mapper/sales/SalesQuotationMapper.xml
+++ b/src/main/resources/mapper/sales/SalesQuotationMapper.xml
@@ -9,6 +9,7 @@
         FROM sales_quotation t1
         LEFT JOIN approve_process t2 ON t1.quotation_no = t2.approve_reason and t2.approve_type = 6
         WHERE 1=1
+          and t2.approve_deleted = 0
         <if test="salesQuotationDto.quotationNo != null and salesQuotationDto.quotationNo != '' ">
             AND t1.quotation_no LIKE CONCAT('%',#{salesQuotationDto.quotationNo},'%')
         </if>
diff --git a/src/main/resources/mapper/sales/ShippingInfoMapper.xml b/src/main/resources/mapper/sales/ShippingInfoMapper.xml
index 82c67b2..048bb23 100644
--- a/src/main/resources/mapper/sales/ShippingInfoMapper.xml
+++ b/src/main/resources/mapper/sales/ShippingInfoMapper.xml
@@ -61,20 +61,21 @@
     <select id="getReturnManagementDtoById" resultType="com.ruoyi.sales.dto.SalesLedgerProductDto">
         SELECT
         slp.*,
+        si.shipping_no,
         GREATEST(slp.quantity - COALESCE(rs.total_return_num, 0), 0) AS un_quantity,
         COALESCE(rs.total_return_num, 0) AS total_return_num
         FROM shipping_info si
         LEFT JOIN sales_ledger_product slp ON si.sales_ledger_product_id = slp.id and slp.type = 1
         LEFT JOIN (
         SELECT
-        return_sale_ledger_product_id,
+        return_sales_ledger_product_id,
         SUM(num) AS total_return_num
         FROM return_sale_product rsp
         left join return_management rm on rm.id = rsp.return_management_id
         left join shipping_info si on si.id = rm.shipping_id
         WHERE 1=1
-        GROUP BY return_sale_ledger_product_id
-        ) rs ON rs.return_sale_ledger_product_id = slp.id
+        GROUP BY return_sales_ledger_product_id
+        ) rs ON rs.return_sales_ledger_product_id = slp.id
         <where>
             <if test="shippingId != null">
                 si.id = #{shippingId}
@@ -86,4 +87,4 @@
         left join sales_ledger sl on si.sales_ledger_id = sl.id
         where si.status = '宸插彂璐�' and sl.customer_name = #{customerName}
     </select>
-</mapper>
\ No newline at end of file
+</mapper>
diff --git a/src/main/resources/mapper/sales/ShippingProductDetailMapper.xml b/src/main/resources/mapper/sales/ShippingProductDetailMapper.xml
new file mode 100644
index 0000000..464af10
--- /dev/null
+++ b/src/main/resources/mapper/sales/ShippingProductDetailMapper.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.sales.mapper.ShippingProductDetailMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.sales.pojo.ShippingProductDetail">
+        <id column="id" property="id" />
+        <result column="stock_inventory_id" property="stockInventoryId" />
+        <result column="batch_no" property="batchNo" />
+        <result column="quantity" property="quantity" />
+        <result column="shipping_info_id" property="shippingInfoId" />
+    </resultMap>
+    <select id="getDetail" resultType="com.ruoyi.sales.dto.ShippingProductDetailDto">
+        select si.batch_no, pm.model as specification_model, p.product_name, spd.quantity as delivery_quantity
+        from shipping_product_detail spd
+                 left join stock_inventory si on si.id = spd.stock_inventory_id
+                 left join product_model pm on pm.id = si.product_model_id
+                 left join product p on p.id = pm.product_id
+        where spd.shipping_info_id = #{id}
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/staff/PersonalShiftMapper.xml b/src/main/resources/mapper/staff/PersonalShiftMapper.xml
index d8ddb1d..69bcae3 100644
--- a/src/main/resources/mapper/staff/PersonalShiftMapper.xml
+++ b/src/main/resources/mapper/staff/PersonalShiftMapper.xml
@@ -12,26 +12,26 @@
         <result column="work_time" property="workTime" />
     </resultMap>
     <select id="performanceShiftPage" resultType="com.ruoyi.staff.dto.PerformanceShiftMapDto">
-         SELECT
+        SELECT
         u.staff_name name,
-        GROUP_CONCAT(s.work_time, '锛�', IFNULL(palc.shift, ''), '锛�', s.id order by s.work_time SEPARATOR ';') AS shift_time,
-                u.id user_id
+        GROUP_CONCAT(s.work_time, '锛�', IFNULL(palc.shift, ''), '锛�', s.id ORDER BY s.work_time SEPARATOR ';') AS shift_time,
+        u.id user_id
         FROM personal_shift s
         LEFT JOIN staff_on_job u ON u.id = s.staff_on_job_id
         LEFT JOIN personal_attendance_location_config palc ON palc.id = s.personal_attendance_location_config_id
         <where>
-             <if test="sysDeptId != null and sysDeptId != ''">
+            <if test="sysDeptId != null and sysDeptId != ''">
                 and u.sys_dept_id = #{sysDeptId}
             </if>
             <if test="time != null and time != ''">
-                and DATE_FORMAT(s.work_time, '%Y-%m') = DATE_FORMAT(#{time}, '%Y-%m' )
+                and DATE_FORMAT(s.work_time, '%Y-%m') = DATE_FORMAT(#{time}, '%Y-%m')
             </if>
             <if test="userName != null and userName != ''">
                 and u.staff_name like concat('%', #{userName}, '%')
             </if>
         </where>
-        GROUP BY u.id
-        order by s.create_time
+        GROUP BY u.id, u.staff_name
+        ORDER BY MAX(s.create_time)
     </select>
    
     <select id="performanceShiftYear" resultType="java.util.Map">
diff --git a/src/main/resources/mapper/staff/StaffOnJobMapper.xml b/src/main/resources/mapper/staff/StaffOnJobMapper.xml
index fe35886..b0c85bc 100644
--- a/src/main/resources/mapper/staff/StaffOnJobMapper.xml
+++ b/src/main/resources/mapper/staff/StaffOnJobMapper.xml
@@ -5,12 +5,14 @@
         SELECT
         staff_on_job.*,
         sp.post_name as postName,
-        sd.dept_name as deptName
+        sd.dept_name as deptName,
+        t1.contract_start_time
         FROM staff_on_job
         LEFT JOIN
         sys_post sp ON sp.post_id = staff_on_job.sys_post_id
         LEFT JOIN
         sys_dept sd ON sd.dept_id = staff_on_job.sys_dept_id
+        LEFT JOIN staff_contract as t1 ON t1.staff_on_job_id = staff_on_job.id
         where 1=1
         <if test="staffOnJob.staffState != null">
             AND staff_state = #{staffOnJob.staffState}
diff --git a/src/main/resources/mapper/stock/StockInRecordMapper.xml b/src/main/resources/mapper/stock/StockInRecordMapper.xml
index d5c3f38..62f1d19 100644
--- a/src/main/resources/mapper/stock/StockInRecordMapper.xml
+++ b/src/main/resources/mapper/stock/StockInRecordMapper.xml
@@ -3,6 +3,17 @@
 <mapper namespace="com.ruoyi.stock.mapper.StockInRecordMapper">
 
     <select id="listPage" resultType="com.ruoyi.stock.dto.StockInRecordDto">
+        WITH RECURSIVE product_tree AS (
+        SELECT id
+        FROM product
+        WHERE id = #{params.topParentProductId}
+
+        UNION ALL
+
+        SELECT p.id
+        FROM product p
+        INNER JOIN product_tree pt ON p.parent_id = pt.id
+        )
         SELECT
         sir.*,
         p.product_name as product_name,
@@ -25,6 +36,9 @@
             </if>
             <if test="params.recordType != null and params.recordType != ''">
                 and sir.record_type = #{params.recordType}
+            </if>
+            <if test="params.topParentProductId != null and params.topParentProductId > 0">
+                and p.id in (select id from product_tree)
             </if>
         </where>
         order by sir.id desc
@@ -56,4 +70,4 @@
         </where>
         order by sir.id desc
     </select>
-</mapper>
\ No newline at end of file
+</mapper>
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index 9db56f9..60fc90e 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -34,6 +34,12 @@
             update_time = now()
         </set>
         where product_model_id = #{ew.productModelId}
+            <if test="ew.batchNo == null">
+                and batch_no is null
+            </if>
+            <if test="ew.batchNo != null">
+                and batch_no = #{ew.batchNo}
+            </if>
     </update>
     <update id="updateSubtractStockInventory">
         update stock_inventory
@@ -50,6 +56,12 @@
             update_time = now()
         </set>
         where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
+            <if test="ew.batchNo == null">
+                and batch_no is null
+            </if>
+            <if test="ew.batchNo != null">
+                and batch_no = #{ew.batchNo}
+            </if>
     </update>
     <select id="pagestockInventory" resultType="com.ruoyi.stock.dto.StockInventoryDto">
         select si.id,
@@ -73,22 +85,203 @@
             and p.product_name like concat('%',#{ew.productName},'%')
         </if>
     </select>
+
+    <select id="pageListCombinedStockInventory" resultType="com.ruoyi.stock.dto.StockInventoryDto">
+        WITH RECURSIVE product_tree AS (
+        SELECT id
+        FROM product
+        WHERE id = #{ew.topParentProductId}
+
+        UNION ALL
+
+        SELECT p.id
+        FROM product p
+        INNER JOIN product_tree pt ON p.parent_id = pt.id
+        )
+        select
+            batch_no,
+            MAX(qualifiedId) as qualifiedId,
+            MAX(unQualifiedId) as unQualifiedId,
+            SUM(qualifiedQuantity) as qualifiedQuantity,
+            SUM(unQualifiedQuantity) as unQualifiedQuantity,
+            SUM(qualifiedLockedQuantity) as qualifiedLockedQuantity,
+            SUM(unQualifiedLockedQuantity) as unQualifiedLockedQuantity,
+            SUM(qualifiedQuantity - qualifiedLockedQuantity - IFNULL(qualifiedPendingOut, 0)) as qualifiedUnLockedQuantity,
+            SUM(unQualifiedQuantity - unQualifiedLockedQuantity - IFNULL(unQualifiedPendingOut, 0)) as unQualifiedUnLockedQuantity,
+            SUM(IFNULL(qualifiedPendingOut, 0)) as qualifiedPendingOutQuantity,
+            SUM(IFNULL(unQualifiedPendingOut, 0)) as unQualifiedPendingOutQuantity,
+            product_model_id,
+            MAX(create_time) as create_time,
+            MAX(update_time) as update_time,
+            MAX(warn_num) as warn_num,
+            MAX(version) as version,
+            model,
+            MAX(remark) as remark,
+            unit,
+            product_name,
+            product_id,
+            'combined' as stockType
+        from (
+            select
+            si.batch_no,
+            si.id as qualifiedId,
+            null as unQualifiedId,
+            si.qualitity as qualifiedQuantity,
+            0 as unQualifiedQuantity,
+            COALESCE(si.locked_quantity, 0) as locked_quantity,
+            COALESCE(si.locked_quantity, 0) as qualifiedLockedQuantity,
+            0 as unQualifiedLockedQuantity,
+            si.product_model_id,
+            si.create_time,
+            si.update_time,
+            COALESCE(si.warn_num, 0) as warn_num,
+            si.version,
+            (si.qualitity - COALESCE(si.locked_quantity, 0)) as un_locked_quantity,
+            pm.model,
+            si.remark,
+            pm.unit,
+            p.product_name,
+            p.id as product_id,
+            (
+                select IFNULL(SUM(sor.stock_out_num), 0)
+                from stock_out_record sor
+                where sor.product_model_id = si.product_model_id
+                  and (si.batch_no is null and sor.batch_no is null or si.batch_no = sor.batch_no)
+                  and sor.type = '0'
+                  and sor.approval_status = 0
+            ) as qualifiedPendingOut,
+            0 as unqualifiedPendingOut
+            from stock_inventory si
+            left join product_model pm on si.product_model_id = pm.id
+            left join product p on pm.product_id = p.id
+
+            union all
+
+            select
+            su.batch_no,
+            null as qualifiedId,
+            su.id as unQualifiedId,
+            0 as qualifiedQuantity,
+            su.qualitity as unQualifiedQuantity,
+            COALESCE(su.locked_quantity, 0) as locked_quantity,
+            0 as qualifiedLockedQuantity,
+            COALESCE(su.locked_quantity, 0) as unQualifiedLockedQuantity,
+            su.product_model_id,
+            su.create_time,
+            su.update_time,
+            0 as warn_num,
+            su.version,
+            (su.qualitity - COALESCE(su.locked_quantity, 0)) as un_locked_quantity,
+            pm.model,
+            su.remark,
+            pm.unit,
+            p.product_name,
+            p.id as product_id,
+            0 as qualifiedPendingOut,
+            (
+                select IFNULL(SUM(sor.stock_out_num), 0)
+                from stock_out_record sor
+                where sor.product_model_id = su.product_model_id
+                  and (su.batch_no is null and sor.batch_no is null or su.batch_no = sor.batch_no)
+                  and sor.type = '1'
+                  and sor.approval_status = 0
+            ) as unqualifiedPendingOut
+            from stock_uninventory su
+            left join product_model pm on su.product_model_id = pm.id
+            left join product p on pm.product_id = p.id
+        ) as combined
+        <where>
+            <if test="ew.productName != null and ew.productName !=''">
+                and combined.product_name in (
+                select distinct p.product_name
+                from product p
+                left join product_model pm on p.id = pm.product_id
+                where p.product_name like concat('%',#{ew.productName},'%') or pm.model like concat('%',#{ew.productName},'%')
+                )
+            </if>
+            <if test="ew.topParentProductId != null and ew.topParentProductId > 0">
+                and combined.product_id in (select id from product_tree)
+            </if>
+        </where>
+        group by batch_no, product_model_id, model, unit, product_name, product_id
+    </select>
+
     <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData">
-        select si.qualitity,
-        pm.model,
-        pm.unit,
-        p.product_name,
-        coalesce(si.warn_num, 0) as warn_num,
-        coalesce(si.locked_quantity, 0) as locked_quantity,
-        si.remark,
-        si.update_time
-        from stock_inventory si
-        left join product_model pm on si.product_model_id = pm.id
-        left join product p on pm.product_id = p.id
-        where 1 = 1
-        <if test="ew.productName != null and ew.productName !=''">
-            and p.product_name like concat('%',#{ew.productName},'%')
-        </if>
+        WITH RECURSIVE product_tree AS (
+        SELECT id
+        FROM product
+        WHERE id = #{ew.topParentProductId}
+
+        UNION ALL
+
+        SELECT p.id
+        FROM product p
+        INNER JOIN product_tree pt ON p.parent_id = pt.id
+        )
+        select
+            SUM(qualifiedQuantity) as qualifiedQuantity,
+            SUM(unQualifiedQuantity) as unQualifiedQuantity,
+            SUM(qualifiedLockedQuantity) as qualifiedLockedQuantity,
+            SUM(unQualifiedLockedQuantity) as unQualifiedLockedQuantity,
+            model,
+            unit,
+            product_name,
+            MAX(warn_num) as warn_num,
+            MAX(remark) as remark,
+            MAX(update_time) as update_time
+        from (
+            select
+            si.qualitity as qualifiedQuantity,
+            0 as unQualifiedQuantity,
+            COALESCE(si.locked_quantity, 0) as qualifiedLockedQuantity,
+            0 as unQualifiedLockedQuantity,
+            si.product_model_id,
+            si.create_time,
+            si.update_time,
+            COALESCE(si.warn_num, 0) as warn_num,
+            si.remark,
+            pm.model,
+            pm.unit,
+            p.product_name,
+            p.id as product_id
+            from stock_inventory si
+            left join product_model pm on si.product_model_id = pm.id
+            left join product p on pm.product_id = p.id
+
+            union all
+
+            select
+            0 as qualifiedQuantity,
+            su.qualitity as unQualifiedQuantity,
+            0 as qualifiedLockedQuantity,
+            COALESCE(su.locked_quantity, 0) as unQualifiedLockedQuantity,
+            su.product_model_id,
+            su.create_time,
+            su.update_time,
+            0 as warn_num,
+            su.remark,
+            pm.model,
+            pm.unit,
+            p.product_name,
+            p.id as product_id
+            from stock_uninventory su
+            left join product_model pm on su.product_model_id = pm.id
+            left join product p on pm.product_id = p.id
+        ) as combined
+        <where>
+            <if test="ew.productName != null and ew.productName !=''">
+                and combined.product_name in (
+                select distinct p.product_name
+                from product p
+                left join product_model pm on p.id = pm.product_id
+                where p.product_name like concat('%',#{ew.productName},'%') or pm.model like concat('%',#{ew.productName},'%')
+                )
+            </if>
+            <if test="ew.topParentProductId != null and ew.topParentProductId > 0">
+                and combined.product_id in (select id from product_tree)
+            </if>
+        </where>
+        group by product_model_id, model, unit, product_name
     </select>
     <select id="stockInventoryPage" resultType="com.ruoyi.stock.dto.StockInRecordDto">
         select sir.*,si.qualitity as current_stock,
@@ -237,4 +430,35 @@
         ORDER BY DATE(sor.create_time) ASC
     </select>
 
+    <select id="selectPendingOutQuantity" resultType="java.math.BigDecimal">
+        SELECT IFNULL(SUM(sor.stock_out_num), 0)
+        FROM stock_out_record sor
+        WHERE sor.product_model_id = #{productModelId}
+          AND (sor.batch_no = #{batchNo} OR (#{batchNo} IS NULL AND sor.batch_no IS NULL))
+          AND sor.type = #{type}
+          AND sor.approval_status = 0
+    </select>
+
+    <select id="listSelectableBatchNoByProductModelIds" resultType="com.ruoyi.stock.pojo.StockInventory">
+        select distinct si.product_model_id,
+                        si.batch_no
+        from stock_inventory si
+        where si.product_model_id in
+        <foreach collection="productModelIds" item="productModelId" open="(" separator="," close=")">
+            #{productModelId}
+        </foreach>
+          and si.batch_no is not null
+          and si.batch_no != ''
+          and (si.qualitity - ifnull(si.locked_quantity, 0)) > 0
+        order by si.product_model_id, si.batch_no
+    </select>
+    <select id="getByModelId" resultType="com.ruoyi.stock.pojo.StockInventory">
+        select spd.id, spd.batch_no, spd.locked_quantity, (spd.qualitity - IFNULL(sd.qualitity, 0)) as qualitity
+        from stock_inventory spd
+                 left join (select stock_inventory_id, sum(quantity) as qualitity
+                            from shipping_product_detail
+                            group by stock_inventory_id) as sd on sd.stock_inventory_id = spd.id
+        where product_model_id = #{productModelId}
+    </select>
+
 </mapper>
diff --git a/src/main/resources/mapper/stock/StockOutRecordMapper.xml b/src/main/resources/mapper/stock/StockOutRecordMapper.xml
index a441de9..8615294 100644
--- a/src/main/resources/mapper/stock/StockOutRecordMapper.xml
+++ b/src/main/resources/mapper/stock/StockOutRecordMapper.xml
@@ -18,6 +18,17 @@
     </resultMap>
 
     <select id="listPage" resultType="com.ruoyi.stock.dto.StockOutRecordDto">
+        WITH RECURSIVE product_tree AS (
+        SELECT id
+        FROM product
+        WHERE id = #{params.topParentProductId}
+
+        UNION ALL
+
+        SELECT p.id
+        FROM product p
+        INNER JOIN product_tree pt ON p.parent_id = pt.id
+        )
         SELECT
         sor.*,
         p.product_name as productName,
@@ -41,6 +52,9 @@
             <if test="params.recordType != null and params.recordType != ''">
                 and sor.record_type = #{params.recordType}
             </if>
+            <if test="params.topParentProductId != null and params.topParentProductId > 0">
+                and p.id in (select id from product_tree)
+            </if>
         </where>
         order by sor.id desc
     </select>
diff --git a/src/main/resources/mapper/stock/StockUninventoryMapper.xml b/src/main/resources/mapper/stock/StockUninventoryMapper.xml
index b171ae2..582542c 100644
--- a/src/main/resources/mapper/stock/StockUninventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockUninventoryMapper.xml
@@ -25,13 +25,24 @@
             </if>
             update_time = now()
         </set>
-        where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
+        where
+        product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
+        <if test="ew.batchNo == null">
+            and batch_no is null
+        </if>
+        <if test="ew.batchNo != null">
+            and batch_no = #{ew.batchNo}
+        </if>
+
     </update>
     <update id="updateAddStockUnInventory">
         update stock_uninventory
         <set>
             <if test="ew.qualitity != null">
                 qualitity = qualitity + #{ew.qualitity},
+            </if>
+            <if test="ew.lockedQuantity != null">
+                locked_quantity = locked_quantity + #{ew.lockedQuantity},
             </if>
             <if test="ew.version != null">
                 version = version + 1,
@@ -42,6 +53,12 @@
             update_time = now()
         </set>
         where product_model_id = #{ew.productModelId}
+        <if test="ew.batchNo == null">
+            and batch_no is null
+        </if>
+        <if test="ew.batchNo != null">
+            and batch_no = #{ew.batchNo}
+        </if>
     </update>
     <select id="pageStockUninventory" resultType="com.ruoyi.stock.dto.StockUninventoryDto">
         select su.id,
@@ -78,4 +95,13 @@
         </if>
     </select>
 
+    <select id="selectPendingOutQuantity" resultType="java.math.BigDecimal">
+        SELECT IFNULL(SUM(sor.stock_out_num), 0)
+        FROM stock_out_record sor
+        WHERE sor.product_model_id = #{productModelId}
+          AND (sor.batch_no = #{batchNo} OR (#{batchNo} IS NULL AND sor.batch_no IS NULL))
+          AND sor.type = #{type}
+          AND sor.approval_status = 0
+    </select>
+
 </mapper>
diff --git a/src/main/resources/mapper/system/SysRoleMapper.xml b/src/main/resources/mapper/system/SysRoleMapper.xml
index 92ab684..9e16cf7 100644
--- a/src/main/resources/mapper/system/SysRoleMapper.xml
+++ b/src/main/resources/mapper/system/SysRoleMapper.xml
@@ -62,6 +62,7 @@
 	
 	<select id="selectRoleAll" resultMap="SysRoleResult">
 		<include refid="selectRoleVo"/>
+		WHERE r.del_flag = '0'
 	</select>
 	
 	<select id="selectRoleListByUserId" parameterType="Long" resultType="Long">
diff --git a/src/main/resources/mapper/system/SysUserMapper.xml b/src/main/resources/mapper/system/SysUserMapper.xml
index e4f818a..72da1a1 100644
--- a/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/src/main/resources/mapper/system/SysUserMapper.xml
@@ -15,6 +15,7 @@
         <result property="password"     column="password"     />
         <result property="status"       column="status"       />
         <result property="delFlag"      column="del_flag"     />
+        <result property="aiEnabled"    column="ai_enabled"   />
         <result property="loginIp"      column="login_ip"     />
         <result property="loginDate"    column="login_date"   />
         <result property="createBy"     column="create_by"    />
@@ -48,7 +49,7 @@
     </resultMap>
 
 	<sql id="selectUserVo">
-        select u.user_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
+        select u.user_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.ai_enabled, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status,u.tenant_id
         from sys_user u
 		    left join sys_user_role ur on u.user_id = ur.user_id
@@ -153,13 +154,18 @@
 	<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
 		select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1
 	</select>
-	<select id="selectUserByIds" resultType="com.ruoyi.project.system.domain.SysUser">
-		<include refid="selectUserVo"/>
-		where u.user_id in <foreach collection="userIds" item="item" open="(" separator="," close=")">
- 			#{item}
-        </foreach>
-		and u.del_flag = '0'
-	</select>
+    <select id="selectUserByIds" resultType="com.ruoyi.project.system.domain.SysUser">
+        <include refid="selectUserVo"/>
+        <where>
+            <if test="userIds != null and userIds.size > 0">
+                and u.user_id in
+                <foreach collection="userIds" item="item" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            and u.del_flag = '0'
+        </where>
+    </select>
 	<select id="selectRegistrantIds" resultType="com.ruoyi.project.system.domain.SysUser">
 		SELECT user_id, nick_name FROM sys_user
 		<where>
diff --git a/src/main/resources/mapper/technology/TechnologyBomMapper.xml b/src/main/resources/mapper/technology/TechnologyBomMapper.xml
new file mode 100644
index 0000000..267b1f5
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyBomMapper.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyBomMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyBom">
+        <id column="id" property="id" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="remark" property="remark" />
+        <result column="version" property="version" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_user" property="updateUser" />
+        <result column="bom_no" property="bomNo" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listPage" resultType="com.ruoyi.technology.bean.vo.TechnologyBomVo">
+        select tb.*,
+               pm.model as productModelName,
+               p.product_name as productName
+        from technology_bom tb
+        left join product_model pm on tb.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        <where>
+            <if test="c.productModelName != null and c.productModelName != ''">
+                and pm.model like concat('%', #{c.productModelName}, '%')
+            </if>
+            <if test="c.productName != null and c.productName != ''">
+                and p.product_name like concat('%', #{c.productName}, '%')
+            </if>
+            <if test="c.bomNo != null and c.bomNo != ''">
+                and tb.bom_no like concat('%', #{c.bomNo}, '%')
+            </if>
+            <if test="c.version != null and c.version != ''">
+                and tb.version = #{c.version}
+            </if>
+        </where>
+        order by tb.id desc
+    </select>
+</mapper>
diff --git a/src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml b/src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml
new file mode 100644
index 0000000..2030715
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyBomStructureMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyBomStructure">
+        <id column="id" property="id" />
+        <result column="parent_id" property="parentId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="operation_id" property="operationId" />
+        <result column="unit_quantity" property="unitQuantity" />
+        <result column="demanded_quantity" property="demandedQuantity" />
+        <result column="unit" property="unit" />
+        <result column="bom_id" property="bomId" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listByBomId" resultType="com.ruoyi.technology.bean.vo.TechnologyBomStructureVo">
+        select tbs.*,
+               p.product_name as productName,
+               pm.product_id as productId,
+               pm.model,
+               top1.name as operationName
+        from technology_bom_structure tbs
+        left join product_model pm on tbs.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        left join technology_operation top1 on tbs.operation_id = top1.id
+        where tbs.bom_id = #{bomId}
+        order by tbs.id
+    </select>
+</mapper>
diff --git a/src/main/resources/mapper/technology/TechnologyOperationMapper.xml b/src/main/resources/mapper/technology/TechnologyOperationMapper.xml
new file mode 100644
index 0000000..f6adc74
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyOperationMapper.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyOperationMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyOperation">
+        <id column="id" property="id" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="name" property="name" />
+        <result column="no" property="no" />
+        <result column="remark" property="remark" />
+        <result column="salary_quota" property="salaryQuota" />
+        <result column="is_quality" property="isQuality" />
+        <result column="type" property="type" />
+        <result column="device_ledger_id" property="deviceLedgerId" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listPage" resultType="com.ruoyi.technology.bean.vo.TechnologyOperationVo">
+        select *
+        from technology_operation t
+        <where>
+            <if test="c.name != null and c.name != ''">
+                and t.name like concat('%', #{c.name}, '%')
+            </if>
+            <if test="c.no != null and c.no != ''">
+                and t.no like concat('%', #{c.no}, '%')
+            </if>
+            <if test="c.type != null">
+                and t.type = #{c.type}
+            </if>
+        </where>
+        order by t.id asc
+    </select>
+</mapper>
diff --git a/src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml b/src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml
new file mode 100644
index 0000000..e1ccb2a
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyOperationParamMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyOperationParam">
+        <id column="id" property="id" />
+        <result column="technology_param_id" property="technologyParamId" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="standard_value" property="standardValue" />
+    </resultMap>
+
+    <select id="listOperationParam" resultType="com.ruoyi.technology.bean.vo.TechnologyOperationParamVo">
+        select top1.*,
+               tp.param_code as paramCode,
+               tp.param_name as paramName,
+               tp.param_type as paramType,
+               tp.param_format as paramFormat,
+               tp.unit,
+               tp.is_required as isRequired
+        from technology_operation_param top1
+        left join technology_param tp on top1.technology_param_id = tp.id
+        <where>
+            <if test="technologyOperationId != null">
+                and top1.technology_operation_id = #{technologyOperationId}
+            </if>
+            <if test="paramId != null">
+                and top1.technology_param_id = #{paramId}
+            </if>
+        </where>
+        order by top1.id asc
+    </select>
+</mapper>
diff --git a/src/main/resources/mapper/technology/TechnologyParamMapper.xml b/src/main/resources/mapper/technology/TechnologyParamMapper.xml
new file mode 100644
index 0000000..4542a2a
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyParamMapper.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyParamMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyParam">
+        <id column="id" property="id" />
+        <result column="param_code" property="paramCode" />
+        <result column="param_name" property="paramName" />
+        <result column="param_type" property="paramType" />
+        <result column="param_format" property="paramFormat" />
+        <result column="unit" property="unit" />
+        <result column="is_required" property="isRequired" />
+        <result column="remark" property="remark" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/technology/TechnologyRoutingMapper.xml b/src/main/resources/mapper/technology/TechnologyRoutingMapper.xml
new file mode 100644
index 0000000..bda31ba
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyRoutingMapper.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyRoutingMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyRouting">
+        <id column="id" property="id"/>
+        <result column="product_model_id" property="productModelId"/>
+        <result column="description" property="description"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="process_route_code" property="processRouteCode"/>
+        <result column="bom_id" property="bomId"/>
+        <result column="create_user" property="createUser"/>
+        <result column="dept_id" property="deptId"/>
+    </resultMap>
+
+    <select id="pageTechnologyRouting" resultType="com.ruoyi.technology.bean.vo.TechnologyRoutingVo">
+        select tr.id,
+        tr.product_model_id as productModelId,
+        tr.description,
+        tr.create_time as createTime,
+        tr.update_time as updateTime,
+        tr.process_route_code as processRouteCode,
+        tr.bom_id as bomId,
+        tr.create_user as createUser,
+        tr.dept_id as deptId,
+        p.product_name as productName,
+        pm.model,
+        tb.bom_no as bomNo
+        from technology_routing tr
+        left join product_model pm on tr.product_model_id = pm.id
+        left join product p on pm.product_id = p.id
+        left join technology_bom tb on tr.bom_id = tb.id
+        <where>
+            <if test="c != null">
+                <if test="c.id != null">
+                    and tr.id = #{c.id}
+                </if>
+                <if test="c.productModelId != null">
+                    and tr.product_model_id = #{c.productModelId}
+                </if>
+                <if test="c.model != null and c.model != ''">
+                    and pm.model like concat('%', #{c.model}, '%')
+                </if>
+                <if test="c.bomId != null">
+                    and tr.bom_id = #{c.bomId}
+                </if>
+                <if test="c.processRouteCode != null and c.processRouteCode != ''">
+                    and tr.process_route_code like concat('%', #{c.processRouteCode}, '%')
+                </if>
+                <if test="c.description != null and c.description != ''">
+                    and tr.description like concat('%', #{c.description}, '%')
+                </if>
+            </if>
+        </where>
+        order by tr.id desc
+    </select>
+
+    <update id="updateProductModelByBomId">
+        update technology_routing
+        set product_model_id = #{productModelId}
+        where bom_id = #{bomId}
+    </update>
+</mapper>
diff --git a/src/main/resources/mapper/technology/TechnologyRoutingOperationMapper.xml b/src/main/resources/mapper/technology/TechnologyRoutingOperationMapper.xml
new file mode 100644
index 0000000..1bbb25c
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyRoutingOperationMapper.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyRoutingOperation">
+        <id column="id" property="id" />
+        <result column="technology_routing_id" property="technologyRoutingId" />
+        <result column="product_model_id" property="productModelId" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="drag_sort" property="dragSort" />
+        <result column="is_quality" property="isQuality" />
+        <result column="create_user" property="createUser" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="pageTechnologyRoutingOperation" resultType="com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo">
+        select tro.*,
+               top2.name as technologyOperationName,
+               p.product_name as productName,
+               pm.model,
+               pm.model as specificationName,
+               pm.unit
+        from technology_routing_operation tro
+                 left join technology_operation top2 on tro.technology_operation_id = top2.id
+                 left join product_model pm on tro.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+        <where>
+            <if test="c != null">
+                <if test="c.id != null">
+                    and tro.id = #{c.id}
+                </if>
+                <if test="c.technologyRoutingId != null">
+                    and tro.technology_routing_id = #{c.technologyRoutingId}
+                </if>
+                <if test="c.routeId != null">
+                    and tro.technology_routing_id = #{c.routeId}
+                </if>
+                <if test="c.productModelId != null">
+                    and tro.product_model_id = #{c.productModelId}
+                </if>
+                <if test="c.technologyOperationId != null">
+                    and tro.technology_operation_id = #{c.technologyOperationId}
+                </if>
+                <if test="c.isQuality != null">
+                    and tro.is_quality = #{c.isQuality}
+                </if>
+            </if>
+        </where>
+        order by tro.drag_sort asc, tro.id asc
+    </select>
+
+    <select id="listTechnologyRoutingOperation" resultType="com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo">
+        select tro.*,
+               top2.name as technologyOperationName,
+               p.product_name as productName,
+               pm.model,
+               pm.model as specificationName,
+               pm.unit
+        from technology_routing_operation tro
+                 left join technology_operation top2 on tro.technology_operation_id = top2.id
+                 left join product_model pm on tro.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+        <where>
+            <if test="c != null">
+                <if test="c.id != null">
+                    and tro.id = #{c.id}
+                </if>
+                <if test="c.technologyRoutingId != null">
+                    and tro.technology_routing_id = #{c.technologyRoutingId}
+                </if>
+                <if test="c.routeId != null">
+                    and tro.technology_routing_id = #{c.routeId}
+                </if>
+                <if test="c.productModelId != null">
+                    and tro.product_model_id = #{c.productModelId}
+                </if>
+                <if test="c.technologyOperationId != null">
+                    and tro.technology_operation_id = #{c.technologyOperationId}
+                </if>
+                <if test="c.isQuality != null">
+                    and tro.is_quality = #{c.isQuality}
+                </if>
+            </if>
+        </where>
+        order by tro.drag_sort asc, tro.id asc
+    </select>
+
+    <select id="getTechnologyRoutingOperationInfo" resultType="com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo">
+        select tro.*,
+               top2.name as technologyOperationName,
+               p.product_name as productName,
+               pm.model,
+               pm.model as specificationName,
+               pm.unit
+        from technology_routing_operation tro
+                 left join technology_operation top2 on tro.technology_operation_id = top2.id
+                 left join product_model pm on tro.product_model_id = pm.id
+                 left join product p on pm.product_id = p.id
+        where tro.id = #{id}
+        limit 1
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/technology/TechnologyRoutingOperationParamMapper.xml b/src/main/resources/mapper/technology/TechnologyRoutingOperationParamMapper.xml
new file mode 100644
index 0000000..1a82456
--- /dev/null
+++ b/src/main/resources/mapper/technology/TechnologyRoutingOperationParamMapper.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.technology.mapper.TechnologyRoutingOperationParamMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.technology.pojo.TechnologyRoutingOperationParam">
+        <id column="id" property="id" />
+        <result column="param_code" property="paramCode" />
+        <result column="param_name" property="paramName" />
+        <result column="param_type" property="paramType" />
+        <result column="param_format" property="paramFormat" />
+        <result column="unit" property="unit" />
+        <result column="is_required" property="isRequired" />
+        <result column="remark" property="remark" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="dept_id" property="deptId" />
+        <result column="param_id" property="paramId" />
+        <result column="technology_operation_id" property="technologyOperationId" />
+        <result column="technology_operation_param_id" property="technologyOperationParamId" />
+        <result column="technology_routing_operation_id" property="technologyRoutingOperationId" />
+        <result column="standard_value" property="standardValue" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/my-prompt-template.txt b/src/main/resources/my-prompt-template.txt
new file mode 100644
index 0000000..3ae68b1
--- /dev/null
+++ b/src/main/resources/my-prompt-template.txt
@@ -0,0 +1,2 @@
+浣犳槸鎴戠殑濂芥湅鍙嬶紝璇风敤涓滃寳璇濆洖绛旈棶棰橈紝鍥炵瓟闂鐨勬椂鍊欓�傚綋娣诲姞琛ㄦ儏绗﹀彿銆�
+浠婂ぉ鏄� {{current_date}}銆�
\ No newline at end of file
diff --git a/src/main/resources/my-prompt-template3.txt b/src/main/resources/my-prompt-template3.txt
new file mode 100644
index 0000000..3041d9a
--- /dev/null
+++ b/src/main/resources/my-prompt-template3.txt
@@ -0,0 +1,3 @@
+浣犳槸鎴戠殑濂芥湅鍙嬶紝鎴戞槸{{username}}锛屾垜鐨勫勾榫勬槸{{age}}锛岃鐢ㄤ笢鍖楄瘽鍥炵瓟闂锛屽洖绛旈棶棰樼殑鏃跺�欓�傚綋娣诲姞琛ㄦ儏
+绗﹀彿銆�
+浠婂ぉ鏄� {{current_date}}銆�
\ No newline at end of file
diff --git a/src/main/resources/mybatis/mybatis-config.xml b/src/main/resources/mybatis/mybatis-config.xml
index ee4d2a1..7259bd8 100644
--- a/src/main/resources/mybatis/mybatis-config.xml
+++ b/src/main/resources/mybatis/mybatis-config.xml
@@ -12,8 +12,7 @@
         <!-- 閰嶇疆榛樿鐨勬墽琛屽櫒.SIMPLE灏辨槸鏅�氭墽琛屽櫒;REUSE鎵ц鍣ㄤ細閲嶇敤棰勫鐞嗚鍙�(prepared statements);BATCH鎵ц鍣ㄥ皢閲嶇敤璇彞骞舵墽琛屾壒閲忔洿鏂� -->
         <setting name="defaultExecutorType"      value="SIMPLE" />
 		<!-- 鎸囧畾 MyBatis 鎵�鐢ㄦ棩蹇楃殑鍏蜂綋瀹炵幇 -->
-        <setting name="logImpl"                  value="SLF4J"  />
-<!--        <setting name="logImpl"                  value="org.apache.ibatis.logging.stdout.StdOutImpl"  />-->
+        <setting name="logImpl"                  value="org.apache.ibatis.logging.stdout.StdOutImpl"  />
         <!-- 浣跨敤椹煎嘲鍛藉悕娉曡浆鎹㈠瓧娈� -->
 		<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
 	</settings>
diff --git a/src/main/resources/purchase-agent-prompt.txt b/src/main/resources/purchase-agent-prompt.txt
new file mode 100644
index 0000000..97f7eb2
--- /dev/null
+++ b/src/main/resources/purchase-agent-prompt.txt
@@ -0,0 +1,14 @@
+浣犳槸浼佷笟閲囪喘鏅鸿兘鍔╃悊銆�
+浣犵殑鐩爣鏄府鍔╃敤鎴峰揩閫熷畬鎴愰噰璐浉鍏充俊鎭煡璇笌瑙h銆�
+
+宸ヤ綔瑙勫垯锛�
+1. 浼樺厛璋冪敤宸ュ叿鍑芥暟鑾峰彇閲囪喘鍙拌处銆佷粯娆俱�佸彂绁ㄣ�侀��璐х瓑缁撴瀯鍖栨暟鎹��
+2. 閬囧埌鈥滅粺璁�/鍒嗘瀽/鎶ヨ〃/浠婂勾/鏈湀/杩慩X澶┾�濈瓑闇�姹傦紝浼樺厛缁欏嚭缁熻缁撴灉鍜屽叧閿粨璁恒��
+3. 鐢ㄦ埛闂�滄湰鏈堥噰璐噾棰濇帓鍚嶉潬鍓嶇殑鐗╂枡鈥濃�滈噰璐噾棰濇帓琛屸�濃�滅墿鏂欐帓琛屸�濇椂锛岃皟鐢ㄢ�滈噰璐墿鏂欓噾棰濇帓琛屸�濄��
+4. 鐢ㄦ埛闂�滃摢浜涢噰璐鍗曡繕鏈叆搴撯�濃�滄湭鍏ュ簱閲囪喘鍗曗�濃�滃緟鍏ュ簱璁㈠崟鈥濇椂锛岃皟鐢ㄢ�滄煡璇㈡湭鍏ュ簱閲囪喘璁㈠崟鈥濄��
+5. 鐢ㄦ埛闂�滄渶杩�7澶╀緵搴斿晢鍒拌揣寮傚父鈥濃�滃埌璐ч棶棰樷�濃�滃埌璐у紓甯糕�濇椂锛岃皟鐢ㄢ�滄煡璇㈤噰璐埌璐у紓甯糕�濄��
+6. 鐢ㄦ埛闂�滃緟浠樻閲囪喘鍗曗�濃�滄湭浠樻閲囪喘鍗曗�濃�滄湭浠樻竻閲囪喘璁㈠崟鈥濇椂锛岃皟鐢ㄢ�滄煡璇㈠緟浠樻閲囪喘鍗曗�濄��
+7. 鐢ㄦ埛闂�滄湰鏈堥噰璐��璐ф儏鍐碘�濃�滈噰璐��璐у垪琛ㄢ�濃�滈��鏂�/鎷掓敹鎯呭喌鈥濇椂锛岃皟鐢ㄢ�滄煡璇㈤噰璐��璐ф儏鍐碘�濄��
+8. 缁撴灉鐢ㄧ畝娲佷腑鏂囧洖绛旓紝鍏堢粰缁撹锛屽啀缁欏叧閿暟鎹偣銆�
+9. 涓嶈缂栭�犻噰璐暟鎹紝鎵�鏈夌粨璁哄繀椤诲熀浜庡伐鍏疯繑鍥炪��
+10. 鏃犳硶鐩存帴寰楀嚭缁撹鏃讹紝鏄庣‘璇存槑缂哄皯鍝簺瀛楁鎴栫瓫閫夋潯浠躲��
diff --git a/src/main/resources/static/work-order-template.docx b/src/main/resources/static/work-order-template.docx
index b90b5b8..bb247fe 100644
--- a/src/main/resources/static/work-order-template.docx
+++ b/src/main/resources/static/work-order-template.docx
Binary files differ
diff --git a/src/main/resources/vm/java/controller.java.vm b/src/main/resources/vm/java/controller.java.vm
index e9c5cb7..8f5565a 100644
--- a/src/main/resources/vm/java/controller.java.vm
+++ b/src/main/resources/vm/java/controller.java.vm
@@ -1,7 +1,7 @@
 package ${packageName}.controller;
 
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;

--
Gitblit v1.9.3