From f8c024b1c1de318a4de485e048d1044cd6dcaa53 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期六, 24 十月 2026 21:05:42 +0800
Subject: [PATCH] feat(search-new):  1.标准查新模块                    2.印章使用记录

---
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/SealUsageLedgerServiceImpl.java      |  123 ++++++
 cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNew.java                    |   20 +
 inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageCopiesUpdate.java                    |   12 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java                            |    3 
 cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewMapper.java            |    3 
 cnas-process/src/main/java/com/ruoyi/process/listener/StandardMethodSearchNewListener.java       |   16 
 cnas-process/src/main/java/com/ruoyi/process/controller/ProcessMethodSearchNewController.java    |   16 
 cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewHistoryMapper.java     |   18 
 cnas-process/src/main/java/com/ruoyi/process/service/ProcessMethodSearchNewService.java          |    5 
 inspect-server/src/main/resources/mapper/SealUsageLedgerMapper.xml                               |   75 +++
 cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java |  296 ++++++++++++--
 cnas-process/src/main/resources/mapper/ProcessMethodSearchNewBackupsMapper.xml                   |    3 
 cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewHistory.java             |   45 ++
 cnas-process/src/main/resources/mapper/ProcessMethodSearchNewMapper.xml                          |   17 
 inspect-server/src/main/java/com/ruoyi/inspect/controller/SealUsageLedgerController.java         |   69 +++
 inspect-server/src/main/java/com/ruoyi/inspect/service/SealUsageLedgerService.java               |   21 +
 inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageLedgerQuery.java                     |   21 +
 inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageExportRequest.java                   |   13 
 inspect-server/src/main/java/com/ruoyi/inspect/pojo/SealUsageLedger.java                         |   51 ++
 cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodSearchNewBackupsDto.java           |   36 +
 cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewBackups.java             |   25 +
 cnas-process/src/main/resources/static/excel/check-records.xlsx                                  |    0 
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java            |   23 +
 inspect-server/src/main/java/com/ruoyi/inspect/util/SealUsageLedgerWordExporter.java             |  114 ++++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java                 |   13 
 cnas-process/src/main/resources/mapper/ProcessMethodSearchNewHistoryMapper.xml                   |   23 +
 inspect-server/src/main/java/com/ruoyi/inspect/mapper/SealUsageLedgerMapper.java                 |   24 +
 ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml                                  |   16 
 28 files changed, 999 insertions(+), 102 deletions(-)

diff --git a/cnas-process/src/main/java/com/ruoyi/process/controller/ProcessMethodSearchNewController.java b/cnas-process/src/main/java/com/ruoyi/process/controller/ProcessMethodSearchNewController.java
index b830ccf..8456b16 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/controller/ProcessMethodSearchNewController.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/controller/ProcessMethodSearchNewController.java
@@ -10,6 +10,7 @@
 import com.ruoyi.process.pojo.ProcessMethodSearchNew;
 import com.ruoyi.process.pojo.ProcessMethodSearchNewArchived;
 import com.ruoyi.process.pojo.ProcessMethodSearchNewBackups;
+import com.ruoyi.process.pojo.ProcessMethodSearchNewHistory;
 import com.ruoyi.process.service.ProcessMethodSearchNewService;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Operation;
@@ -76,10 +77,17 @@
         return Result.success(processMethodSearchNewService.pageMethodSearchNew(page, processMethodSearchNew));
     }
 
