From 2d1e904f3049218474318cb1e2fe5c3a3869cfb0 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 29 一月 2026 16:47:34 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New' into dev_New

---
 src/main/java/com/ruoyi/safe/controller/SafeTrainingDetailsController.java      |   45 +
 src/main/java/com/ruoyi/safe/service/SafeTrainingFileService.java               |   16 
 src/main/java/com/ruoyi/production/dto/ProductOrderDto.java                     |    3 
 src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java           |    7 
 src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java    |   95 ++-
 src/main/java/com/ruoyi/sales/service/ShippingInfoService.java                  |    2 
 src/main/java/com/ruoyi/safe/mapper/SafeTrainingMapper.java                     |   25 
 src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java          |  179 ++++++
 src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java                 |   11 
 src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java           |    6 
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java         |   18 
 src/main/resources/mapper/production/ProductOrderMapper.xml                     |    3 
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                    |    3 
 src/main/java/com/ruoyi/ScheduleTask.java                                       |   58 ++
 src/main/java/com/ruoyi/safe/service/impl/SafeTrainingFileServiceImpl.java      |   20 
 src/main/java/com/ruoyi/safe/dto/SafeTrainingDto.java                           |   26 
 src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java   |    3 
 src/main/resources/mapper/safe/SafeAccidentMapper.xml                           |    8 
 src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java        |    8 
 src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java           |    5 
 src/main/resources/mapper/safe/SafeTrainingDetailsMapper.xml                    |   37 +
 src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java        |   50 +
 src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java    |    1 
 src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java |  144 ++--
 src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java                         |   57 ++
 src/main/java/com/ruoyi/safe/service/SafeTrainingService.java                   |   33 +
 src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java            |    2 
 src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java                    |    3 
 src/main/resources/static/safe-training.docx                                    |    0 
 src/main/java/com/ruoyi/safe/pojo/SafeTraining.java                             |  123 ++++
 src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java             |    2 
 src/main/resources/static/safe-training-details.docx                            |    0 
 src/main/java/com/ruoyi/safe/mapper/SafeTrainingFileMapper.java                 |   18 
 src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java                           |    3 
 src/main/resources/mapper/sales/SalesLedgerMapper.xml                           |   39 
 src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java             |   81 ++
 src/main/java/com/ruoyi/sales/pojo/SalesLedger.java                             |    9 
 src/main/resources/mapper/safe/SafeTrainingFileMapper.xml                       |   19 
 src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java                    |   29 +
 src/main/java/com/ruoyi/safe/mapper/SafeTrainingDetailsMapper.java              |   27 
 src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java            |    4 
 src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java     |   67 +
 src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java   |   81 ++
 src/main/resources/mapper/sales/ShippingInfoMapper.xml                          |    2 
 src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java            |   24 
 src/main/java/com/ruoyi/safe/controller/SafeTrainingFileController.java         |   72 ++
 src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java                    |    2 
 src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java                      |   95 +++
 src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java                |   31 
 src/main/resources/mapper/safe/SafeTrainingMapper.xml                           |   59 ++
 50 files changed, 1,455 insertions(+), 200 deletions(-)

diff --git a/src/main/java/com/ruoyi/ScheduleTask.java b/src/main/java/com/ruoyi/ScheduleTask.java
new file mode 100644
index 0000000..9913292
--- /dev/null
+++ b/src/main/java/com/ruoyi/ScheduleTask.java
@@ -0,0 +1,58 @@
+package com.ruoyi;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.project.system.domain.SysNotice;
+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 org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+@Component
+//瀹氭椂浠诲姟姹囨��
+public class ScheduleTask {
+
+    @Autowired
+    private SafeTrainingMapper safeTrainingMapper;
+
+    @Autowired
+    private SysNoticeMapper noticeMapper;
+
+    //瀹氭椂浠诲姟(15鍒嗛挓鎵ц涓�娆�--鍒ゆ柇鍩硅璁″垝鏁版嵁,鐘舵�佸仛鍙樻洿)
+    @Scheduled(cron = "0 0/15 * * * ?")
+    public void testScheduleTask() {
+        List<SafeTraining> safeTrainings = safeTrainingMapper.selectList(Wrappers.<SafeTraining>lambdaQuery().ne(SafeTraining::getState, 2));
+        if (safeTrainings.size() > 0) {
+            for (SafeTraining safeTraining : safeTrainings) {
+                //鏍规嵁鏃堕棿鍒ゆ柇鍩硅鐘舵��
+                String trainingDate = safeTraining.getTrainingDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+                LocalDateTime openingTime = LocalDateTime.parse((trainingDate + safeTraining.getOpeningTime()), DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss"));
+                LocalDateTime endTime = LocalDateTime.parse((trainingDate + safeTraining.getEndTime()), DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss"));
+                if (LocalDateTime.now().isBefore(openingTime)) {
+                    //鏈紑濮�
+                    safeTraining.setState(0);
+                } else if (LocalDateTime.now().isAfter(endTime)) {
+                    //宸茬粨鏉�
+                    safeTraining.setState(2);
+                } else {
+                    //杩涜涓�
+                    safeTraining.setState(1);
+                }
+                safeTrainingMapper.updateById(safeTraining);
+            }
+        }
+    }
+
+    //宸茶鏁版嵁鍋氫竴涓畾鏃朵换鍔�(姣忔湀1鍙�1鐐规竻鐞嗕竴娆′笂涓湀宸茶鏁版嵁)
+    @Scheduled(cron = "0 0 1 1 * ?")
+    public void cleanReadData() {
+        noticeMapper.delete(Wrappers.<SysNotice>lambdaQuery()
+                .eq(SysNotice::getStatus,"1")
+                .lt(SysNotice::getCreateTime, LocalDateTime.now()));
+    }
+}
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 5ff767c..55d2ed0 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -1,6 +1,7 @@
 package com.ruoyi.approve.service.impl;
 
 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;
@@ -12,20 +13,21 @@
 import com.ruoyi.approve.service.IApproveNodeService;
 import com.ruoyi.approve.vo.ApproveProcessVO;
 import com.ruoyi.common.enums.FileNameType;
+import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
 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.sales.mapper.CommonFileMapper;
-import com.ruoyi.sales.mapper.SalesQuotationMapper;
-import com.ruoyi.sales.mapper.SalesQuotationProductMapper;
-import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.purchase.service.impl.PurchaseLedgerServiceImpl;
+import com.ruoyi.sales.mapper.*;
 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;
@@ -42,7 +44,7 @@
 import java.util.List;
 
 @Service
-@RequiredArgsConstructor
+//@RequiredArgsConstructor
 public class ApproveNodeServiceImpl extends ServiceImpl<ApproveNodeMapper, ApproveNode> implements IApproveNodeService {
 
     @Autowired
@@ -73,7 +75,13 @@
 
     @Autowired
     private CommonFileServiceImpl commonFileService;
+    @Autowired
+    private StockUtils stockUtils;
+    @Autowired
+    private SalesLedgerProductMapper salesLedgerProductMapper;
 
+    @Autowired
+    private PurchaseLedgerServiceImpl purchaseLedgerServiceImpl;
 
 
     public ApproveProcess getApproveById(String id) {
@@ -186,6 +194,17 @@
                 if (status.equals(2)) {
                     // 鍚屾剰
                     purchaseLedger.setApprovalStatus(3);
+                    List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper<SalesLedgerProduct>()
+                            .lambda().eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()).eq(SalesLedgerProduct::getType, 2));
+                    for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
+                        // 璐ㄦ
+                        if (salesLedgerProduct.getIsChecked()) {
+                            purchaseLedgerServiceImpl.addQualityInspect(purchaseLedger, salesLedgerProduct);
+                        }else {
+                            //鐩存帴鍏ュ簱
+                            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId());
+                        }
+                    }
                 } else if (status.equals(3)) {
                     // 鎷掔粷
                     purchaseLedger.setApprovalStatus(4);
@@ -222,7 +241,7 @@
                 if(status.equals(2)){
                     shippingInfo.setStatus("瀹℃牳閫氳繃");
                 }else if(status.equals(3)){
-                    shippingInfo.setType("瀹℃牳鎷掔粷");
+                    shippingInfo.setStatus("瀹℃牳鎷掔粷");
                 }else if(status.equals(1)){
                     shippingInfo.setStatus("瀹℃牳涓�");
                 }
@@ -248,10 +267,17 @@
                         .eq(ApproveProcess::getApproveId, approveNode.getApproveProcessId())).get(0);
                 if (approveProcess.getApproveUserIds().split(",").length > nodeOrder){
                     String id = approveProcess.getApproveUserIds().split(",")[nodeOrder];
-                    sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
-                            approveNode.getApproveProcessId()+"娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                            Arrays.asList(Long.valueOf(id)),
-                            "/collaborativeApproval/approvalProcess?approveType="+approveProcess.getApproveType()+"&approveId="+approveNode.getApproveProcessId());
+                    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 {
+                        sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
+                                approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
+                                Arrays.asList(Long.valueOf(id)),
+                                "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
+                    }
                 }
                 break;
             case 2:
@@ -294,7 +320,9 @@
             case 6:
                 return "鎶ヤ环瀹℃壒";
             case 7:
-                return "鍑哄簱瀹℃壒";
+                return "鍙戣揣瀹℃壒";
+            case 8:
+                return "鍗遍櫓浣滀笟瀹℃壒";
         }
         return null;
     }
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 adf14c8..14fe835 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -51,22 +51,30 @@
 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");
 
-    private final StringRedisTemplate redisTemplate;
-
-    private final DailyRedisCounter dailyRedisCounter;
-
-    private final SysDeptMapper sysDeptMapper;
-    private final IApproveNodeService approveNodeService;
-    private final SysUserMapper sysUserMapper;
-    private final ApproveProcessMapper approveProcessMapper;
-    private final TempFileServiceImpl tempFileService;
-    private final CommonFileMapper commonFileMapper;
-    private final CommonFileServiceImpl commonFileService;
-    private final ISysNoticeService sysNoticeService;
+    @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;
 
     @Override
     public void addApprove(ApproveProcessVO approveProcessVO) throws Exception {
@@ -126,10 +134,17 @@
         tempFileService.migrateTempFilesToFormal(approveProcess.getId(), approveProcessVO.getTempFileIds(), FileNameType.ApproveProcess.getValue());
         /*娑堟伅閫氱煡*/
         String id = approveProcessVO.getApproveUserIds().split(",")[0];
-        sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcessVO.getApproveType()),
-                approveID + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                Arrays.asList(Long.valueOf(id)),
-                "/collaborativeApproval/approvalProcess?approveType=" + approveProcessVO.getApproveType() + "&approveId=" + approveID);
+        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 {
+            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
+                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
+                    Arrays.asList(Long.valueOf(id)),
+                    "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
+        }
     }
 
     @Override
@@ -239,7 +254,8 @@
         return one;
     }
 
-    private final ApproveNodeMapper approveNodeMapper;
+    @Autowired
+    private ApproveNodeMapper approveNodeMapper;
 
     // 鎶ヤ环瀹℃壒缂栬緫瀹℃牳浜�
     public void updateApproveUser(ApproveGetAndUpdateVo approveGetAndUpdateVo) {
@@ -276,10 +292,17 @@
         approveNodeService.initApproveNodes(approveGetAndUpdateVo.getApproveUserIds(), approveProcess.getApproveId(), approveProcess.getTenantId());
         /*娑堟伅閫氱煡*/
         String id = approveProcess.getApproveUserIds().split(",")[0];
-        sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
-                approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
-                Arrays.asList(Long.valueOf(id)),
-                "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
+        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 {
+            sysNoticeService.simpleNoticeByUser(approveProcessType(approveProcess.getApproveType()),
+                    approveProcess.getApproveId() + "娴佺▼缂栧彿鐨勫鎵归渶瑕佹偍瀹℃牳!!!!!",
+                    Arrays.asList(Long.valueOf(id)),
+                    "/collaborativeApproval/approvalProcess?approveType=" + approveProcess.getApproveType() + "&approveId=" + approveProcess.getApproveId());
+        }
     }
 
 
diff --git a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
index 9d87223..819ce65 100644
--- a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
+++ b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -1,6 +1,7 @@
 package com.ruoyi.procurementrecord.utils;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+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;
@@ -101,14 +102,16 @@
         StockInRecord one = stockInRecordService.getOne(new QueryWrapper<StockInRecord>()
                 .lambda().eq(StockInRecord::getRecordId, recordId)
                 .eq(StockInRecord::getRecordType, recordType));
-
-        stockInRecordService.batchDelete(Collections.singletonList(one.getId()));
+        if (ObjectUtils.isNotEmpty(one)) {
+            stockInRecordService.batchDelete(Collections.singletonList(one.getId()));
+        }
     }
     public void deleteStockOutRecord(Long recordId, String recordType) {
         StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>()
                 .lambda().eq(StockOutRecord::getRecordId, recordId)
                 .eq(StockOutRecord::getRecordType, recordType));
-
-        stockOutRecordService.batchDelete(Collections.singletonList(one.getId()));
+        if (ObjectUtils.isNotEmpty(one)) {
+            stockOutRecordService.batchDelete(Collections.singletonList(one.getId()));
+        }
     }
 }
diff --git a/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java b/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
index b12803d..fe989ba 100644
--- a/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
+++ b/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
@@ -43,4 +43,7 @@
     @ApiModelProperty(value = "BOM缂栧彿")
     @Excel(name = "BOM缂栧彿")
     private String bomNo;
+
+    @ApiModelProperty(value = "浜ゆ湡鍋忓樊")
+    private Integer deliveryDaysDiff;
 }
diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java
index 0b4dae4..942a700 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java
@@ -1,19 +1,22 @@
 package com.ruoyi.project.system.mapper;
 
 import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import com.ruoyi.project.system.domain.SysDept;
 
 /**
  * 閮ㄩ棬绠$悊 鏁版嵁灞�
- * 
+ *
  * @author ruoyi
  */
+@Mapper
 public interface SysDeptMapper
 {
     /**
      * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
-     * 
+     *
      * @param dept 閮ㄩ棬淇℃伅
      * @return 閮ㄩ棬淇℃伅闆嗗悎
      */
@@ -21,7 +24,7 @@
 
     /**
      * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
-     * 
+     *
      * @param roleId 瑙掕壊ID
      * @param deptCheckStrictly 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
      * @return 閫変腑閮ㄩ棬鍒楄〃
@@ -30,7 +33,7 @@
 
     /**
      * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
-     * 
+     *
      * @param deptId 閮ㄩ棬ID
      * @return 閮ㄩ棬淇℃伅
      */
@@ -38,7 +41,7 @@
 
     /**
      * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬
-     * 
+     *
      * @param deptId 閮ㄩ棬ID
      * @return 閮ㄩ棬鍒楄〃
      */
@@ -46,7 +49,7 @@
 
     /**
      * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
-     * 
+     *
      * @param deptId 閮ㄩ棬ID
      * @return 瀛愰儴闂ㄦ暟
      */
@@ -54,7 +57,7 @@
 
     /**
      * 鏄惁瀛樺湪瀛愯妭鐐�
-     * 
+     *
      * @param deptId 閮ㄩ棬ID
      * @return 缁撴灉
      */
@@ -62,7 +65,7 @@
 
     /**
      * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
-     * 
+     *
      * @param deptId 閮ㄩ棬ID
      * @return 缁撴灉
      */
@@ -70,7 +73,7 @@
 
     /**
      * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
-     * 
+     *
      * @param deptName 閮ㄩ棬鍚嶇О
      * @param parentId 鐖堕儴闂↖D
      * @return 缁撴灉
@@ -79,7 +82,7 @@
 
     /**
      * 鏂板閮ㄩ棬淇℃伅
-     * 
+     *
      * @param dept 閮ㄩ棬淇℃伅
      * @return 缁撴灉
      */
@@ -87,7 +90,7 @@
 
     /**
      * 淇敼閮ㄩ棬淇℃伅
-     * 
+     *
      * @param dept 閮ㄩ棬淇℃伅
      * @return 缁撴灉
      */
@@ -95,14 +98,14 @@
 
     /**
      * 淇敼鎵�鍦ㄩ儴闂ㄦ甯哥姸鎬�
-     * 
+     *
      * @param deptIds 閮ㄩ棬ID缁�
      */
     public void updateDeptStatusNormal(Long[] deptIds);
 
     /**
      * 淇敼瀛愬厓绱犲叧绯�
-     * 
+     *
      * @param depts 瀛愬厓绱�
      * @return 缁撴灉
      */
@@ -110,7 +113,7 @@
 
     /**
      * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
-     * 
+     *
      * @param deptId 閮ㄩ棬ID
      * @return 缁撴灉
      */
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 bf794b5..679514d 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,5 +1,6 @@
 package com.ruoyi.project.system.service.impl;
 
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -22,6 +23,7 @@
 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;
@@ -210,4 +212,5 @@
         sysNotice.setTenantId(tenantId);
         return sysNotice;
     }