-    @Operation(summary = "鑷姩褰掓。璁板綍鍒楄〃")
-    @GetMapping("/pageAutoArchived")
-    public Result<IPage<ProcessMethodSearchNew>> pageAutoArchived(ProcessMethodSearchNew processMethodSearchNew, Page page) {
-        return Result.success(processMethodSearchNewService.pageAutoArchived(page, processMethodSearchNew));
+    @Operation(summary = "鏌ヨ鍘嗘鏍囧噯鏌ユ柊璁板綍")
+    @GetMapping("/listSearchNewHistory")
+    public Result<List<ProcessMethodSearchNewHistory>> listSearchNewHistory(Integer methodSearchNewId) {
+        return Result.success(processMethodSearchNewService.listSearchNewHistory(methodSearchNewId));
+    }
+
+    @Operation(summary = "鍒嗛〉鏌ヨ鍏ㄩ儴鏌ユ柊璁板綍")
+    @GetMapping("/pageSearchNewHistory")
+    public Result<IPage<ProcessMethodSearchNewHistory>> pageSearchNewHistory(
+            Page<ProcessMethodSearchNewHistory> page, String standardNo) {
+        return Result.success(processMethodSearchNewService.pageSearchNewHistory(page, standardNo));
     }
 
     @Operation(summary = "鏍囧噯鏌ユ柊瀵煎嚭")
diff --git a/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodSearchNewBackupsDto.java b/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodSearchNewBackupsDto.java
index ac15b4a..7b65738 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodSearchNewBackupsDto.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodSearchNewBackupsDto.java
@@ -32,29 +32,33 @@
     @Schema(description = "鎵瑰噯浜烘棩鏈�")
     private String ratifyDate;
 
-    @ExcelProperty(value = {"鏄惁鏈夋洿鏂版爣鍑�", "鏄惁鏈夋洿鏂版爣鍑�"}, index = 4)
-    @Schema(description = "鏄惁鏈夋洿鏂版爣鍑�")
-    private String isNewStandardString;
+    @ExcelProperty(value = {"鏌ユ柊鏃ユ湡", "鏌ユ柊鏃ユ湡"}, index = 4)
+    private String searchNewDateString;
 
-    @ExcelProperty(value = {"鏌ユ柊璁板綍", "鏍囧噯缃�"}, index = 7)
-    @Schema(description = "鏍囧噯缃�")
-    private String standardNet;
+    @ExcelProperty(value = {"鏌ユ柊缁撴灉", "鏌ユ柊缁撴灉"}, index = 5)
+    private String searchNewResultString;
 
-    @ExcelProperty(value = {"鏌ユ柊璁板綍", "濮旀墭鎯呮姤鎵�"}, index = 8)
-    @Schema(description = "濮旀墭鎯呮姤鎵�")
-    private String informationOffices;
+    @ExcelProperty(value = {"鏌ユ柊璁板綍鏉ユ簮", "涓浗鏍囧噯鍖栧鍛樹細"}, index = 8)
+    private String standardizationAdministration;
 
-    @ExcelProperty(value = {"鏌ユ柊璁板綍", "鏍囧噯涔﹀簵"}, index = 9)
-    @Schema(description = "鏍囧噯涔﹀簵")
-    private String standardBookstore;
+    @ExcelProperty(value = {"鏌ユ柊璁板綍鏉ユ簮", "鍥藉甯傚満鐩戠潱绠$悊鎬诲眬"}, index = 9)
+    private String marketRegulation;
 
-    @ExcelProperty(value = {"鏌ユ柊璁板綍", "鍏朵粬"}, index = 10)
+    @ExcelProperty(value = {"鏌ユ柊璁板綍鏉ユ簮", "鍏ㄥ浗鏍囧噯淇℃伅鍏叡鏈嶅姟骞冲彴"}, index = 10)
+    private String nationalStandardInfo;
+
+    @ExcelProperty(value = {"鏌ユ柊璁板綍鏉ユ簮", "鍥藉鏍囧噯鍏ㄦ枃鍏紑绯荤粺"}, index = 11)
+    private String nationalStandardFullText;
+
+    @ExcelProperty(value = {"鏌ユ柊璁板綍鏉ユ簮", "宸ユ爣缃�"}, index = 12)
+    private String industryStandard;
+
+    @ExcelProperty(value = {"鏌ユ柊璁板綍鏉ユ簮", "鍏朵粬"}, index = 13)
     @Schema(description = "鍏朵粬")
     private String other;
 
-    @ExcelProperty(value = {"澶囨敞", "澶囨敞"}, index = 11)
-    @Schema(description = "澶囨敞")
-    private String remarkString;
+    @ExcelProperty(value = {"鍏朵粬鏉ユ簮鍚嶇О", "鍏朵粬鏉ユ簮鍚嶇О"}, index = 14)
+    private String otherWebsite;
 
     @ExcelProperty(value = {"搴忓彿", "搴忓彿"}, index = 0)
     @Schema(description = "搴忓彿")
diff --git a/cnas-process/src/main/java/com/ruoyi/process/listener/StandardMethodSearchNewListener.java b/cnas-process/src/main/java/com/ruoyi/process/listener/StandardMethodSearchNewListener.java
index 0ce0eee..065a103 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/listener/StandardMethodSearchNewListener.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/listener/StandardMethodSearchNewListener.java
@@ -16,7 +16,7 @@
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 
-/** 鏍规嵁鏍囧噯缁存姢淇濆瓨鍔ㄤ綔鍚屾鐢熸垚銆佸綊妗f爣鍑嗘煡鏂拌褰曘�� */
+/** 鏍规嵁鏍囧噯缁存姢淇濆瓨鍔ㄤ綔鍚屾鐢熸垚鎴栨洿鏂扮幇琛屾爣鍑嗘煡鏂拌褰曘�� */
 @Component
 @RequiredArgsConstructor
 public class StandardMethodSearchNewListener {
@@ -44,20 +44,24 @@
         ProcessMethodSearchNew current = searchNewMapper.selectOne(Wrappers.<ProcessMethodSearchNew>lambdaQuery()
                 .eq(ProcessMethodSearchNew::getCurrentAutoStandardId, event.getStandardMethodId())
                 .last("FOR UPDATE"));
+        if (current == null && searchNewMapper.selectCount(Wrappers.<ProcessMethodSearchNew>lambdaQuery()
+                .eq(ProcessMethodSearchNew::getStandardMethodId, event.getStandardMethodId())
+                .eq(ProcessMethodSearchNew::getIsAutoArchived, 1)) > 0) {
+            return;
+        }
         if (!event.isEdit() && current != null) {
             return;
         }
 
-        LocalDateTime now = LocalDateTime.now(CHINA_ZONE);
         if (current != null) {
             searchNewMapper.update(null, Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
                     .eq(ProcessMethodSearchNew::getMethodSearchNewId, current.getMethodSearchNewId())
-                    .set(ProcessMethodSearchNew::getIsNewStandard, 0)
-                    .set(ProcessMethodSearchNew::getIsAutoArchived, 1)
-                    .set(ProcessMethodSearchNew::getCurrentAutoStandardId, null)
-                    .set(ProcessMethodSearchNew::getAutoArchivedTime, now));
+                    .set(ProcessMethodSearchNew::getMethodName, event.getName())
+                    .set(ProcessMethodSearchNew::getStandardNo, event.getCode()));
+            return;
         }
 
+        LocalDateTime now = LocalDateTime.now(CHINA_ZONE);
         ProcessMethodSearchNew created = new ProcessMethodSearchNew();
         created.setMethodName(event.getName());
         created.setStandardNo(event.getCode());
diff --git a/cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewHistoryMapper.java b/cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewHistoryMapper.java
new file mode 100644
index 0000000..5abc2c8
--- /dev/null
+++ b/cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewHistoryMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.process.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.process.pojo.ProcessMethodSearchNewHistory;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface ProcessMethodSearchNewHistoryMapper extends BaseMapper<ProcessMethodSearchNewHistory> {
+    List<ProcessMethodSearchNewHistory> selectByMainId(@Param("methodSearchNewId") Integer methodSearchNewId);
+
+    IPage<ProcessMethodSearchNewHistory> pageAll(@Param("page") Page<ProcessMethodSearchNewHistory> page,
+                                                 @Param("standardNo") String standardNo);
+}
diff --git a/cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewMapper.java b/cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewMapper.java
index c415bca..e82cfc7 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewMapper.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/mapper/ProcessMethodSearchNewMapper.java
@@ -28,8 +28,5 @@
      */
     IPage<ProcessMethodSearchNew> pageMethodSearchNew(@Param("page") Page page, @Param("ew") QueryWrapper<ProcessMethodSearchNewBackupsDto> processMethodSearchNewDtoQueryWrapper, @Param("beginDate") String beginDate, @Param("endDate") String endDate);
 
-    IPage<ProcessMethodSearchNew> pageAutoArchived(@Param("page") Page page,
-                                                    @Param("ew") QueryWrapper<ProcessMethodSearchNew> queryWrapper);
-
 }
 
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNew.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNew.java
index 840eae1..eebad4f 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNew.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNew.java
@@ -2,9 +2,11 @@
 
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 
 /**
@@ -43,7 +45,7 @@
     @Schema(description = "鏂版爣鍑嗗彿")
     private String newStandardNo;
 
-    @Schema(description = "鏌ユ柊璁板綍鏉ユ簮, 0,鏍囧噯缃�, 1濮旀墭鎯呮姤, 2鏍囧噯鏁�, 3鍏朵粬")
+    @Schema(description = "鏌ユ柊鏉ユ簮锛�0-2涓哄巻鍙叉潵婧愶紝3鍏朵粬锛�4涓浗鏍囧噯鍖栧鍛樹細锛�5鍥藉甯傚満鐩戠潱绠$悊鎬诲眬锛�6鍏ㄥ浗鏍囧噯淇℃伅鍏叡鏈嶅姟骞冲彴锛�7鍥藉鏍囧噯鍏ㄦ枃鍏紑绯荤粺锛�8宸ユ爣缃�")
     private Integer searchNewSource;
 
     @Schema(description = "鏌ユ柊鏃堕棿")
@@ -56,10 +58,26 @@
     @Schema(description = "鏉ユ簮涓哄叾浠栨椂濉啓鐨勫叿浣撶綉鍧�鎴栫綉绔欏悕绉�")
     private String searchNewWebsite;
 
+    @Schema(description = "鏈�杩戜竴娆℃煡鏂颁汉ID")
+    private Integer searchNewUserId;
+
     @Schema(description = "鏌ユ柊浜�")
     @TableField(exist = false)
     private String searchNewUserName;
 
+    @Schema(description = "涓嬫鏌ユ柊鏃ユ湡")
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate nextSearchDate;
+
+    @JsonIgnore
+    @TableField("next_search_date_override")
+    private LocalDate nextSearchDatePersisted;
+
+    @Schema(description = "鏌ユ柊鐘舵�侊細鏈埌鏈熴�佷粖鏃ュ埌鏈熴�佸凡閫炬湡")
+    @TableField(exist = false)
+    private String searchDueStatus;
+
     @Schema(description = "澶囨敞,0浣滃簾, 1鏇挎崲")
     private Integer remark;
 
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewBackups.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewBackups.java
index a503d88..0010ced 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewBackups.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewBackups.java
@@ -9,6 +9,7 @@
 import lombok.Setter;
 
 import java.time.LocalDateTime;
+import java.time.LocalDate;
 
 /**
  * <p>
@@ -49,17 +50,37 @@
     @Schema(description = "鏄惁鏄柊鏍囧噯, 0鍚�,1鏄�")
     private Integer isNewStandard;
 
-    @ExcelProperty(value = {"鏂版爣鍑嗗悕绉�", "鏂版爣鍑嗗悕绉�"}, index = 5)
+    @ExcelProperty(value = {"鏂版爣鍑嗗悕绉�", "鏂版爣鍑嗗悕绉�"}, index = 6)
     @Schema(description = "鏂版爣鍑嗗悕绉�")
     private String newMethodName;
 
-    @ExcelProperty(value = {"鏂版爣鍑嗗彿", "鏂版爣鍑嗗彿"}, index =6)
+    @ExcelProperty(value = {"鏂版爣鍑嗗彿", "鏂版爣鍑嗗彿"}, index = 7)
     @Schema(description = "鏂版爣鍑嗗彿")
     private String newStandardNo;
 
     @Schema(description = "鏌ユ柊璁板綍鏉ユ簮, 0,鏍囧噯缃�, 1濮旀墭鎯呮姤, 2鏍囧噯鏁�, 3鍏朵粬")
     private Integer searchNewSource;
 
+    @Schema(description = "鏌ユ柊鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime searchNewTime;
+
+    @Schema(description = "涓嬫鏌ユ柊鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate nextSearchDate;
+
+    @Schema(description = "鏌ユ柊缁撴灉")
+    private String searchNewResult;
+
+    @Schema(description = "鍏朵粬鏉ユ簮缃戠珯鍚嶇О")
+    private String searchNewWebsite;
+
+    @Schema(description = "鏌ユ柊浜篒D")
+    private Integer searchNewUserId;
+
+    @TableField(exist = false)
+    private String searchNewUserName;
+
     @Schema(description = "澶囨敞,0浣滃簾, 1鏇挎崲")
     private Integer remark;
 
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewHistory.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewHistory.java
new file mode 100644
index 0000000..dd48335
--- /dev/null
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodSearchNewHistory.java
@@ -0,0 +1,45 @@
+package com.ruoyi.process.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("cnas_process_method_search_new_history")
+@Schema(description = "鏍囧噯鍘嗘鏌ユ柊璁板綍")
+public class ProcessMethodSearchNewHistory {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Integer methodSearchNewId;
+    private Integer standardMethodId;
+    private String methodName;
+    private String standardNo;
+    private String fileNo;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate searchNewDate;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate nextSearchDate;
+
+    private String searchNewResult;
+    private Integer searchNewSource;
+    private String searchNewWebsite;
+    private String newMethodName;
+    private String newStandardNo;
+    private Integer searchNewUserId;
+
+    @TableField(exist = false)
+    private String searchNewUserName;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+}
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/ProcessMethodSearchNewService.java b/cnas-process/src/main/java/com/ruoyi/process/service/ProcessMethodSearchNewService.java
index d6d1257..6b409dd 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/ProcessMethodSearchNewService.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/ProcessMethodSearchNewService.java
@@ -8,6 +8,7 @@
 import com.ruoyi.process.pojo.ProcessMethodSearchNew;
 import com.ruoyi.process.pojo.ProcessMethodSearchNewArchived;
 import com.ruoyi.process.pojo.ProcessMethodSearchNewBackups;
+import com.ruoyi.process.pojo.ProcessMethodSearchNewHistory;
 import org.springframework.web.multipart.MultipartFile;
 
 import jakarta.servlet.http.HttpServletResponse;
@@ -44,7 +45,9 @@
      */
     IPage<ProcessMethodSearchNew> pageMethodSearchNew(Page page, ProcessMethodSearchNewBackupsDto processMethodSearchNew);
 