+
 }
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 e5942a2..37ca018 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -55,6 +55,7 @@
 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;
@@ -84,52 +85,71 @@
  * @date 2025-05-09
  */
 @Service
-@RequiredArgsConstructor
 @Slf4j
 public class PurchaseLedgerServiceImpl extends ServiceImpl<PurchaseLedgerMapper, PurchaseLedger> implements IPurchaseLedgerService {
-    private final AccountExpenseService accountExpenseService;
-    private final PurchaseLedgerMapper purchaseLedgerMapper;
+    @Autowired
+    private  AccountExpenseService accountExpenseService;
+    @Autowired
+    private  PurchaseLedgerMapper purchaseLedgerMapper;
 
-    private final SalesLedgerMapper salesLedgerMapper;
-    private final SalesLedgerProductMapper salesLedgerProductMapper;
+    @Autowired
+    private  SalesLedgerMapper salesLedgerMapper;
+    @Autowired
+    private  SalesLedgerProductMapper salesLedgerProductMapper;
 
-    private final SysUserMapper userMapper;
+    @Autowired
+    private  SysUserMapper userMapper;
 
-    private final TempFileMapper tempFileMapper;
+    @Autowired
+    private  TempFileMapper tempFileMapper;
 
-    private final CommonFileMapper commonFileMapper;
+    @Autowired
+    private  CommonFileMapper commonFileMapper;
 
-    private final SupplierManageMapper supplierManageMapper;
+    @Autowired
+    private  SupplierManageMapper supplierManageMapper;
 
-    private final ProductMapper productMapper;
+    @Autowired
+    private  ProductMapper productMapper;
 
-    private final ProductModelMapper productModelMapper;
+    @Autowired
+    private  ProductModelMapper productModelMapper;
 
-    private final SysUserMapper sysUserMapper;
+    @Autowired
+    private  SysUserMapper sysUserMapper;
 
-    private final TicketRegistrationMapper ticketRegistrationMapper;
+    @Autowired
+    private  TicketRegistrationMapper ticketRegistrationMapper;
 
-    private final ProductRecordMapper productRecordMapper;
+    @Autowired
+    private  ProductRecordMapper productRecordMapper;
 
-    private final PaymentRegistrationMapper paymentRegistrationMapper;
-
-    private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper;
-
-    private final StringRedisTemplate redisTemplate;
-    private final QualityInspectMapper qualityInspectMapper;
-    private final CommonFileServiceImpl commonFileService;
-    private final QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
-    private final QualityTestStandardParamMapper qualityTestStandardParamMapper;
-    private final QualityTestStandardMapper qualityTestStandardMapper;
-    private final QualityInspectParamMapper qualityInspectParamMapper;
-
-    private final ApproveProcessServiceImpl approveProcessService;
-
-    private final ProcurementRecordMapper procurementRecordStorageMapper;
-
-    private final PurchaseLedgerTemplateMapper purchaseLedgerTemplateMapper;
-
-    private final SalesLedgerProductTemplateMapper salesLedgerProductTemplateMapper;
+    @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;
 
@@ -205,7 +225,8 @@
         return 1;
     }
 
-    private void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct) {
+
+    public void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct) {
         QualityInspect qualityInspect = new QualityInspect();
         qualityInspect.setInspectType(0);
         qualityInspect.setSupplier(purchaseLedger.getSupplierName());
@@ -400,6 +421,12 @@
         if (ids == null || ids.length == 0) {
            throw new BaseException("璇烽�変腑鑷冲皯涓�鏉℃暟鎹�");
         }
+        for (Long id : ids) {
+            PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id);
+            if (purchaseLedger.getApprovalStatus().equals(3)) {
+                throw new BaseException(purchaseLedger.getPurchaseContractNumber()+"宸茬粡瀹℃壒閫氳繃锛屼笉鍏佽鍒犻櫎");
+            }
+        }
         // 鎵归噺鍒犻櫎鍏宠仈鐨勯噰璐叆搴撹褰�
         LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductQueryWrapper = new LambdaQueryWrapper<>();
         salesLedgerProductQueryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids)
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
index 1cce084..b015150 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
@@ -29,6 +29,7 @@
      */
     @PostMapping("/add")
     public AjaxResult add(@RequestBody QualityUnqualified qualityUnqualified) {
+        qualityUnqualified.setInspectState(0);
         return AjaxResult.success(qualityUnqualifiedService.save(qualityUnqualified));
     }
 
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 b33ba5c..0e8497a 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -63,82 +63,84 @@
     public int deal(QualityUnqualified qualityUnqualified) {
         QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId());
         QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
-        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) {
-                            // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶у伐鍗曞彿
-                            QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
-                            queryWrapper.likeRight("work_order_no", datePrefix)
-                                    .orderByDesc("work_order_no")
-                                    .last("LIMIT 1");
-                            ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectOne(queryWrapper);
-                            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;
+        if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType()!=0) {
+            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) {
+                                // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶у伐鍗曞彿
+                                QueryWrapper<ProductWorkOrder> queryWrapper = new QueryWrapper<>();
+                                queryWrapper.likeRight("work_order_no", datePrefix)
+                                        .orderByDesc("work_order_no")
+                                        .last("LIMIT 1");
+                                ProductWorkOrder lastWorkOrder = productWorkOrderMapper.selectOne(queryWrapper);
+                                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 = 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);
                             }
-                            // 鐢熸垚瀹屾暣鐨勫伐鍗曞彿
-                            String workOrderNoStr = 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);
                         }
                     }
-                }
-                break;
-            case "鎶ュ簾":
-                //璋冪敤涓嶅悎鏍煎簱瀛樻帴鍙� 鍏ヤ笉鍚堟牸搴�
-                stockUtils.addUnStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(),unqualified.getId());
-                break;
-            case "璁╂鏀捐":
-                //璋冪敤鎻愪氦鍚堟牸鐨勬帴鍙�
-                stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(),unqualified.getId());
-                qualityInspect.setCheckResult("鍚堟牸");
-                qualityInspectService.submit(qualityInspect);
-                break;
-            default:
-                break;
+                    break;
+                case "鎶ュ簾":
+                    //璋冪敤涓嶅悎鏍煎簱瀛樻帴鍙� 鍏ヤ笉鍚堟牸搴�
+                    stockUtils.addUnStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId());
+                    break;
+                case "璁╂鏀捐":
+                    //璋冪敤鎻愪氦鍚堟牸鐨勬帴鍙�
+                    stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
+                    qualityInspect.setCheckResult("鍚堟牸");
+                    qualityInspectService.submit(qualityInspect);
+                    break;
+                default:
+                    break;
+            }
         }
         qualityUnqualified.setInspectState(1);//宸插鐞�
         return qualityUnqualifiedMapper.updateById(qualityUnqualified);
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java b/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
index 615514a..3db1660 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
@@ -48,7 +48,7 @@
 
     @ApiOperation("鍒犻櫎浜嬫晠涓婃姤璁板綍")
     @DeleteMapping("/{ids}")