-    IPage<ProcessMethodSearchNew> pageAutoArchived(Page page, ProcessMethodSearchNew processMethodSearchNew);
+    List<ProcessMethodSearchNewHistory> listSearchNewHistory(Integer methodSearchNewId);
+
+    IPage<ProcessMethodSearchNewHistory> pageSearchNewHistory(Page<ProcessMethodSearchNewHistory> page, String standardNo);
 
     /**
      * 鏍囧噯鏌ユ柊瀵煎嚭
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java b/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java
index 8790ea3..a167b12 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java
@@ -20,10 +20,13 @@
 import com.ruoyi.process.dto.ProcessMethodSearchNewBackupsDto;
 import com.ruoyi.process.mapper.ProcessMethodSearchNewArchivedMapper;
 import com.ruoyi.process.mapper.ProcessMethodSearchNewBackupsMapper;
+import com.ruoyi.process.mapper.ProcessMethodSearchNewFileSeqMapper;
 import com.ruoyi.process.mapper.ProcessMethodSearchNewMapper;
+import com.ruoyi.process.mapper.ProcessMethodSearchNewHistoryMapper;
 import com.ruoyi.process.pojo.ProcessMethodSearchNew;
 import com.ruoyi.process.pojo.ProcessMethodSearchNewArchived;
 import com.ruoyi.process.pojo.ProcessMethodSearchNewBackups;
+import com.ruoyi.process.pojo.ProcessMethodSearchNewHistory;
 import com.ruoyi.process.service.ProcessMethodSearchNewBackupsService;
 import com.ruoyi.process.service.ProcessMethodSearchNewService;
 import org.springframework.beans.BeanUtils;
@@ -40,6 +43,8 @@
 import java.io.OutputStream;
 import java.net.URLEncoder;
 import java.time.LocalDateTime;
+import java.time.LocalDate;
+import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.List;
@@ -55,12 +60,19 @@
 @Transactional(rollbackFor = Exception.class)
 public class ProcessMethodSearchNewServiceImpl extends ServiceImpl<ProcessMethodSearchNewMapper, ProcessMethodSearchNew> implements ProcessMethodSearchNewService {
 
+    private static final ZoneId CHINA_ZONE = ZoneId.of("Asia/Shanghai");
+    private static final DateTimeFormatter FILE_DATE = DateTimeFormatter.BASIC_ISO_DATE;
+
     @Resource
     private ProcessMethodSearchNewArchivedMapper processMethodSearchNewArchivedMapper;
     @Resource
     private ProcessMethodSearchNewBackupsService processMethodSearchNewBackupsService;
     @Resource
     private ProcessMethodSearchNewBackupsMapper processMethodSearchNewBackupsMapper;
+    @Resource
+    private ProcessMethodSearchNewHistoryMapper processMethodSearchNewHistoryMapper;
+    @Resource
+    private ProcessMethodSearchNewFileSeqMapper processMethodSearchNewFileSeqMapper;
 
     /**
      * 鏂板鏍囧噯鏌ユ柊
@@ -71,18 +83,26 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean addMethodSearchNew(List<ProcessMethodSearchNew> processMethodSearchNewList) {
+        if (processMethodSearchNewList == null || processMethodSearchNewList.isEmpty()) {
+            throw new ErrorException("璇峰~鍐欐爣鍑嗘煡鏂拌褰�");
+        }
+        Integer userId = SecurityUtils.getUserId().intValue();
         for (ProcessMethodSearchNew processMethodSearchNew : processMethodSearchNewList) {
+            validateSearchRecord(processMethodSearchNew);
             processMethodSearchNew.setIsNewStandard(1);
             processMethodSearchNew.setIsAutoArchived(0);
             processMethodSearchNew.setStandardMethodId(null);
             processMethodSearchNew.setCurrentAutoStandardId(null);
             processMethodSearchNew.setAutoArchivedTime(null);
+            processMethodSearchNew.setSearchNewUserId(userId);
+            processMethodSearchNew.setRemark(toLegacyRemark(processMethodSearchNew.getSearchNewResult()));
             if (!Integer.valueOf(3).equals(processMethodSearchNew.getSearchNewSource())) {
                 processMethodSearchNew.setSearchNewWebsite(null);
             }
+            this.save(processMethodSearchNew);
+            insertHistory(processMethodSearchNew, userId);
+            handleSearchResult(processMethodSearchNew);
         }
-        // 鏂板
-        this.saveBatch(processMethodSearchNewList);
         return true;
     }
 
@@ -93,24 +113,35 @@
             throw new ErrorException("鏍囧噯鏌ユ柊璁板綍涓嶅瓨鍦�");
         }
         if (Integer.valueOf(1).equals(old.getIsAutoArchived())) {
-            throw new ErrorException("鑷姩褰掓。璁板綍涓嶅厑璁镐慨鏀�");
+            throw new ErrorException("宸插綊妗f爣鍑嗕笉鑳界户缁煡鏂�");
         }
-        return update(Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
+        processMethodSearchNew.setMethodName(old.getMethodName());
+        processMethodSearchNew.setStandardNo(old.getStandardNo());
+        processMethodSearchNew.setFileNo(old.getFileNo());
+        processMethodSearchNew.setStandardMethodId(old.getStandardMethodId());
+        validateSearchRecord(processMethodSearchNew);
+        Integer userId = SecurityUtils.getUserId().intValue();
+        boolean updated = update(Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
                 .eq(ProcessMethodSearchNew::getMethodSearchNewId, old.getMethodSearchNewId())
-                .set(ProcessMethodSearchNew::getVerifyId, processMethodSearchNew.getVerifyId())
-                .set(ProcessMethodSearchNew::getMethodName, processMethodSearchNew.getMethodName())
-                .set(ProcessMethodSearchNew::getStandardNo, processMethodSearchNew.getStandardNo())
-                .set(ProcessMethodSearchNew::getFileNo, processMethodSearchNew.getFileNo())
                 .set(ProcessMethodSearchNew::getNewMethodName, processMethodSearchNew.getNewMethodName())
                 .set(ProcessMethodSearchNew::getNewStandardNo, processMethodSearchNew.getNewStandardNo())
                 .set(ProcessMethodSearchNew::getSearchNewSource, processMethodSearchNew.getSearchNewSource())
                 .set(ProcessMethodSearchNew::getSearchNewTime, processMethodSearchNew.getSearchNewTime())
+                .set(ProcessMethodSearchNew::getNextSearchDatePersisted,
+                        processMethodSearchNew.getNextSearchDatePersisted())
                 .set(ProcessMethodSearchNew::getSearchNewResult, processMethodSearchNew.getSearchNewResult())
+                .set(ProcessMethodSearchNew::getSearchNewUserId, userId)
                 .set(ProcessMethodSearchNew::getSearchNewWebsite,
                         Integer.valueOf(3).equals(processMethodSearchNew.getSearchNewSource())
                                 ? processMethodSearchNew.getSearchNewWebsite() : null)
-                .set(ProcessMethodSearchNew::getRemark, processMethodSearchNew.getRemark())
+                .set(ProcessMethodSearchNew::getRemark, toLegacyRemark(processMethodSearchNew.getSearchNewResult()))
                 .set(ProcessMethodSearchNew::getIsNewStandard, 1));
+        if (updated) {
+            ProcessMethodSearchNew latest = getById(old.getMethodSearchNewId());
+            insertHistory(latest, userId);
+            handleSearchResult(latest);
+        }
+        return updated;
     }
 
     @Override
@@ -123,7 +154,13 @@
             throw new ErrorException("鏍囧噯鏌ユ柊璁板綍涓嶅瓨鍦�");
         }
         if (Integer.valueOf(1).equals(old.getIsAutoArchived())) {
-            throw new ErrorException("鑷姩褰掓。璁板綍涓嶅厑璁稿垹闄�");
+            throw new ErrorException("宸插綊妗f爣鍑嗕笉鑳藉垹闄�");
+        }
+        Long historyCount = processMethodSearchNewHistoryMapper.selectCount(
+                Wrappers.<ProcessMethodSearchNewHistory>lambdaQuery()
+                        .eq(ProcessMethodSearchNewHistory::getMethodSearchNewId, methodSearchNewId));
+        if (historyCount != null && historyCount > 0) {
+            throw new ErrorException("璇ユ爣鍑嗗凡鏈夋煡鏂拌褰曪紝涓嶅厑璁稿垹闄�");
         }
         return removeById(methodSearchNewId);
     }
@@ -140,13 +177,152 @@
         String endDate = processMethodSearchNew.getEndDate();
         processMethodSearchNew.setBeginDate(null);
         processMethodSearchNew.setEndDate(null);
-        return baseMapper.pageMethodSearchNew(page, QueryWrappers.queryWrappers(processMethodSearchNew), beginDate, endDate);
+        IPage<ProcessMethodSearchNew> result = baseMapper.pageMethodSearchNew(
+                page, QueryWrappers.queryWrappers(processMethodSearchNew), beginDate, endDate);
+        LocalDate today = LocalDate.now(CHINA_ZONE);
+        result.getRecords().forEach(item -> {
+            LocalDate nextDate = item.getNextSearchDate();
+            if (nextDate == null) {
+                item.setSearchDueStatus("寰呴娆℃煡鏂�");
+            } else if (today.isAfter(nextDate)) {
+                item.setSearchDueStatus("宸查�炬湡");
+            } else if (today.isEqual(nextDate)) {
+                item.setSearchDueStatus("浠婃棩鍒版湡");
+            } else {
+                item.setSearchDueStatus("鏈埌鏈�");
+            }
+        });
+        return result;
     }
 
     @Override
-    public IPage<ProcessMethodSearchNew> pageAutoArchived(Page page, ProcessMethodSearchNew processMethodSearchNew) {
-        processMethodSearchNew.setIsAutoArchived(null);
-        return baseMapper.pageAutoArchived(page, QueryWrappers.queryWrappers(processMethodSearchNew));
+    public List<ProcessMethodSearchNewHistory> listSearchNewHistory(Integer methodSearchNewId) {
+        if (methodSearchNewId == null) {
+            throw new ErrorException("缂哄皯鏍囧噯鏌ユ柊璁板綍id");
+        }
+        if (getById(methodSearchNewId) == null) {
+            throw new ErrorException("鏍囧噯鏌ユ柊璁板綍涓嶅瓨鍦�");
+        }
+        return processMethodSearchNewHistoryMapper.selectByMainId(methodSearchNewId);
+    }
+
+    @Override
+    public IPage<ProcessMethodSearchNewHistory> pageSearchNewHistory(Page<ProcessMethodSearchNewHistory> page,
+                                                                      String standardNo) {
+        return processMethodSearchNewHistoryMapper.pageAll(page,
+                StringUtils.isBlank(standardNo) ? null : standardNo.trim());
+    }
+
+    private void validateSearchRecord(ProcessMethodSearchNew row) {
+        if (row == null) {
+            throw new ErrorException("璇峰~鍐欐爣鍑嗘煡鏂拌褰�");
+        }
+        if (StringUtils.isBlank(row.getMethodName()) || StringUtils.isBlank(row.getStandardNo())
+                || StringUtils.isBlank(row.getFileNo())) {
+            throw new ErrorException("璇峰~鍐欐爣鍑嗗悕绉般�佹爣鍑嗗彿鍜屾枃浠剁紪鍙�");
+        }
+        if (row.getSearchNewTime() == null) {
+            throw new ErrorException("璇烽�夋嫨鏌ユ柊鏃ユ湡");
+        }
+        row.setSearchNewTime(row.getSearchNewTime().toLocalDate().atStartOfDay());
+        if (!"鐜拌鏈夋晥".equals(row.getSearchNewResult())
+                && !"宸蹭慨璁�/鏈夋柊鐗堟湰鏇夸唬".equals(row.getSearchNewResult())
+                && !"搴熸锛堟棤鏇夸唬锛�".equals(row.getSearchNewResult())
+                && !"鍗冲皢瀹炴柦".equals(row.getSearchNewResult())) {
+            throw new ErrorException("璇烽�夋嫨鏈夋晥鐨勬煡鏂扮粨鏋�");
+        }
+        Integer source = row.getSearchNewSource();
+        if (source == null || source < 3 || source > 8) {
+            throw new ErrorException("璇烽�夋嫨鏈夋晥鐨勬煡鏂拌褰曟潵婧�");
+        }
+        if ("宸蹭慨璁�/鏈夋柊鐗堟湰鏇夸唬".equals(row.getSearchNewResult())
+                && (StringUtils.isBlank(row.getNewMethodName()) || StringUtils.isBlank(row.getNewStandardNo()))) {
+            throw new ErrorException("鏌ユ柊缁撴灉涓哄凡淇/鏈夋柊鐗堟湰鏇夸唬鏃讹紝璇峰~鍐欐柊鏍囧噯鍚嶇О鍜屾柊鏍囧噯鍙�");
+        }
+        if (!"宸蹭慨璁�/鏈夋柊鐗堟湰鏇夸唬".equals(row.getSearchNewResult())) {
+            row.setNewMethodName(null);
+            row.setNewStandardNo(null);
+        }
+        if (!Integer.valueOf(3).equals(source)) {
+            row.setSearchNewWebsite(null);
+        }
+        if ("宸蹭慨璁�/鏈夋柊鐗堟湰鏇夸唬".equals(row.getSearchNewResult())
+                || "搴熸锛堟棤鏇夸唬锛�".equals(row.getSearchNewResult())) {
+            row.setNextSearchDate(null);
+        } else if (row.getNextSearchDate() == null) {
+            row.setNextSearchDate(row.getSearchNewTime().toLocalDate().plusMonths(3));
+        }
+        row.setNextSearchDatePersisted(row.getNextSearchDate());
+    }
+
+    private Integer toLegacyRemark(String result) {
+        if ("搴熸锛堟棤鏇夸唬锛�".equals(result)) return 0;
+        if ("宸蹭慨璁�/鏈夋柊鐗堟湰鏇夸唬".equals(result)) return 1;
+        return null;
+    }
+
+    private void insertHistory(ProcessMethodSearchNew row, Integer userId) {
+        ProcessMethodSearchNewHistory history = new ProcessMethodSearchNewHistory();
+        history.setMethodSearchNewId(row.getMethodSearchNewId());
+        history.setStandardMethodId(row.getStandardMethodId());
+        history.setMethodName(row.getMethodName());
+        history.setStandardNo(row.getStandardNo());
+        history.setFileNo(row.getFileNo());
+        history.setSearchNewDate(row.getSearchNewTime().toLocalDate());
+        history.setNextSearchDate(row.getNextSearchDatePersisted());
+        history.setSearchNewResult(row.getSearchNewResult());
+        history.setSearchNewSource(row.getSearchNewSource());
+        history.setSearchNewWebsite(row.getSearchNewWebsite());
+        history.setNewMethodName(row.getNewMethodName());
+        history.setNewStandardNo(row.getNewStandardNo());
+        history.setSearchNewUserId(userId);
+        history.setCreateTime(LocalDateTime.now(CHINA_ZONE));
+        processMethodSearchNewHistoryMapper.insert(history);
+    }
+
+    /** 鏃ф爣鍑嗗彧淇濈暀鍦ㄦ煡鏂拌褰曪紱鏈夋柊鐗堟椂鍒涘缓鏂扮殑涓诲垪琛ㄨ褰曘�� */
+    private void handleSearchResult(ProcessMethodSearchNew oldStandard) {
+        String result = oldStandard.getSearchNewResult();
+        if (!"搴熸锛堟棤鏇夸唬锛�".equals(result) && !"宸蹭慨璁�/鏈夋柊鐗堟湰鏇夸唬".equals(result)) {
+            return;
+        }
+
+        LocalDateTime now = LocalDateTime.now(CHINA_ZONE);
+        update(Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
+                .eq(ProcessMethodSearchNew::getMethodSearchNewId, oldStandard.getMethodSearchNewId())
+                .set(ProcessMethodSearchNew::getIsNewStandard, 0)
+                .set(ProcessMethodSearchNew::getIsAutoArchived, 1)
+                .set(ProcessMethodSearchNew::getCurrentAutoStandardId, null)
+                .set(ProcessMethodSearchNew::getAutoArchivedTime, now));
+
+        if (!"宸蹭慨璁�/鏈夋柊鐗堟湰鏇夸唬".equals(result)) {
+            return;
+        }
+        if (count(Wrappers.<ProcessMethodSearchNew>lambdaQuery()
+                .eq(ProcessMethodSearchNew::getStandardNo, oldStandard.getNewStandardNo())
+                .eq(ProcessMethodSearchNew::getIsAutoArchived, 0)) > 0) {
+            return;
+        }
+
+        ProcessMethodSearchNew replacement = new ProcessMethodSearchNew();
+        replacement.setMethodName(oldStandard.getNewMethodName());
+        replacement.setStandardNo(oldStandard.getNewStandardNo());
+        replacement.setFileNo(nextFileNo(now.toLocalDate()));
+        replacement.setIsNewStandard(1);
+        replacement.setStandardMethodId(oldStandard.getStandardMethodId());
+        replacement.setCurrentAutoStandardId(oldStandard.getCurrentAutoStandardId());
+        replacement.setIsAutoArchived(0);
+        save(replacement);
+    }
+
+    private String nextFileNo(LocalDate date) {
+        String prefix = date.format(FILE_DATE);
+        processMethodSearchNewFileSeqMapper.insertIfAbsent(date);
+        Integer stored = processMethodSearchNewFileSeqMapper.selectForUpdate(date);
+        Integer existing = processMethodSearchNewFileSeqMapper.selectMaxExisting(prefix);
+        int next = Math.max(stored == null ? 0 : stored, existing == null ? 0 : existing) + 1;
+        processMethodSearchNewFileSeqMapper.updateValue(date, next);
+        return prefix + String.format("%03d", next);
     }
 
     /**
@@ -176,33 +352,40 @@
         for (ProcessMethodSearchNewBackups methodSearchNew : methodSearchNewBackups) {
             ProcessMethodSearchNewBackupsDto searchNewBackupsDto = new ProcessMethodSearchNewBackupsDto();
             BeanUtils.copyProperties(methodSearchNew, searchNewBackupsDto);
-            // 鏄惁鏄窡鏂版爣鍑�
-            if (methodSearchNew.getIsNewStandard().equals(1)) {
-                searchNewBackupsDto.setIsNewStandardString("鏄�");
-            } else {
-                searchNewBackupsDto.setIsNewStandardString("鍚�");
-            }
-
-            // 澶囨敞
-            if (methodSearchNew.getRemark() != null) {
-                if (methodSearchNew.getRemark().equals(1)) {
-                    searchNewBackupsDto.setRemarkString("鏇挎崲");
-                } else {
-                    searchNewBackupsDto.setRemarkString("浣滃簾");
-                }
-            }
+            searchNewBackupsDto.setSearchNewDateString(methodSearchNew.getSearchNewTime() == null
+                    ? null : methodSearchNew.getSearchNewTime().format(timeFormatter));
+            searchNewBackupsDto.setSearchNewResultString(methodSearchNew.getSearchNewResult());
             if (methodSearchNew.getSearchNewSource() != null) switch (methodSearchNew.getSearchNewSource()) {
                 case 0:
-                    searchNewBackupsDto.setStandardNet("鈭�");
+                    searchNewBackupsDto.setOther("鈭�");
+                    searchNewBackupsDto.setOtherWebsite("鏍囧噯缃戯紙鍘嗗彶鏉ユ簮锛�");
                     break;
                 case 1:
-                    searchNewBackupsDto.setInformationOffices("鈭�");
+                    searchNewBackupsDto.setOther("鈭�");
+                    searchNewBackupsDto.setOtherWebsite("濮旀墭鎯呮姤鎵�锛堝巻鍙叉潵婧愶級");
                     break;
                 case 2:
-                    searchNewBackupsDto.setStandardBookstore("鈭�");
+                    searchNewBackupsDto.setOther("鈭�");
+                    searchNewBackupsDto.setOtherWebsite("鏍囧噯涔﹀簵锛堝巻鍙叉潵婧愶級");
+                    break;
+                case 4:
+                    searchNewBackupsDto.setStandardizationAdministration("鈭�");
+                    break;
+                case 5:
+                    searchNewBackupsDto.setMarketRegulation("鈭�");
+                    break;
+                case 6:
+                    searchNewBackupsDto.setNationalStandardInfo("鈭�");
+                    break;
+                case 7:
+                    searchNewBackupsDto.setNationalStandardFullText("鈭�");
+                    break;
+                case 8:
+                    searchNewBackupsDto.setIndustryStandard("鈭�");
                     break;
                 case 3:
                     searchNewBackupsDto.setOther("鈭�");
+                    searchNewBackupsDto.setOtherWebsite(methodSearchNew.getSearchNewWebsite());
                     break;
             }
             searchNewBackupsDto.setIndex(index);
@@ -269,7 +452,7 @@
             response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
             response.setCharacterEncoding("utf-8");
             String fileName = URLEncoder.encode(
-                    "鍘熸潗鏂欐娴嬩俊鎭鍑�", "UTF-8");
+                    "鏍囧噯鏌ユ柊璁板綍", "UTF-8");
             response.setHeader("Content-disposition",
                     "attachment;filename=" + fileName + ".xlsx");
         } catch (Exception e) {
@@ -312,31 +495,39 @@
             List<ProcessMethodSearchNew> collect = searchNewDtoList.stream().map(searchNewDto -> {
                 ProcessMethodSearchNew searchNew = new ProcessMethodSearchNew();
                 BeanUtils.copyProperties(searchNewDto, searchNew);
-                searchNew.setIsNewStandard(1);
-                searchNew.setIsAutoArchived(0);
+                if (StringUtils.isNotBlank(searchNewDto.getSearchNewDateString())) {
+                    String dateText = searchNewDto.getSearchNewDateString().trim();
+                    searchNew.setSearchNewTime(LocalDate.parse(dateText.substring(0, Math.min(10, dateText.length()))).atStartOfDay());
+                }
+                searchNew.setSearchNewResult(searchNewDto.getSearchNewResultString());
+                int sourceCount = 0;
+                if (StringUtils.isNotBlank(searchNewDto.getStandardizationAdministration())) sourceCount++;
+                if (StringUtils.isNotBlank(searchNewDto.getMarketRegulation())) sourceCount++;
+                if (StringUtils.isNotBlank(searchNewDto.getNationalStandardInfo())) sourceCount++;
+                if (StringUtils.isNotBlank(searchNewDto.getNationalStandardFullText())) sourceCount++;
+                if (StringUtils.isNotBlank(searchNewDto.getIndustryStandard())) sourceCount++;
+                if (StringUtils.isNotBlank(searchNewDto.getOther())) sourceCount++;
+                if (sourceCount != 1) {
+                    throw new ErrorException("鏍囧噯鍙�" + searchNew.getStandardNo() + "蹇呴』涓斿彧鑳介�夋嫨涓�涓煡鏂版潵婧�");
+                }
                 // 鏌ユ柊璁板綍
-                if (StringUtils.isNotBlank(searchNewDto.getStandardNet())) {
-                    searchNew.setSearchNewSource(0);
-                } else if (StringUtils.isNotBlank(searchNewDto.getInformationOffices())) {
-                    searchNew.setSearchNewSource(1);
-                } else if (StringUtils.isNotBlank(searchNewDto.getStandardBookstore())) {
-                    searchNew.setSearchNewSource(2);
+                if (StringUtils.isNotBlank(searchNewDto.getStandardizationAdministration())) {
+                    searchNew.setSearchNewSource(4);
+                } else if (StringUtils.isNotBlank(searchNewDto.getMarketRegulation())) {
+                    searchNew.setSearchNewSource(5);
+                } else if (StringUtils.isNotBlank(searchNewDto.getNationalStandardInfo())) {
+                    searchNew.setSearchNewSource(6);
+                } else if (StringUtils.isNotBlank(searchNewDto.getNationalStandardFullText())) {
+                    searchNew.setSearchNewSource(7);
+                } else if (StringUtils.isNotBlank(searchNewDto.getIndustryStandard())) {
+                    searchNew.setSearchNewSource(8);
                 } else if (StringUtils.isNotBlank(searchNewDto.getOther())) {
                     searchNew.setSearchNewSource(3);
+                    searchNew.setSearchNewWebsite(searchNewDto.getOtherWebsite());
                 }
-
-                // 澶囨敞
-                if (StringUtils.isNotBlank(searchNewDto.getRemarkString())) {
-                    if (searchNewDto.getRemarkString().equals("鏇挎崲")) {
-                        searchNew.setRemark(1);
-                    } else if (searchNewDto.getRemarkString().equals("浣滃簾")) {
-                        searchNew.setRemark(0);
-                    }
-                }
-
                 return searchNew;
             }).collect(Collectors.toList());
-            this.saveBatch(collect);
+            addMethodSearchNew(collect);
 
         } catch (IOException e) {
             throw new RuntimeException(e);
@@ -365,6 +556,7 @@
         List<ProcessMethodSearchNewBackups> methodSearchNewBackups = searchNewList.stream().map(processMethodSearchNew -> {
             ProcessMethodSearchNewBackups backups = new ProcessMethodSearchNewBackups();
             BeanUtils.copyProperties(processMethodSearchNew, backups);
+            backups.setNextSearchDate(processMethodSearchNew.getNextSearchDatePersisted());
             backups.setIsNewStandard(0);
             backups.setArchivedId(archived.getArchivedId());
             return backups;
diff --git a/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewBackupsMapper.xml b/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewBackupsMapper.xml
index 46e55a3..df951e9 100644
--- a/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewBackupsMapper.xml
+++ b/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewBackupsMapper.xml
@@ -3,7 +3,8 @@
 <mapper namespace="com.ruoyi.process.mapper.ProcessMethodSearchNewBackupsMapper">
 
     <select id="pageSearchNewBackups" resultType="com.ruoyi.process.pojo.ProcessMethodSearchNewBackups">
-        select *
+        select a.*,
+               (select u.name from user u where u.id = a.search_new_user_id) as searchNewUserName
         from (select *
         from cnas_process_method_search_new_backups
         order by create_time desc
diff --git a/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewHistoryMapper.xml b/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewHistoryMapper.xml
new file mode 100644
index 0000000..01d2a16
--- /dev/null
+++ b/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewHistoryMapper.xml
@@ -0,0 +1,23 @@
+<?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.process.mapper.ProcessMethodSearchNewHistoryMapper">
+    <select id="selectByMainId" resultType="com.ruoyi.process.pojo.ProcessMethodSearchNewHistory">
+        SELECT h.*, u.name AS searchNewUserName
+        FROM cnas_process_method_search_new_history h
+        LEFT JOIN user u ON u.id = h.search_new_user_id
+        WHERE h.method_search_new_id = #{methodSearchNewId}
+        ORDER BY h.search_new_date DESC, h.create_time DESC, h.id DESC
+    </select>
+
+    <select id="pageAll" resultType="com.ruoyi.process.pojo.ProcessMethodSearchNewHistory">
+        SELECT h.*, u.name AS searchNewUserName
+        FROM cnas_process_method_search_new_history h
+        LEFT JOIN user u ON u.id = h.search_new_user_id
+        <where>
+            <if test="standardNo != null and standardNo != ''">
+                h.standard_no LIKE CONCAT('%', #{standardNo}, '%')
+            </if>
+        </where>
+        ORDER BY h.search_new_date DESC, h.create_time DESC, h.id DESC
+    </select>
+</mapper>
diff --git a/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewMapper.xml b/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewMapper.xml
index c006f77..3d05316 100644
--- a/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewMapper.xml
+++ b/cnas-process/src/main/resources/mapper/ProcessMethodSearchNewMapper.xml
@@ -5,7 +5,11 @@
     <!-- 鏍囧噯鏌ユ柊鍒嗛〉鏌ヨ -->
     <select id="pageMethodSearchNew" resultType="com.ruoyi.process.pojo.ProcessMethodSearchNew">
         select a.*,
-               (select u.name from user u where u.id = a.create_user) as searchNewUserName
+               CASE WHEN a.search_new_time IS NOT NULL THEN
+                   (select u.name from user u where u.id = a.search_new_user_id)
+               END as searchNewUserName,
+               COALESCE(a.next_search_date_override,
+                        DATE_ADD(DATE(COALESCE(a.search_new_time, a.create_time)), INTERVAL 3 MONTH)) as nextSearchDate
         from (select *
         from cnas_process_method_search_new
         <where>
@@ -21,15 +25,4 @@
         </if>
     </select>
 
-    <select id="pageAutoArchived" resultType="com.ruoyi.process.pojo.ProcessMethodSearchNew">
-        select *
-        from (
-            select * from cnas_process_method_search_new
-            where is_auto_archived = 1
-            order by auto_archived_time desc, method_search_new_id desc
-        ) a
-        <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
-            ${ew.customSqlSegment}
-        </if>
-    </select>
 </mapper>
diff --git a/cnas-process/src/main/resources/static/excel/check-records.xlsx b/cnas-process/src/main/resources/static/excel/check-records.xlsx
index 7afdfff..a947233 100644
--- a/cnas-process/src/main/resources/static/excel/check-records.xlsx
+++ b/cnas-process/src/main/resources/static/excel/check-records.xlsx
Binary files differ
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/controller/SealUsageLedgerController.java b/inspect-server/src/main/java/com/ruoyi/inspect/controller/SealUsageLedgerController.java
new file mode 100644
index 0000000..dd7bd4e
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/controller/SealUsageLedgerController.java
@@ -0,0 +1,69 @@
+package com.ruoyi.inspect.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.framework.exception.ErrorException;
+import com.ruoyi.inspect.dto.SealUsageCopiesUpdate;
+import com.ruoyi.inspect.dto.SealUsageExportRequest;
+import com.ruoyi.inspect.dto.SealUsageLedgerQuery;
+import com.ruoyi.inspect.pojo.SealUsageLedger;
+import com.ruoyi.inspect.service.SealUsageLedgerService;
+import com.ruoyi.inspect.util.SealUsageLedgerWordExporter;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+@RestController
+@RequestMapping("/sealUsageLedger")
+@Tag(name = "鐢ㄥ嵃绠$悊鍙拌处")
+public class SealUsageLedgerController {
+
+    @Resource
+    private SealUsageLedgerService ledgerService;
+
+    @Operation(summary = "鍒嗛〉鏌ヨ鐢ㄥ嵃绠$悊鍙拌处")
+    @GetMapping("/page")
+    @PreAuthorize("@ss.hasPermi('structural:sealUsageLedger:list')")
+    public Result page(Page<SealUsageLedger> page, SealUsageLedgerQuery query) {
+        return Result.success(ledgerService.page(page, query));
+    }
+
+    @Operation(summary = "淇敼鐢ㄥ嵃浠芥暟")
+    @PostMapping("/updateCopies")
+    @PreAuthorize("@ss.hasPermi('structural:sealUsageLedger:edit')")
+    public Result updateCopies(@RequestBody SealUsageCopiesUpdate update) {
+        ledgerService.updateCopies(update);
+        return Result.success();
+    }
+
+    @Operation(summary = "瀵煎嚭鍗扮珷浣跨敤鐧昏琛� Word")
+    @PostMapping("/exportWord")
+    @PreAuthorize("@ss.hasPermi('structural:sealUsageLedger:export')")
+    public void exportWord(@RequestBody SealUsageExportRequest request, HttpServletResponse response) {
+        List<SealUsageLedger> ledgers = ledgerService.listForExport(request);
+        String fileName = "鍗扮珷浣跨敤鐧昏琛╛" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".docx";
+        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
+        response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''"
+                + URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20"));
+        try {
+            SealUsageLedgerWordExporter.write(ledgers, response.getOutputStream());
+        } catch (IOException e) {
+            throw new ErrorException("鐢ㄥ嵃鍙拌处瀵煎嚭澶辫触");
+        }
+    }
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageCopiesUpdate.java b/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageCopiesUpdate.java
new file mode 100644
index 0000000..1091bb9
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageCopiesUpdate.java
@@ -0,0 +1,12 @@
+package com.ruoyi.inspect.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class SealUsageCopiesUpdate implements Serializable {
+    private Long id;
+    private Integer copies;
+    private Integer version;
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageExportRequest.java b/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageExportRequest.java
new file mode 100644
index 0000000..f79e3ca
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageExportRequest.java
@@ -0,0 +1,13 @@
+package com.ruoyi.inspect.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class SealUsageExportRequest implements Serializable {
+    private String mode;
+    private List<Long> ids;
+    private SealUsageLedgerQuery query;
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageLedgerQuery.java b/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageLedgerQuery.java
new file mode 100644
index 0000000..111e25f
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/dto/SealUsageLedgerQuery.java
@@ -0,0 +1,21 @@
+package com.ruoyi.inspect.dto;
+
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+@Data
+public class SealUsageLedgerQuery implements Serializable {
+    private String reportCode;
+    private String sealName;
+    private String projectName;
+    private String useUserName;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate startDate;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate endDate;
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/mapper/SealUsageLedgerMapper.java b/inspect-server/src/main/java/com/ruoyi/inspect/mapper/SealUsageLedgerMapper.java
new file mode 100644
index 0000000..a000b61
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/mapper/SealUsageLedgerMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.inspect.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.ruoyi.inspect.dto.SealUsageLedgerQuery;
+import com.ruoyi.inspect.pojo.SealUsageLedger;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface SealUsageLedgerMapper extends BaseMapper<SealUsageLedger> {
+    IPage<SealUsageLedger> selectLedgerPage(IPage<SealUsageLedger> page,
+                                             @Param("query") SealUsageLedgerQuery query);
+
+    List<SealUsageLedger> selectForExport(@Param("query") SealUsageLedgerQuery query,
+                                           @Param("ids") List<Long> ids);
+
+    String selectProjectName(@Param("insOrderId") Integer insOrderId);
+
+    int updateCopies(@Param("id") Long id,
+                     @Param("copies") Integer copies,
+                     @Param("version") Integer version,
+                     @Param("updateUser") Integer updateUser);
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/pojo/SealUsageLedger.java b/inspect-server/src/main/java/com/ruoyi/inspect/pojo/SealUsageLedger.java
new file mode 100644
index 0000000..de079f9
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/pojo/SealUsageLedger.java
@@ -0,0 +1,51 @@
+package com.ruoyi.inspect.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("seal_usage_ledger")
+@Schema(description = "鐢ㄥ嵃绠$悊鍙拌处")
+public class SealUsageLedger implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private Integer reportId;
+    private String reportCode;
+    private Integer insOrderId;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime useTime;
+
+    private String sealIds;
+    private String sealNames;
+    private String projectName;
+    private Integer useUserId;
+    private String useUserName;
+    private Integer copies;
+    private Integer version;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/SealUsageLedgerService.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/SealUsageLedgerService.java
new file mode 100644
index 0000000..f28e707
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/SealUsageLedgerService.java
@@ -0,0 +1,21 @@
+package com.ruoyi.inspect.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.inspect.dto.SealUsageCopiesUpdate;
+import com.ruoyi.inspect.dto.SealUsageExportRequest;
+import com.ruoyi.inspect.dto.SealUsageLedgerQuery;
+import com.ruoyi.inspect.pojo.InsReport;
+import com.ruoyi.inspect.pojo.SealUsageLedger;
+
+import java.util.List;
+
+public interface SealUsageLedgerService {
+    IPage<SealUsageLedger> page(Page<SealUsageLedger> page, SealUsageLedgerQuery query);
+
+    void updateCopies(SealUsageCopiesUpdate update);
+
+    List<SealUsageLedger> listForExport(SealUsageExportRequest request);
+
+    void recordApprovedReport(InsReport report);
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
index 8401156..14df655 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
@@ -50,6 +50,7 @@
 import com.ruoyi.inspect.service.InsOrderService;
 import com.ruoyi.inspect.service.InsReportService;
 import com.ruoyi.inspect.service.RawMaterialOrderService;
+import com.ruoyi.inspect.service.SealUsageLedgerService;
 import com.ruoyi.inspect.util.PreserveReportPicturePlaceholderHandler;
 import com.ruoyi.inspect.util.ReportSealLayoutUtil;
 import com.ruoyi.inspect.util.ReportSignaturePictureUtils;
@@ -107,6 +108,8 @@
     private UserMapper userMapper;
     @Resource
     private InsReportMapper insReportMapper;
+    @Resource
+    private SealUsageLedgerService sealUsageLedgerService;
     @Resource
     private InsOrderStateMapper insOrderStateMapper;
     @Resource
@@ -431,7 +434,18 @@
     @Transactional(rollbackFor = Exception.class)
     public int ratifyReport(Integer id, Integer isRatify, String ratifyTell, String sealIds,
                             Integer maSealId, Integer reportSealId, Integer seamSealId) {
-        InsReport insReport = insReportMapper.selectById(id);
+        if (id == null || (isRatify == null || (isRatify != 0 && isRatify != 1))) {
+            throw new ErrorException("鎵瑰噯鍙傛暟涓嶆纭�");
+        }
+        InsReport insReport = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
+                .eq(InsReport::getId, id)
+                .last("FOR UPDATE"));
+        if (insReport == null) {
+            throw new ErrorException("鎶ュ憡涓嶅瓨鍦�");
+        }
+        if (Objects.equals(insReport.getIsRatify(), 1)) {
+            throw new ErrorException("鎶ュ憡宸叉壒鍑嗭紝璇峰嬁閲嶅鎿嶄綔");
+        }
         if (Objects.equals(insReport.getExamineUserId(), SecurityUtils.getUserId().intValue())) {
             throw new ErrorException("瀹℃牳浜哄拰鎵瑰噯浜轰笉鑳戒负鍚屼竴浜猴紝璇烽噸鏂伴�夋嫨鎵瑰噯浜�");
         }
@@ -602,7 +616,12 @@
             });
         }
 
-        return insReportMapper.updateById(insReport);
+        int affected = insReportMapper.updateById(insReport);
+        if (affected != 1) {
+            throw new ErrorException("鎶ュ憡鎵瑰噯鐘舵�佷繚瀛樺け璐�");
+        }
+        sealUsageLedgerService.recordApprovedReport(insReport);
+        return affected;
     }
 
     /**
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/SealUsageLedgerServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/SealUsageLedgerServiceImpl.java
new file mode 100644
index 0000000..fbd0487
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/SealUsageLedgerServiceImpl.java
@@ -0,0 +1,123 @@
+package com.ruoyi.inspect.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.exception.ErrorException;
+import com.ruoyi.inspect.dto.SealUsageCopiesUpdate;
+import com.ruoyi.inspect.dto.SealUsageExportRequest;
+import com.ruoyi.inspect.dto.SealUsageLedgerQuery;
+import com.ruoyi.inspect.mapper.SealUsageLedgerMapper;
+import com.ruoyi.inspect.pojo.InsReport;
+import com.ruoyi.inspect.pojo.SealUsageLedger;
+import com.ruoyi.inspect.service.SealUsageLedgerService;
+import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.system.mapper.UserMapper;
+import jakarta.annotation.Resource;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+
+@Service
+public class SealUsageLedgerServiceImpl implements SealUsageLedgerService {
+
+    @Resource
+    private SealUsageLedgerMapper ledgerMapper;
+
+    @Resource
+    private UserMapper userMapper;
+
+    @Override
+    public IPage<SealUsageLedger> page(Page<SealUsageLedger> page, SealUsageLedgerQuery query) {
+        validateDateRange(query);
+        return ledgerMapper.selectLedgerPage(page, query);
+    }
+
+    @Override
+    public void updateCopies(SealUsageCopiesUpdate update) {
+        if (update == null || update.getId() == null || update.getVersion() == null) {
+            throw new ErrorException("缂哄皯鍙拌处璁板綍鎴栫増鏈俊鎭�");
+        }
+        if (update.getCopies() == null || update.getCopies() < 1) {
+            throw new ErrorException("浠芥暟蹇呴』涓烘鏁存暟");
+        }
+        int affected = ledgerMapper.updateCopies(update.getId(), update.getCopies(), update.getVersion(),
+                SecurityUtils.getUserId().intValue());
+        if (affected != 1) {
+            if (ledgerMapper.selectById(update.getId()) == null) {
+                throw new ErrorException("鐢ㄥ嵃鍙拌处璁板綍涓嶅瓨鍦�");
+            }
+            throw new ErrorException("璁板綍宸茶淇敼锛岃鍒锋柊鍚庨噸璇�");
+        }
+    }
+
+    @Override
+    public List<SealUsageLedger> listForExport(SealUsageExportRequest request) {
+        if (request == null || StringUtils.isBlank(request.getMode())) {
+            throw new ErrorException("璇烽�夋嫨瀵煎嚭鏂瑰紡");
+        }
+        List<SealUsageLedger> result;
+        if ("selected".equals(request.getMode())) {
+            if (request.getIds() == null || request.getIds().isEmpty()) {
+                throw new ErrorException("璇烽�夋嫨瑕佸鍑虹殑璁板綍");
+            }
+            List<Long> ids = new ArrayList<>(new LinkedHashSet<>(request.getIds()));
+            if (ids.stream().anyMatch(Objects::isNull)) {
+                throw new ErrorException("瀵煎嚭璁板綍鍙傛暟涓嶆纭�");
+            }
+            result = ledgerMapper.selectForExport(null, ids);
+            if (result.size() != ids.size()) {
+                throw new ErrorException("閮ㄥ垎鐢ㄥ嵃鍙拌处璁板綍涓嶅瓨鍦ㄦ垨鏃犳潈璁块棶");
+            }
+        } else if ("filtered".equals(request.getMode())) {
+            SealUsageLedgerQuery query = request.getQuery() == null ? new SealUsageLedgerQuery() : request.getQuery();
+            validateDateRange(query);
+            result = ledgerMapper.selectForExport(query, null);
+        } else {
+            throw new ErrorException("涓嶆敮鎸佺殑瀵煎嚭鏂瑰紡");
+        }
+        if (result.isEmpty()) {
+            throw new ErrorException("鏆傛棤鍙鍑虹殑璁板綍");
+        }
+        return result;
+    }
+
+    @Override
+    public void recordApprovedReport(InsReport report) {
+        if (report == null || report.getId() == null || report.getRatifyTime() == null
+                || report.getRatifyUserId() == null || StringUtils.isBlank(report.getCode())
+                || StringUtils.isBlank(report.getSealNames())) {
+            throw new ErrorException("鎶ュ憡鎵瑰噯淇℃伅涓嶅畬鏁达紝鏃犳硶鐢熸垚鐢ㄥ嵃鍙拌处");
+        }
+        User ratifyUser = userMapper.selectById(report.getRatifyUserId());
+        if (ratifyUser == null || StringUtils.isBlank(ratifyUser.getName())) {
+            throw new ErrorException("鎵句笉鍒版姤鍛婃壒鍑嗕汉锛屾棤娉曠敓鎴愮敤鍗板彴璐�");
+        }
+        String projectName = StringUtils.defaultString(ledgerMapper.selectProjectName(report.getInsOrderId()));
+
+        SealUsageLedger ledger = new SealUsageLedger();
+        ledger.setReportId(report.getId());
+        ledger.setReportCode(report.getCode());
+        ledger.setInsOrderId(report.getInsOrderId());
+        ledger.setUseTime(report.getRatifyTime());
+        ledger.setSealIds(report.getSealIds());
+        ledger.setSealNames(report.getSealNames());
+        ledger.setProjectName(projectName);
+        ledger.setUseUserId(report.getRatifyUserId());
+        ledger.setUseUserName(ratifyUser.getName());
+        ledger.setCopies(1);
+        ledger.setVersion(0);
+        ledgerMapper.insert(ledger);
+    }
+
+    private void validateDateRange(SealUsageLedgerQuery query) {
+        if (query != null && query.getStartDate() != null && query.getEndDate() != null
+                && query.getStartDate().isAfter(query.getEndDate())) {
+            throw new ErrorException("寮�濮嬫棩鏈熶笉鑳芥櫄浜庣粨鏉熸棩鏈�");
+        }
+    }
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/util/SealUsageLedgerWordExporter.java b/inspect-server/src/main/java/com/ruoyi/inspect/util/SealUsageLedgerWordExporter.java
new file mode 100644
index 0000000..2681eee
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/util/SealUsageLedgerWordExporter.java
@@ -0,0 +1,114 @@
+package com.ruoyi.inspect.util;
+
+import com.ruoyi.inspect.pojo.SealUsageLedger;
+import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
+import org.apache.poi.xwpf.usermodel.TableRowAlign;
+import org.apache.poi.xwpf.usermodel.TextAlignment;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.apache.poi.xwpf.usermodel.XWPFTable;
+import org.apache.poi.xwpf.usermodel.XWPFTableCell;
+import org.apache.poi.xwpf.usermodel.XWPFTableRow;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+public final class SealUsageLedgerWordExporter {
+
+    private static final String[] HEADERS = {"鏃ユ湡", "鍗扮珷鍚嶇О", "妫�娴嬮」鐩悕绉�", "鎶ュ憡缂栧彿", "浠芥暟", "鐢ㄥ嵃浜虹瀛�"};
+    private static final int[] WIDTHS = {1200, 2300, 1800, 1900, 800, 1400};
+    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy.MM.dd");
+
+    private SealUsageLedgerWordExporter() {
+    }
+
+    public static void write(List<SealUsageLedger> ledgers, OutputStream outputStream) throws IOException {
+        try (XWPFDocument document = new XWPFDocument()) {
+            configurePage(document);
+            addTitle(document);
+            XWPFTable table = document.createTable(ledgers.size() + 1, HEADERS.length);
+            table.setStyleID("TableGrid");
+            table.setTableAlignment(TableRowAlign.CENTER);
+            table.setWidth("100%");
+
+            XWPFTableRow header = table.getRow(0);
+            header.setRepeatHeader(true);
+            header.setHeight(620);
+            for (int col = 0; col < HEADERS.length; col++) {
+                formatCell(header.getCell(col), HEADERS[col], true, WIDTHS[col]);
+            }
+
+            for (int index = 0; index < ledgers.size(); index++) {
+                SealUsageLedger ledger = ledgers.get(index);
+                XWPFTableRow row = table.getRow(index + 1);
+                row.setHeight(780);
+                formatCell(row.getCell(0), ledger.getUseTime().format(DATE_FORMAT), false, WIDTHS[0]);
+                formatCell(row.getCell(1), lineBreakSeals(ledger.getSealNames()), false, WIDTHS[1]);
+                formatCell(row.getCell(2), ledger.getProjectName(), false, WIDTHS[2]);
+                formatCell(row.getCell(3), ledger.getReportCode(), false, WIDTHS[3]);
+                formatCell(row.getCell(4), String.valueOf(ledger.getCopies()), false, WIDTHS[4]);
+                formatCell(row.getCell(5), ledger.getUseUserName(), false, WIDTHS[5]);
+            }
+            document.write(outputStream);
+        }
+    }
+
+    private static void configurePage(XWPFDocument document) {
+        CTSectPr section = document.getDocument().getBody().addNewSectPr();
+        CTPageSz pageSize = section.addNewPgSz();
+        pageSize.setW(BigInteger.valueOf(11906));
+        pageSize.setH(BigInteger.valueOf(16838));
+        CTPageMar margin = section.addNewPgMar();
+        margin.setTop(BigInteger.valueOf(1134));
+        margin.setBottom(BigInteger.valueOf(1134));
+        margin.setLeft(BigInteger.valueOf(850));
+        margin.setRight(BigInteger.valueOf(850));
+    }
+
+    private static void addTitle(XWPFDocument document) {
+        XWPFParagraph paragraph = document.createParagraph();
+        paragraph.setAlignment(ParagraphAlignment.CENTER);
+        paragraph.setSpacingAfter(220);
+        XWPFRun run = paragraph.createRun();
+        run.setText("鍗扮珷浣跨敤鐧昏琛�");
+        run.setBold(true);
+        run.setFontFamily("瀹嬩綋");
+        run.setFontSize(20);
+    }
+
+    private static void formatCell(XWPFTableCell cell, String text, boolean header, int width) {
+        cell.setWidth(String.valueOf(width));
+        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
+        XWPFParagraph paragraph = cell.getParagraphs().get(0);
+        paragraph.setAlignment(ParagraphAlignment.CENTER);
+        paragraph.setVerticalAlignment(TextAlignment.CENTER);
+        paragraph.setSpacingBefore(0);
+        paragraph.setSpacingAfter(0);
+        XWPFRun run = paragraph.createRun();
+        String[] lines = safe(text).split("\\n", -1);
+        for (int i = 0; i < lines.length; i++) {
+            if (i > 0) {
+                run.addBreak();
+            }
+            run.setText(lines[i]);
+        }
+        run.setBold(header);
+        run.setFontFamily("瀹嬩綋");
+        run.setFontSize(header ? 12 : 11);
+    }
+
+    private static String lineBreakSeals(String names) {
+        return safe(names).replace("锛�", "\n").replace(",", "\n");
+    }
+
+    private static String safe(String value) {
+        return value == null ? "" : value;
+    }
+}
diff --git a/inspect-server/src/main/resources/mapper/SealUsageLedgerMapper.xml b/inspect-server/src/main/resources/mapper/SealUsageLedgerMapper.xml
new file mode 100644
index 0000000..d27e385
--- /dev/null
+++ b/inspect-server/src/main/resources/mapper/SealUsageLedgerMapper.xml
@@ -0,0 +1,75 @@
+<?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.inspect.mapper.SealUsageLedgerMapper">
+
+    <sql id="LedgerColumns">
+        ledger.id, ledger.report_id, ledger.report_code, ledger.ins_order_id,
+        ledger.use_time, ledger.seal_ids, ledger.seal_names,
+        COALESCE(io.sample_view, '') AS project_name,
+        ledger.use_user_id, ledger.use_user_name, ledger.copies, ledger.version,
+        ledger.create_user, ledger.create_time, ledger.update_user, ledger.update_time
+    </sql>
+
+    <sql id="LedgerFilters">
+        <if test="query != null">
+            <if test="query.reportCode != null and query.reportCode != ''">
+                AND ledger.report_code LIKE CONCAT('%', #{query.reportCode}, '%')
+            </if>
+            <if test="query.sealName != null and query.sealName != ''">
+                AND ledger.seal_names LIKE CONCAT('%', #{query.sealName}, '%')
+            </if>
+            <if test="query.projectName != null and query.projectName != ''">
+                AND io.sample_view LIKE CONCAT('%', #{query.projectName}, '%')
+            </if>
+            <if test="query.useUserName != null and query.useUserName != ''">
+                AND ledger.use_user_name LIKE CONCAT('%', #{query.useUserName}, '%')
+            </if>
+            <if test="query.startDate != null">
+                AND ledger.use_time <![CDATA[ >= ]]> #{query.startDate}
+            </if>
+            <if test="query.endDate != null">
+                AND ledger.use_time <![CDATA[ < ]]> DATE_ADD(#{query.endDate}, INTERVAL 1 DAY)
+            </if>
+        </if>
+    </sql>
+
+    <select id="selectLedgerPage" resultType="com.ruoyi.inspect.pojo.SealUsageLedger">
+        SELECT <include refid="LedgerColumns"/>
+        FROM seal_usage_ledger ledger
+        LEFT JOIN ins_order io ON io.id = ledger.ins_order_id
+        WHERE 1 = 1
+        <include refid="LedgerFilters"/>
+        ORDER BY ledger.use_time DESC, ledger.id DESC
+    </select>
+
+    <select id="selectForExport" resultType="com.ruoyi.inspect.pojo.SealUsageLedger">
+        SELECT <include refid="LedgerColumns"/>
+        FROM seal_usage_ledger ledger
+        LEFT JOIN ins_order io ON io.id = ledger.ins_order_id
+        WHERE 1 = 1
+        <if test="ids != null and ids.size() > 0">
+            AND ledger.id IN
+            <foreach collection="ids" item="id" open="(" separator="," close=")">
+                #{id}
+            </foreach>
+        </if>
+        <include refid="LedgerFilters"/>
+        ORDER BY ledger.use_time DESC, ledger.id DESC
+    </select>
+
+    <select id="selectProjectName" resultType="java.lang.String">
+        SELECT io.sample_view
+        FROM ins_order io
+        WHERE io.id = #{insOrderId}
+    </select>
+
+    <update id="updateCopies">
+        UPDATE seal_usage_ledger
+        SET copies = #{copies},
+            version = version + 1,
+            update_user = #{updateUser},
+            update_time = NOW()
+        WHERE id = #{id}
+          AND version = #{version}
+    </update>
+</mapper>
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
index 750555d..664c39b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
@@ -138,4 +138,7 @@
      * @return 鍖归厤鐨勮彍鍗曞垪琛�
      */
     public List<SysMenu> selectMenusByPathOrRouteName(@Param("path") String path, @Param("routeName") String routeName);
+
+    /** 鍗扮珷浣跨敤鐧昏瀵规墍鏈夎鑹插紑鏀剧殑鐖惰彍鍗曘�侀〉闈㈠強鎿嶄綔鑿滃崟銆� */
+    public List<Long> selectSealUsageLedgerAccessMenuIds();
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
index 89a84f6..7a1a277 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -19,6 +19,7 @@
 import com.ruoyi.system.domain.SysRoleMenu;
 import com.ruoyi.system.domain.SysUserRole;
 import com.ruoyi.system.mapper.SysRoleDeptMapper;
+import com.ruoyi.system.mapper.SysMenuMapper;
 import com.ruoyi.system.mapper.SysRoleMapper;
 import com.ruoyi.system.mapper.SysRoleMenuMapper;
 import com.ruoyi.system.mapper.SysUserRoleMapper;
@@ -37,6 +38,9 @@
 
     @Autowired
     private SysRoleMenuMapper roleMenuMapper;
+
+    @Autowired
+    private SysMenuMapper menuMapper;
 
     @Autowired
     private SysUserRoleMapper userRoleMapper;
@@ -295,7 +299,14 @@
         int rows = 1;
         // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
         List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
-        for (Long menuId : role.getMenuIds())
+        Set<Long> menuIds = new HashSet<Long>();
+        if (role.getMenuIds() != null)
+        {
+            menuIds.addAll(Arrays.asList(role.getMenuIds()));
+        }
+        // 鍗扮珷浣跨敤鐧昏闈㈠悜鎵�鏈夎鑹诧紱鏂板缓鎴栫紪杈戣鑹叉椂涓�骞朵繚鐣欓〉闈€�佺埗鑿滃崟鍙婃搷浣滄潈闄愩��
+        menuIds.addAll(menuMapper.selectSealUsageLedgerAccessMenuIds());
+        for (Long menuId : menuIds)
         {
             SysRoleMenu rm = new SysRoleMenu();
             rm.setRoleId(role.getRoleId());
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
index a5f6463..f800951 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
@@ -208,8 +208,22 @@
 	    update sys_menu set order_num = #{orderNum} where menu_id = #{menuId}
 	</update>
 
+	<select id="selectSealUsageLedgerAccessMenuIds" resultType="java.lang.Long">
+		SELECT DISTINCT candidate.menu_id
+		FROM sys_menu ledger
+		JOIN sys_menu candidate
+		  ON candidate.menu_id = ledger.parent_id
+		  OR candidate.menu_id = ledger.menu_id
+		  OR (candidate.parent_id = ledger.menu_id
+		      AND candidate.perms IN ('structural:sealUsageLedger:edit',
+		                              'structural:sealUsageLedger:export'))
+		WHERE ledger.component = 'structural/sealManage/usageLedger/index'
+		  AND ledger.menu_type = 'C'
+		  AND ledger.status = '0'
+	</select>
+
 	<delete id="deleteMenuById" parameterType="Long">
 	    delete from sys_menu where menu_id = #{menuId}
 	</delete>
 
-</mapper> 
\ No newline at end of file
+</mapper>

--
Gitblit v1.9.3