-    public R delSafeCertification(@RequestBody List<Integer> ids) {
+    public R delSafeAccident(@RequestBody List<Integer> ids) {
         return R.ok(safeAccidentService.removeBatchByIds(ids));
     }
 
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java b/src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java
new file mode 100644
index 0000000..3ea4689
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/controller/SafeTrainingController.java
@@ -0,0 +1,81 @@
+package com.ruoyi.safe.controller;
+
+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 org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:06
+ */
+@RestController
+@RequestMapping("/safeTraining")
+@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳")
+public class SafeTrainingController {
+
+    @Autowired
+    private SafeTrainingService safeTrainingService;
+
+    @Autowired
+    private SafeTrainingDetailsService safeTrainingDetailsService;
+
+    @GetMapping("/page")
+    @ApiOperation("鍒嗛〉鏌ヨ")
+    public R page(Page page, SafeTrainingDto safeTrainingDto) {
+        return R.ok(safeTrainingService.pageSafeTraining(page, safeTrainingDto));
+    }
+
+    @ApiOperation("鏂板/缂栬緫瀹夊叏鍩硅鑰冩牳")
+    @PostMapping()
+    public R addOrUpdate(@RequestBody SafeTraining safeTraining) {
+        return R.ok(safeTrainingService.addOrUpdate(safeTraining));
+    }
+
+    @ApiOperation("绛惧埌")
+    @PostMapping ("/sign")
+    public R sign(@RequestBody SafeTrainingDetails safeTrainingDetails) {
+        return R.ok(safeTrainingDetailsService.save(safeTrainingDetails));
+    }
+
+    @ApiOperation("缁撴灉鏄庣粏鏌ヨ")
+    @GetMapping ("/getSafeTraining")
+    public R getSafeTraining(Long id) {
+        return R.ok(safeTrainingService.getSafeTraining(id));
+    }
+
+    @ApiOperation("缁撴灉鏄庣粏淇濆瓨")
+    @PostMapping ("/saveSafeTraining")
+    public R saveSafeTraining(@RequestBody SafeTrainingDto safeTrainingDto) {
+        return R.ok(safeTrainingService.saveSafeTraining(safeTrainingDto));
+    }
+
+    @ApiOperation("鍒犻櫎瀹夊叏鍩硅鑰冩牳")
+    @DeleteMapping("/{ids}")
+    public R delSafeTraining(@RequestBody List<Integer> ids) {
+        return R.ok(safeTrainingService.delSafeTraining(ids));
+    }
+
+    @ApiOperation("瀵煎嚭")
+    @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
new file mode 100644
index 0000000..75bcfb9
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/controller/SafeTrainingDetailsController.java
@@ -0,0 +1,45 @@
+package com.ruoyi.safe.controller;
+
+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 org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:15
+ */
+@RestController
+@RequestMapping("/safeTrainingDetails")
+@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏")
+public class SafeTrainingDetailsController {
+
+
+    @Autowired
+    private SafeTrainingDetailsService safeTrainingDetailsService;
+
+    @GetMapping("/page")
+    @ApiOperation("鍒嗛〉鏌ヨ")
+    public R page(Page page, SafeTrainingDetails safeTrainingDetails) {
+        return R.ok(safeTrainingDetailsService.pageDetails(page, safeTrainingDetails));
+    }
+
+    @ApiOperation("瀵煎嚭")
+    @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
new file mode 100644
index 0000000..3057900
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/controller/SafeTrainingFileController.java
@@ -0,0 +1,72 @@
+package com.ruoyi.safe.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.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 org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:23
+ */
+@RestController
+@RequestMapping("/safeTrainingFile")
+@Api(tags = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢")
+public class SafeTrainingFileController {
+
+    @Resource
+    private SafeTrainingFileService safeTrainingFileService;
+
+
+    /**
+     * 鏂板
+     * @param safeHiddenFile
+     * @return
+     */
+    @PostMapping("/add")
+    @ApiOperation("鏂板")
+    public R add(@RequestBody SafeTrainingFile safeHiddenFile) {
+        return R.ok(safeTrainingFileService.save(safeHiddenFile));
+    }
+
+    /**
+     * 鍒犻櫎
+     * @param ids
+     * @return
+     */
+    @DeleteMapping("/del")
+    @ApiOperation("鍒犻櫎")
+    public R delSafeHiddenFile(@RequestBody List<Integer> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return R.fail("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        //鍒犻櫎妫�楠岄檮浠�
+        return R.ok(safeTrainingFileService.removeBatchByIds(ids));
+    }
+
+    /**
+     *鍒嗛〉鏌ヨ
+     * @param page
+     * @param safeTrainingFile
+     * @return
+     */
+    @GetMapping("/listPage")
+    @ApiOperation("鍒嗛〉鏌ヨ")
+    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/SafeTrainingDetailsDto.java b/src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java
new file mode 100644
index 0000000..0eb6da5
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/dto/SafeTrainingDetailsDto.java
@@ -0,0 +1,29 @@
+package com.ruoyi.safe.dto;
+
+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 lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+public class SafeTrainingDetailsDto extends SafeTrainingDetails {
+
+    @ApiModelProperty("鍩硅浜哄憳缂栧彿")
+    private String userName;
+
+    @ApiModelProperty("鍩硅浜哄憳鍚嶇О")
+    private String nickName;
+
+    @ApiModelProperty("鎵嬫満鍙风爜")
+    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
new file mode 100644
index 0000000..0b8d7cd
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/dto/SafeTrainingDto.java
@@ -0,0 +1,26 @@
+package com.ruoyi.safe.dto;
+
+import com.ruoyi.safe.pojo.SafeTraining;
+import com.ruoyi.safe.pojo.SafeTrainingDetails;
+import com.ruoyi.safe.pojo.SafeTrainingFile;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SafeTrainingDto extends SafeTraining {
+
+    @ApiModelProperty("鎶ュ悕浜烘暟")
+    private Integer nums;
+
+    @ApiModelProperty("璇勪环浜�")
+    private String assessmentUserName;
+
+    @ApiModelProperty("闄勪欢闆嗗悎")
+    private List<SafeTrainingFile> safeTrainingFileList;
+
+    @ApiModelProperty("鍩硅璁板綍浜哄憳璇︽儏闆嗗悎")
+    private List<SafeTrainingDetailsDto> safeTrainingDetailsDtoList;
+
+}
diff --git a/src/main/java/com/ruoyi/safe/mapper/SafeTrainingDetailsMapper.java b/src/main/java/com/ruoyi/safe/mapper/SafeTrainingDetailsMapper.java
new file mode 100644
index 0000000..2a05cf8
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/mapper/SafeTrainingDetailsMapper.java
@@ -0,0 +1,27 @@
+package com.ruoyi.safe.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.dto.SafeTrainingDetailsDto;
+import com.ruoyi.safe.pojo.SafeTrainingDetails;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:15
+ */
+@Mapper
+public interface SafeTrainingDetailsMapper extends BaseMapper<SafeTrainingDetails> {
+
+    List<SafeTrainingDetailsDto> getSafeTraining(@Param("id") Long id);
+
+    IPage<SafeTrainingDetails> pageDetails(Page page, @Param("c") SafeTrainingDetails safeTrainingDetails);
+}
diff --git a/src/main/java/com/ruoyi/safe/mapper/SafeTrainingFileMapper.java b/src/main/java/com/ruoyi/safe/mapper/SafeTrainingFileMapper.java
new file mode 100644
index 0000000..709df72
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/mapper/SafeTrainingFileMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.safe.mapper;
+
+import com.ruoyi.safe.pojo.SafeTrainingFile;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:23
+ */
+@Mapper
+public interface SafeTrainingFileMapper extends BaseMapper<SafeTrainingFile> {
+
+}
diff --git a/src/main/java/com/ruoyi/safe/mapper/SafeTrainingMapper.java b/src/main/java/com/ruoyi/safe/mapper/SafeTrainingMapper.java
new file mode 100644
index 0000000..a1fe28d
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/mapper/SafeTrainingMapper.java
@@ -0,0 +1,25 @@
+package com.ruoyi.safe.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.dto.SafeTrainingDto;
+import com.ruoyi.safe.pojo.SafeTraining;
+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-29 10:54:06
+ */
+@Mapper
+public interface SafeTrainingMapper extends BaseMapper<SafeTraining> {
+
+    IPage<SafeTrainingDto> pageSafeTraining(Page page, @Param("c") SafeTrainingDto safeTrainingDto);
+
+    SafeTrainingDto getSafeTraining(@Param("id") Long id);
+}
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeTraining.java b/src/main/java/com/ruoyi/safe/pojo/SafeTraining.java
new file mode 100644
index 0000000..f9ecc29
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeTraining.java
@@ -0,0 +1,123 @@
+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.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+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>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:06
+ */
+@Getter
+@Setter
+@TableName("safe_training")
+@ApiModel(value = "SafeTraining瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳")
+public class SafeTraining implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("璇剧▼缂栧彿")
+    private String courseCode;
+
+    @ApiModelProperty("鍩硅鐩爣")
+    private String trainingObjectives;
+
+    @ApiModelProperty("鍩硅鍐呭")
+    private String trainingContent;
+
+    @ApiModelProperty("鍩硅鏂瑰紡")
+    private String trainingMode;
+
+    @ApiModelProperty("鐘舵��(0锛氭湭寮�濮�1锛氳繘琛屼腑锛�2锛氬凡缁撴潫)")
+    private Integer state;
+
+    @ApiModelProperty("鍙傚姞瀵硅薄")
+    private String participants;
+
+    @ApiModelProperty("鍩硅鍦扮偣")
+    private String placeTraining;
+
+    @ApiModelProperty("鍩硅璁插笀")
+    private String trainingLecturer;
+
+    @ApiModelProperty("鍩硅鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @NotBlank(message = "鍩硅鏃ユ湡涓嶈兘涓虹┖")
+    private LocalDate trainingDate;
+
+    @ApiModelProperty("寮�濮嬫椂闂�(鏃跺垎绉�)")
+    @NotBlank(message = "寮�濮嬫椂闂翠笉鑳戒负绌�")
+    private String openingTime;
+
+    @ApiModelProperty("缁撴潫鏃堕棿(鏃跺垎绉�)")
+    @NotBlank(message = "缁撴潫鏃堕棿涓嶈兘涓虹┖")
+    private String endTime;
+
+    @ApiModelProperty("璇鹃瀛﹀垎")
+    private String projectCredits;
+
+    @ApiModelProperty("璇炬椂")
+    private Double classHour;
+
+    @ApiModelProperty("鑰冩牳鏂瑰紡")
+    private String assessmentMethod;
+
+    @ApiModelProperty("鏈鍩硅缁煎悎璇勪环")
+    private String comprehensiveAssessment;
+
+    @ApiModelProperty("澶囨敞")
+    private String remarks;
+
+    @ApiModelProperty("璇勪环浜篿d")
+    private Integer assessmentUserId;
+
+    @ApiModelProperty("璇勪环鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate assessmentDate;
+
+    @ApiModelProperty("鍩硅鎽樿")
+    private String trainingAbstract;
+
+    @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)
+    private Integer createUser;
+
+    @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_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer tenantId;
+}
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java
new file mode 100644
index 0000000..a53ea3d
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingDetails.java
@@ -0,0 +1,95 @@
+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.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>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:15
+ */
+@Getter
+@Setter
+@TableName("safe_training_details")
+@ApiModel(value = "SafeTrainingDetails瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏")
+public class SafeTrainingDetails implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty("鐢ㄦ埛琛ㄦ牸锛坲ser锛変富閿�")
+    @NotBlank(message = "鐢ㄦ埛id涓嶈兘涓虹┖")
+    private Long userId;
+
+    @ApiModelProperty("鍏宠仈瀹夊叏鍩硅鑰冩牳id")
+    private Integer safeTrainingId;
+
+    @ApiModelProperty("鑰冩牳缁撴灉")
+    private String examinationResults;
+
+    @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)
+    private Integer createUser;
+
+    @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_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer tenantId;
+
+
+    @ApiModelProperty("鍩硅鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @TableField(exist = false)
+    private LocalDate trainingDate;
+
+    @ApiModelProperty("璇剧▼缂栧彿")
+    @TableField(exist = false)
+    private String courseCode;
+
+    @ApiModelProperty("鍩硅鍐呭")
+    @TableField(exist = false)
+    private String trainingContent;
+
+    @ApiModelProperty("鍩硅璇炬椂")
+    @TableField(exist = false)
+    private Double classHour;
+
+    @ApiModelProperty("璇鹃瀛﹀垎")
+    @TableField(exist = false)
+    private String projectCredits;
+
+    @ApiModelProperty("澶囨敞")
+    @TableField(exist = false)
+    private String remarks;
+}
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java
new file mode 100644
index 0000000..9ed72a7
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeTrainingFile.java
@@ -0,0 +1,57 @@
+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.LocalDateTime;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:23
+ */
+@Getter
+@Setter
+@TableName("safe_training_file")
+@ApiModel(value = "SafeTrainingFile瀵硅薄", description = "瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢")
+public class SafeTrainingFile implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty("鍏宠仈瀹夊叏鍩硅鑰冩牳id")
+    private Integer safeTrainingId;
+
+    private String name;
+
+    private String url;
+
+    private Object fileSize;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer tenantId;
+}
diff --git a/src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java b/src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java
new file mode 100644
index 0000000..8a06f05
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/SafeTrainingDetailsService.java
@@ -0,0 +1,24 @@
+package com.ruoyi.safe.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.dto.SafeTrainingDto;
+import com.ruoyi.safe.pojo.SafeTrainingDetails;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:15
+ */
+public interface SafeTrainingDetailsService extends IService<SafeTrainingDetails> {
+
+    IPage<SafeTrainingDetails> pageDetails(Page page, SafeTrainingDetails safeTrainingDetails);
+
+    void export(HttpServletResponse response, Long userId);
+}
diff --git a/src/main/java/com/ruoyi/safe/service/SafeTrainingFileService.java b/src/main/java/com/ruoyi/safe/service/SafeTrainingFileService.java
new file mode 100644
index 0000000..7d17c41
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/SafeTrainingFileService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.safe.service;
+
+import com.ruoyi.safe.pojo.SafeTrainingFile;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:23
+ */
+public interface SafeTrainingFileService extends IService<SafeTrainingFile> {
+
+}
diff --git a/src/main/java/com/ruoyi/safe/service/SafeTrainingService.java b/src/main/java/com/ruoyi/safe/service/SafeTrainingService.java
new file mode 100644
index 0000000..56f2e6e
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/SafeTrainingService.java
@@ -0,0 +1,33 @@
+package com.ruoyi.safe.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.dto.SafeTrainingDto;
+import com.ruoyi.safe.pojo.SafeTraining;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:06
+ */
+public interface SafeTrainingService extends IService<SafeTraining> {
+
+    IPage<SafeTrainingDto> pageSafeTraining(Page page, SafeTrainingDto safeTrainingDto);
+
+    int addOrUpdate(SafeTraining safeTraining);
+
+    SafeTrainingDto getSafeTraining(Long id);
+
+    int saveSafeTraining(SafeTrainingDto safeTrainingDto);
+
+    int delSafeTraining(List<Integer> ids);
+
+    void export(HttpServletResponse response, Long id);
+}
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 9e4aa57..6f928bc 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeHiddenServiceImpl.java
@@ -47,7 +47,7 @@
     @Override
     public int add(SafeHidden safeHidden) {
         safeHiddenMapper.insert(safeHidden);
-        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
         String no = "YH" + String.format("%s%03d", datePrefix, safeHidden.getId());
         safeHidden.setHiddenCode(no);
         safeHiddenMapper.updateById(safeHidden);
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java
new file mode 100644
index 0000000..2804aa3
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingDetailsServiceImpl.java
@@ -0,0 +1,81 @@
+package com.ruoyi.safe.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+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.service.SafeTrainingDetailsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--璁板綍璇︽儏 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:15
+ */
+@Service
+public class SafeTrainingDetailsServiceImpl extends ServiceImpl<SafeTrainingDetailsMapper, SafeTrainingDetails> implements SafeTrainingDetailsService {
+
+    @Autowired
+    private SafeTrainingDetailsMapper safeTrainingDetailsMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Override
+    public IPage<SafeTrainingDetails> pageDetails(Page page, SafeTrainingDetails safeTrainingDetails) {
+        return safeTrainingDetailsMapper.pageDetails(page, safeTrainingDetails);
+    }
+
+    @Override
+    public void export(HttpServletResponse response, Long userId) {
+        SafeTrainingDetails safeTrainingDetails = new SafeTrainingDetails();
+        safeTrainingDetails.setUserId(userId);
+        SysUser sysUser = sysUserMapper.selectUserById(userId);
+        List<SafeTrainingDetails> safeTrainingDetailsList = safeTrainingDetailsMapper.pageDetails(new Page(1, -1), safeTrainingDetails).getRecords();
+        InputStream inputStream = this.getClass().getResourceAsStream("/static/safe-training-details.docx");
+        Configure configure = Configure.builder()
+                .bind("safeTrainingDetailsList", new HackLoopTableRenderPolicy())
+                .build();
+        XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(
+                new HashMap<String, Object>() {{
+                    put("user", sysUser);
+                    put("safeTrainingDetailsList", safeTrainingDetailsList);
+                }});
+
+        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/safe/service/impl/SafeTrainingFileServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingFileServiceImpl.java
new file mode 100644
index 0000000..6d5c53b
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingFileServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.safe.service.impl;
+
+import com.ruoyi.safe.pojo.SafeTrainingFile;
+import com.ruoyi.safe.mapper.SafeTrainingFileMapper;
+import com.ruoyi.safe.service.SafeTrainingFileService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳--闄勪欢 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:23
+ */
+@Service
+public class SafeTrainingFileServiceImpl extends ServiceImpl<SafeTrainingFileMapper, SafeTrainingFile> implements SafeTrainingFileService {
+
+}
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
new file mode 100644
index 0000000..0179898
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
@@ -0,0 +1,179 @@
+package com.ruoyi.safe.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.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.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 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;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--瀹夊叏鍩硅鑰冩牳 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-29 10:54:06
+ */
+@Service
+public class SafeTrainingServiceImpl extends ServiceImpl<SafeTrainingMapper, SafeTraining> implements SafeTrainingService {
+
+    @Autowired
+    private SafeTrainingMapper safeTrainingMapper;
+
+    @Autowired
+    private SafeTrainingFileMapper safeTrainingFileMapper;
+
+    @Autowired
+    private SafeTrainingDetailsMapper safeTrainingDetailsMapper;
+
+    @Override
+    public IPage<SafeTrainingDto> pageSafeTraining(Page page, SafeTrainingDto safeTrainingDto) {
+        return safeTrainingMapper.pageSafeTraining(page, safeTrainingDto);
+    }
+
+    @Override
+    public int addOrUpdate(SafeTraining safeTraining) {
+        if (ObjectUtils.isNull(safeTraining.getId())) {
+            String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
+            // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶ц绋嬬紪鍙�
+            QueryWrapper<SafeTraining> queryWrapper = new QueryWrapper<>();
+            queryWrapper.likeRight("course_code", datePrefix)
+                    .orderByDesc("course_code")
+                    .last("LIMIT 1");
+            SafeTraining lastSafeTraining = safeTrainingMapper.selectOne(queryWrapper);
+            int sequenceNumber = 1; // 榛樿搴忓彿
+            if (lastSafeTraining != null && lastSafeTraining.getCourseCode() != null) {
+                String lastNo = lastSafeTraining.getCourseCode().toString();
+                if (lastNo.startsWith(datePrefix)) {
+                    String seqStr = lastNo.substring(datePrefix.length());
+                    try {
+                        sequenceNumber = Integer.parseInt(seqStr) + 1;
+                    } catch (NumberFormatException e) {
+                        sequenceNumber = 1;
+                    }
+                }
+            }
+            // 鐢熸垚瀹屾暣鐨勮绋嬬紪鍙�
+            String no = "KC-" + String.format("%s%03d", datePrefix, sequenceNumber);
+            safeTraining.setCourseCode(no);
+        }
+        //鏍规嵁鏃堕棿鍒ゆ柇鍩硅鐘舵��
+        String trainingDate = safeTraining.getTrainingDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        LocalDateTime openingTime = LocalDateTime.parse((trainingDate + safeTraining.getOpeningTime()), DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss"));
+        LocalDateTime endTime = LocalDateTime.parse((trainingDate + safeTraining.getEndTime()), DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss"));
+        if (LocalDateTime.now().isBefore(openingTime)) {
+            //鏈紑濮�
+            safeTraining.setState(0);
+        } else if (LocalDateTime.now().isAfter(endTime)) {
+            //宸茬粨鏉�
+            safeTraining.setState(2);
+        } else {
+            //杩涜涓�
+            safeTraining.setState(1);
+        }
+        //鏂板鎴栨洿鏂�
+        saveOrUpdate(safeTraining);
+        return 0;
+    }
+
+    @Override
+    public SafeTrainingDto getSafeTraining(Long id) {
+        //涓昏〃鏁版嵁
+        SafeTrainingDto safeTrainingDto = safeTrainingMapper.getSafeTraining(id);
+        //闄勪欢
+        List<SafeTrainingFile> safeTrainingFiles = safeTrainingFileMapper.selectList(Wrappers.<SafeTrainingFile>lambdaQuery().eq(SafeTrainingFile::getSafeTrainingId, id));
+        safeTrainingDto.setSafeTrainingFileList(safeTrainingFiles);
+        //鍩硅璁板綍璇︽儏
+        List<SafeTrainingDetailsDto> safeTrainingDetailsDto = safeTrainingDetailsMapper.getSafeTraining(id);
+        safeTrainingDto.setSafeTrainingDetailsDtoList(safeTrainingDetailsDto);
+        return safeTrainingDto;
+    }
+
+    @Override
+    public int saveSafeTraining(SafeTrainingDto safeTrainingDto) {
+        //鏇存柊涓昏〃
+        safeTrainingMapper.updateById(safeTrainingDto);
+        //鏇存柊鍩硅璁板綍璇︽儏
+        safeTrainingDto.getSafeTrainingDetailsDtoList().forEach(safeTrainingDetailsDto -> {
+            safeTrainingDetailsMapper.updateById(safeTrainingDetailsDto);
+        });
+        return 0;
+    }
+
+    @Override
+    public int delSafeTraining(List<Integer> ids) {
+        //鍒犻櫎涓昏〃
+        safeTrainingMapper.deleteBatchIds(ids);
+        //鍒犻櫎闄勪欢
+        safeTrainingFileMapper.delete(Wrappers.<SafeTrainingFile>lambdaQuery().in(SafeTrainingFile::getSafeTrainingId, ids));
+        //鍒犻櫎鍩硅璁板綍
+        safeTrainingDetailsMapper.delete(Wrappers.<SafeTrainingDetails>lambdaQuery().in(SafeTrainingDetails::getSafeTrainingId, ids));
+        return 0;
+    }
+
+    @Override
+    public void export(HttpServletResponse response, Long id) {
+        SafeTrainingDto safeTrainingDto = safeTrainingMapper.getSafeTraining(id);
+        List<SafeTrainingDetailsDto> safeTrainingDetailsDtoList = safeTrainingDetailsMapper.getSafeTraining(id);
+        InputStream inputStream = this.getClass().getResourceAsStream("/static/safe-training.docx");
+        Configure configure = Configure.builder()
+                .bind("safeTrainingDetailsDtoList", new HackLoopTableRenderPolicy())
+                .build();
+        XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(
+                new HashMap<String, Object>() {{
+                    put("safeTrainingDto", safeTrainingDto);
+                    put("safeTrainingDetailsDtoList", safeTrainingDetailsDtoList);
+                }});
+
+        try {
+            response.setContentType("application/msword");
+            String fileName = URLEncoder.encode(
+                    safeTrainingDto.getCourseCode() + "鍩硅涓庤�冩牳璁″垝", "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/sales/controller/ShippingInfoController.java b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
index a30adb9..0cf0797 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -64,7 +64,7 @@
     @GetMapping("/listPage")
     @ApiOperation("鍙戣揣淇℃伅鍒楄〃")
     public AjaxResult listPage(Page page, ShippingInfo req) {
-        IPage<ShippingInfo> listPage = shippingInfoService.listPage(page,req);
+        IPage<ShippingInfoDto> listPage = shippingInfoService.listPage(page,req);
         return AjaxResult.success(listPage);
     }
 
@@ -96,8 +96,6 @@
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "鍙戣揣淇℃伅绠$悊", businessType = BusinessType.UPDATE)
     public AjaxResult deductStock(@RequestBody ShippingInfoDto req) throws IOException {
-
-
         return shippingInfoService.deductStock( req) ? AjaxResult.success() : AjaxResult.error();
     }
 
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
index bd19d51..78169a0 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
@@ -54,4 +54,7 @@
 
     @ApiModelProperty(value = "浠樻鏂瑰紡")
     private String paymentMethod;
+
+    @ApiModelProperty(value = "浜よ揣鏃ユ湡")
+    private LocalDate deliveryDate;
 }
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java
index 3da8364..41b380a 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java
@@ -55,4 +55,6 @@
      */
     private Long supplierId;
 
+    private Integer approvalStatus;
+
 }
diff --git a/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java b/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java
index 88dec8a..9ab16d5 100644
--- a/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.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.sales.dto.ShippingInfoDto;
 import com.ruoyi.sales.pojo.ShippingInfo;
 import org.apache.ibatis.annotations.Param;
 
@@ -13,7 +14,7 @@
  * @date : 2025/10/22 9:32
  */
 public interface ShippingInfoMapper extends BaseMapper<ShippingInfo> {
-    IPage<ShippingInfo> listPage(Page page,@Param("req") ShippingInfo req);
+    IPage<ShippingInfoDto> listPage(Page page, @Param("req") ShippingInfo req);
 
     List<ShippingInfo> listAll();
 }
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
index 8a48696..30097b4 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -130,5 +130,14 @@
     @TableField(exist = false)
     @ApiModelProperty(value = "鐢熶骇鐘舵��")
     private String productionStatus = "鏈紑濮�";
+
+    //浜よ揣鏃ユ湡
+    @ApiModelProperty(value = "浜よ揣鏃ユ湡")
+    @TableField(value = "delivery_date")
+    private LocalDate deliveryDate;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "浜よ揣澶╂暟宸�")
+    private Integer deliveryDaysDiff;
 }
 
diff --git a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
index 81bcf6e..d9a3a8c 100644
--- a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
+++ b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
@@ -14,7 +14,7 @@
  * @date : 2025/10/22 9:33
  */
 public interface ShippingInfoService extends IService<ShippingInfo>{
-    IPage<ShippingInfo> listPage(Page page, ShippingInfo req);
+    IPage<ShippingInfoDto> listPage(Page page, ShippingInfo req);
 
     boolean deductStock(ShippingInfoDto req) throws IOException;
 
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 88b8e22..f3aac49 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
@@ -40,6 +40,11 @@
     @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)
+                .eq(CommonFile::getType, type));
+    }
+
     public void deleteByBusinessId(Long businessId,Integer type) {
         commonFileMapper.delete(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, businessId)
                 .eq(CommonFile::getType, type));
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 614fc20..d89119f 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java
@@ -326,6 +326,14 @@
         if(ObjectUtils.isEmpty(invoiceRegistrationProductDto)){
             throw new RuntimeException("浜у搧寮�绁ㄥ彴璐︽煡鎵惧け璐�");
         }
+        List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(new LambdaQueryWrapper<InvoiceRegistrationProduct>()
+                .eq(InvoiceRegistrationProduct::getSalesLedgerProductId, invoiceRegistrationProductDto.getSalesLedgerProductId()));
+        if(CollectionUtils.isNotEmpty(invoiceRegistrationProducts)){
+            invoiceRegistrationProductDto.setNoInvoiceNum(invoiceRegistrationProductDto.getQuantity()
+                    .subtract(invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getInvoiceNum).reduce(BigDecimal.ZERO, BigDecimal::add)));
+            invoiceRegistrationProductDto.setNoInvoiceAmount(invoiceRegistrationProductDto.getTaxInclusiveTotalPrice()
+                    .subtract(invoiceRegistrationProducts.stream().map(InvoiceRegistrationProduct::getInvoiceAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
+        }
         // 鏌ヨ闄勪欢
         QueryWrapper<InvoiceLedgerFile> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("invoice_ledger_id", invoiceRegistrationProductDto.getInvoiceLedgerId());
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 3a5a0ab..ea372b0 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -49,9 +49,11 @@
     private ApproveProcessServiceImpl approveProcessService;
 
     @Override
-    public IPage<ShippingInfo> listPage(Page page, ShippingInfo req) {
-        IPage<ShippingInfo> listPage = shippingInfoMapper.listPage(page, req);
-
+    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()));
+        });
         return listPage;
     }
 
@@ -61,14 +63,16 @@
         if (byId == null) {
             throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
         }
+        //鎵e噺搴撳瓨
+        if(!"宸插彂璐�".equals(byId.getStatus())){
+            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
+            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+        }
         byId.setExpressNumber(req.getExpressNumber());
         byId.setExpressCompany(req.getExpressCompany());
         byId.setStatus("宸插彂璐�");
         byId.setShippingCarNumber(req.getShippingCarNumber());
-        boolean update = this.updateById(req);
-        //鎵e噺搴撳瓨
-        SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(req.getSalesLedgerProductId());
-        stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+        boolean update = this.updateById(byId);
         // 杩佺Щ鏂囦欢
         if(CollectionUtils.isNotEmpty(req.getTempFileIds())){
             tempFileService.migrateTempFilesToFormal(req.getId(), req.getTempFileIds(), FileNameType.SHIP.getValue());
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 53604e0..8e4ce04 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -69,8 +69,10 @@
         // 鏇存柊瀵瑰簲鐢ㄦ埛鐘舵�佷负鍋滅敤
         // 鏍规嵁鍛樺伐缂栧彿鏌ヨ鐢ㄦ埛
         SysUser sysUser = sysUserMapper.selectUserByUserName(staffOnJob.getStaffNo());
-        sysUser.setStatus("1");
-        sysUserMapper.updateUser(sysUser);
+        if (sysUser != null) {
+            sysUser.setStatus("1");
+            sysUserMapper.updateUser(sysUser);
+        }
 
         // 鏇存柊绂昏亴鐘舵�佷负绂昏亴
         staffOnJob.setStaffState(0);
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 a024221..98e7bdb 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java
@@ -90,7 +90,7 @@
             throw new BaseException("缂栧彿涓�"+staffOnJobParams.getStaffNo()+"鐨勫憳宸ヤ笉瀛樺湪,鏃犳硶鏇存柊!!!");
         }
 
-        String[] ignoreProperties = {"id"};//鎺掗櫎id灞炴��
+        String[] ignoreProperties = {"id"};//鎺掗櫎鏇存柊灞炴��
 
         // 鑾峰彇鏈�鏂板悎鍚屾暟鎹紝骞朵笖鏇存柊
         StaffContract contract = staffContractMapper.selectOne(Wrappers.<StaffContract>lambdaQuery()
@@ -103,9 +103,8 @@
         }
 
         // 鏇存柊鍛樺伐鏁版嵁
-        BeanUtils.copyProperties(staffOnJobParams,job,ignoreProperties);
-        job.setContractExpireTime(staffOnJobParams.getContractEndTime());
-        return staffOnJobMapper.updateById(job);
+        staffOnJobParams.setContractExpireTime(staffOnJobParams.getContractEndTime());
+        return staffOnJobMapper.updateById(staffOnJobParams);
     }
 
     //鍒犻櫎鍏ヨ亴
diff --git a/src/main/resources/mapper/production/ProductOrderMapper.xml b/src/main/resources/mapper/production/ProductOrderMapper.xml
index 28e03b5..70ce815 100644
--- a/src/main/resources/mapper/production/ProductOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -21,7 +21,8 @@
         slp.specification_model,
         ppr.process_route_code,
         pb.bom_no,
-        ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus
+        ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus,
+        DATEDIFF(sl.delivery_date, CURDATE()) AS delivery_days_diff
         from product_order po
         left join sales_ledger sl on po.sales_ledger_id = sl.id
         left join sales_ledger_product slp on po.product_model_id = slp.id
diff --git a/src/main/resources/mapper/safe/SafeAccidentMapper.xml b/src/main/resources/mapper/safe/SafeAccidentMapper.xml
index 159e7cd..c7dc368 100644
--- a/src/main/resources/mapper/safe/SafeAccidentMapper.xml
+++ b/src/main/resources/mapper/safe/SafeAccidentMapper.xml
@@ -27,7 +27,7 @@
     </resultMap>
     <select id="pageSafeAccident" resultType="com.ruoyi.safe.pojo.SafeAccident">
         select sa.*,
-               su.nick_name createUserName,
+               su.nick_name createUserName
         from safe_accident sa
         left join sys_user su on sa.create_user = su.user_id
         where 1=1
@@ -35,13 +35,13 @@
             and sa.accident_code like concat('%', #{c.accidentCode}, '%')
         </if>
         <if test="c.accidentName != null and c.accidentName != ''">
-            and sa.accident_name like concat('%', #{accidentName}, '%')
+            and sa.accident_name like concat('%', #{c.accidentName}, '%')
         </if>
         <if test="c.accidentType != null and c.accidentType != ''">
-            and sa.accident_type like concat('%', #{accidentType}, '%')
+            and sa.accident_type like concat('%', #{c.accidentType}, '%')
         </if>
         <if test="c.accidentGrade != null and c.accidentGrade != ''">
-            and sa.accident_grade like concat('%', #{accidentGrade}, '%')
+            and sa.accident_grade like concat('%', #{c.accidentGrade}, '%')
         </if>
     </select>
 
diff --git a/src/main/resources/mapper/safe/SafeTrainingDetailsMapper.xml b/src/main/resources/mapper/safe/SafeTrainingDetailsMapper.xml
new file mode 100644
index 0000000..c96d711
--- /dev/null
+++ b/src/main/resources/mapper/safe/SafeTrainingDetailsMapper.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.safe.mapper.SafeTrainingDetailsMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.pojo.SafeTrainingDetails">
+        <id column="id" property="id"/>
+        <result column="user_id" property="userId"/>
+        <result column="safe_training_id" property="safeTrainingId"/>
+        <result column="examination_results" property="examinationResults"/>
+        <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>
+    <select id="getSafeTraining" resultType="com.ruoyi.safe.dto.SafeTrainingDetailsDto">
+        select std.*,
+               su.user_name,
+               su.nick_name,
+               su.phonenumber
+        from safe_training_details std
+                 left join sys_user su on std.user_id = su.user_id
+        where std.safe_training_id = #{id}
+    </select>
+    <select id="pageDetails" resultType="com.ruoyi.safe.pojo.SafeTrainingDetails">
+        select std.*,
+               st.*
+        from safe_training_details std
+                 left join safe_training st on std.safe_training_id = st.id
+        where std.user_id = #{c.userId}
+        <if test="c.trainingDate != null">
+            and st.training_date = #{c.trainingDate}
+        </if>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/safe/SafeTrainingFileMapper.xml b/src/main/resources/mapper/safe/SafeTrainingFileMapper.xml
new file mode 100644
index 0000000..34a42a6
--- /dev/null
+++ b/src/main/resources/mapper/safe/SafeTrainingFileMapper.xml
@@ -0,0 +1,19 @@
+<?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.safe.mapper.SafeTrainingFileMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.pojo.SafeTrainingFile">
+        <id column="id" property="id" />
+        <result column="safe_training_id" property="safeTrainingId" />
+        <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/safe/SafeTrainingMapper.xml b/src/main/resources/mapper/safe/SafeTrainingMapper.xml
new file mode 100644
index 0000000..473b5f2
--- /dev/null
+++ b/src/main/resources/mapper/safe/SafeTrainingMapper.xml
@@ -0,0 +1,59 @@
+<?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.safe.mapper.SafeTrainingMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.pojo.SafeTraining">
+        <id column="id" property="id" />
+        <result column="course_code" property="courseCode" />
+        <result column="training_objectives" property="trainingObjectives" />
+        <result column="training_content" property="trainingContent" />
+        <result column="training_mode" property="trainingMode" />
+        <result column="state" property="state" />
+        <result column="participants" property="participants" />
+        <result column="place_training" property="placeTraining" />
+        <result column="training_lecturer" property="trainingLecturer" />
+        <result column="training_date" property="trainingDate" />
+        <result column="opening_time" property="openingTime" />
+        <result column="end_time" property="endTime" />
+        <result column="project_credits" property="projectCredits" />
+        <result column="class_hour" property="classHour" />
+        <result column="assessment_method" property="assessmentMethod" />
+        <result column="comprehensive_assessment" property="comprehensiveAssessment" />
+        <result column="remarks" property="remarks" />
+        <result column="assessment_user_id" property="assessmentUserId" />
+        <result column="assessment_date" property="assessmentDate" />
+        <result column="training_abstract" property="trainingAbstract" />
+        <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>
+    <select id="pageSafeTraining" resultType="com.ruoyi.safe.dto.SafeTrainingDto">
+        select st.*,
+               su.nick_name assessmentUserName,
+                count(std.id) nums
+        from safe_training st
+        left join safe_training_details std on std.safe_training_id = st.id
+        left join sys_user su on st.assessment_user_id = su.user_id
+        where 1=1
+        <if test="c.placeTraining != null and c.placeTraining != ''">
+            and st.place_training like concat('%', #{c.placeTraining}, '%')
+        </if>
+        <if test="c.trainingDate != null and c.trainingDate != ''">
+            and st.training_date = #{c.trainingDate}
+        </if>
+        <if test="c.state != null and c.state != ''">
+            and st.state like concat('%', #{c.state}, '%')
+        </if>
+    </select>
+    <select id="getSafeTraining" resultType="com.ruoyi.safe.dto.SafeTrainingDto">
+         select st.*,
+                su.nick_name assessmentUserName
+         from safe_training st
+                  left join sys_user su on st.assessment_user_id = su.user_id
+         where st.id=#{id}
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/sales/SalesLedgerMapper.xml b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
index 552b83d..7bc2d2d 100644
--- a/src/main/resources/mapper/sales/SalesLedgerMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -15,24 +15,25 @@
 
     <select id="selectSalesLedgerList" resultType="com.ruoyi.sales.pojo.SalesLedger">
         SELECT
-            T1.id,
-            T1.sales_contract_no,
-            T1.customer_contract_no,
-            T1.project_name,
-            T1.entry_date,
-            T1.salesman,
-            T1.customer_id,
-            T1.customer_name,
-            T1.entry_person,
-            T1.remarks,
-            T1.attachment_materials,
-            T1.tenant_id,
-            T1.contract_amount,
-            T1.execution_date,
-            T2.nick_name AS entry_person_name,
-            T1.payment_method
+        T1.id,
+        T1.sales_contract_no,
+        T1.customer_contract_no,
+        T1.project_name,
+        T1.entry_date,
+        T1.salesman,
+        T1.customer_id,
+        T1.customer_name,
+        T1.entry_person,
+        T1.remarks,
+        T1.attachment_materials,
+        T1.tenant_id,
+        T1.contract_amount,
+        T1.execution_date,
+        T2.nick_name AS entry_person_name,
+        T1.payment_method,
+        DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff
         FROM
-            sales_ledger T1
+        sales_ledger T1
         LEFT JOIN sys_user T2 ON T1.entry_person = T2.user_id
         <where>
             <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
@@ -59,7 +60,9 @@
         T1.contract_amount as noInvoiceAmountTotal,
         T1.execution_date,
         T2.nick_name AS entry_person_name,
-        T1.payment_method
+        T1.payment_method,
+        T1.delivery_date,
+        DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff
         FROM
         sales_ledger T1
         LEFT JOIN sys_user T2 ON T1.entry_person = T2.user_id
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index ae9f718..06063b3 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -81,6 +81,9 @@
             <if test="req.purchaseContractNumber != null and req.purchaseContractNumber != '' ">
                 AND sl.purchase_contract_number like concat('%',#{req.purchaseContractNumber},'%')
             </if>
+            <if test="req.approvalStatus != null and req.approvalStatus != ''">
+                and sl.approval_status = #{req.approvalStatus}
+            </if>
             <if test="req.customerContractNo != null and req.customerContractNo != '' ">
                 AND sl.customer_contract_no like concat('%',#{req.customerContractNo},'%')
             </if>
diff --git a/src/main/resources/mapper/sales/ShippingInfoMapper.xml b/src/main/resources/mapper/sales/ShippingInfoMapper.xml
index 34073ef..6026980 100644
--- a/src/main/resources/mapper/sales/ShippingInfoMapper.xml
+++ b/src/main/resources/mapper/sales/ShippingInfoMapper.xml
@@ -2,7 +2,7 @@
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.sales.mapper.ShippingInfoMapper">
 
-    <select id="listPage" resultType="com.ruoyi.sales.pojo.ShippingInfo">
+    <select id="listPage" resultType="com.ruoyi.sales.dto.ShippingInfoDto">
         SELECT
         s.id,
         s.sales_ledger_id,
diff --git a/src/main/resources/static/safe-training-details.docx b/src/main/resources/static/safe-training-details.docx
new file mode 100644
index 0000000..d2b502f
--- /dev/null
+++ b/src/main/resources/static/safe-training-details.docx
Binary files differ
diff --git a/src/main/resources/static/safe-training.docx b/src/main/resources/static/safe-training.docx
new file mode 100644
index 0000000..0bc1d64
--- /dev/null
+++ b/src/main/resources/static/safe-training.docx
Binary files differ

--
Gitblit v1.9.3