From a0d5f2224a6ec422f9f9d1493d81bdc0b161e18b Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期四, 15 十月 2026 11:21:22 +0800
Subject: [PATCH] 质量监督:新增监督计划下发接口(校验已批准且未重复下发,向监督员及被监督人推送站内消息与企业微信通知);详情记录新增监督内容、监督记录、存在问题、整改意见字段;计划导出监督频次按月份数自动计算、监督时间仅显示月份、签名缺失兜底透明图避免导出失败,模板补全标题并新增记录编号;新增日常监督检查记录表 Word 模板并接入记录单导出;方法验证:新增数据处理、质量控制方法、方法结果验证、验证结论及评审、审批意见字段,导出支持评审、审批勾选项与日期格式化,同步调整 Word 模板

---
 cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySupervise.java                       |    7 +
 cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodVerify.java                    |   31 ++++
 cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetails.java                |    4 
 cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java    |  286 ++++++++++++++++++++++++++++++++++------
 cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodVerifyServiceImpl.java |   17 ++
 cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java             |    7 +
 cnas-process/src/main/resources/static/quality-supervise.docx                                 |    0 
 cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodVerifyExportWordDto.java        |   12 +
 cnas-process/src/main/resources/static/daily-supervise-record.docx                            |    0 
 cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java       |   10 +
 cnas-process/src/main/resources/static/method-verify.docx                                     |    0 
 cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java          |   16 ++
 12 files changed, 345 insertions(+), 45 deletions(-)

diff --git a/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java b/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java
index 900d100..369546a 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/controller/QualitySuperviseController.java
@@ -72,6 +72,16 @@
     }
 
     /**
+     * 鐩戠潱璁″垝涓嬪彂
+     * @return
+     */
+    @Operation(summary = "鐩戠潱璁″垝涓嬪彂")
+    @PostMapping("/issueQualitySupervise")
+    public Result issueQualitySupervise(@RequestBody QualitySupervise qualitySupervise){
+        return Result.success(qualitySuperviseService.issueQualitySupervise(qualitySupervise));
+    }
+
+    /**
      * 鐩戠潱璁″垝鍒犻櫎
      * @return
      */
diff --git a/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodVerifyExportWordDto.java b/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodVerifyExportWordDto.java
index 16a4eeb..d51420c 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodVerifyExportWordDto.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/dto/ProcessMethodVerifyExportWordDto.java
@@ -37,4 +37,16 @@
 
     @Schema(description = "纭鏃堕棿")
     private String confirmDateStr;
+
+    @Schema(description = "璇勫鎰忚-鍕鹃�夐」灞曠ず")
+    private String reviewResultStr;
+
+    @Schema(description = "璇勫鎰忚-鏃ユ湡")
+    private String reviewDateStr;
+
+    @Schema(description = "瀹℃壒鎰忚-鍕鹃�夐」灞曠ず")
+    private String approvalResultStr;
+
+    @Schema(description = "瀹℃壒鎰忚-鏃ユ湡")
+    private String approvalDateStr;
 }
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodVerify.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodVerify.java
index 693471b..b5558cb 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodVerify.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/ProcessMethodVerify.java
@@ -5,6 +5,7 @@
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 
 /**
@@ -104,6 +105,36 @@
     @Schema(description = "(鍏朵粬)澶囨敞")
     private String otherRemark;
 
+    @Schema(description = "鏁版嵁澶勭悊")
+    private String dataProcessing;
+
+    @Schema(description = "璐ㄩ噺鎺у埗鏂规硶")
+    private String qualityControlMethod;
+
+    @Schema(description = "鏂规硶缁撴灉楠岃瘉")
+    private String methodResultVerification;
+
+    @Schema(description = "楠岃瘉缁撹")
+    private String verificationConclusion;
+
+    @Schema(description = "璇勫鎰忚-缁撹(鍚屾剰浣跨敤/涓嶈兘浣跨敤/闄愬埗浣跨敤)")
+    private String reviewResult;
+
+    @Schema(description = "璇勫鎰忚-璇勫浜哄憳")
+    private String reviewPerson;
+
+    @Schema(description = "璇勫鎰忚-鏃ユ湡")
+    private LocalDate reviewDate;
+
+    @Schema(description = "瀹℃壒鎰忚-缁撹(鍚屾剰浣跨敤/涓嶈兘浣跨敤/闄愬埗浣跨敤)")
+    private String approvalResult;
+
+    @Schema(description = "瀹℃壒鎰忚-鎶�鏈礋璐d汉")
+    private String approvalPerson;
+
+    @Schema(description = "瀹℃壒鎰忚-鏃ユ湡")
+    private LocalDate approvalDate;
+
     @Schema(description = "纭鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     private LocalDateTime confirmDate;
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySupervise.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySupervise.java
index 78fd1d6..e03a152 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySupervise.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySupervise.java
@@ -57,6 +57,13 @@
     @Schema(description = "鎵瑰噯鍐呭")
     private String ratifyRemark;
 
+    @Schema(description = "涓嬪彂鐘舵��, 0 鏈笅鍙�, 1 宸蹭笅鍙�")
+    private Integer issueStatus;
+
+    @Schema(description = "涓嬪彂鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime issueTime;
+
     @Schema(description = "鍒涘缓浜�")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetails.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetails.java
index 3968983..7626156 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetails.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetails.java
@@ -73,5 +73,9 @@
     @TableField(select = false, exist = false)
     private Integer index;
 
+    // 瀵煎嚭浣跨敤锛氱洃鐫i娆�(鎸夌洃鐫f椂闂存湀浠芥暟璁$畻)
+    @TableField(select = false, exist = false)
+    private String superviseFrequency;
+
 }
 
diff --git a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java
index 40c9a13..e652262 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/pojo/QualitySuperviseDetailsRecord.java
@@ -30,6 +30,18 @@
     @Schema(description = "鐩戠潱鍛�")
     private String supervisor;
 
+    @Schema(description = "鐩戠潱鍐呭(澶氶」椤垮彿鍒嗛殧)")
+    private String superviseContent;
+
+    @Schema(description = "鐩戠潱璁板綍")
+    private String superviseRecord;
+
+    @Schema(description = "瀛樺湪闂(涓嶇鍚堥棶棰樻弿杩�)")
+    private String problemDesc;
+
+    @Schema(description = "鏁存敼鎰忚")
+    private String rectifyAdvice;
+
     @Schema(description = "妫�娴嬮」鐩�")
     private String testItem;
 
@@ -113,5 +125,9 @@
     @TableField(exist = false,select = false)
     private String ratifyUserName;
 
+    @Schema(description = "鐩戠潱鍐呭-鍕鹃�夊睍绀�(瀵煎嚭鐢�)")
+    @TableField(exist = false, select = false)
+    private String superviseContentStr;
+
 }
 
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java b/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java
index 9f67987..832f672 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/QualitySuperviseService.java
@@ -34,6 +34,13 @@
     boolean ratifyQualitySupervise(QualitySupervise qualitySupervise);
 
     /**
+     * 鐩戠潱璁″垝涓嬪彂
+     * @param qualitySupervise
+     * @return
+     */
+    boolean issueQualitySupervise(QualitySupervise qualitySupervise);
+
+    /**
      * 鐩戠潱璁″垝鍒楄〃
      * @return
      */
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodVerifyServiceImpl.java b/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodVerifyServiceImpl.java
index b0438c0..ca298cb 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodVerifyServiceImpl.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodVerifyServiceImpl.java
@@ -1,6 +1,6 @@
 package com.ruoyi.process.service.impl;
 
-import cn.hutool.core.bean.BeanUtil;
+import  cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@@ -389,9 +389,24 @@
         }
         // 纭鏃ユ湡
         processMethodVerifyExportWordDto.setConfirmDateStr(processMethodVerify.getConfirmDate() != null ? processMethodVerify.getConfirmDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")): null);
+        // 璇勫鎰忚
+        processMethodVerifyExportWordDto.setReviewResultStr(buildOpinionCheckBox(processMethodVerify.getReviewResult()));
+        processMethodVerifyExportWordDto.setReviewDateStr(processMethodVerify.getReviewDate() != null ? processMethodVerify.getReviewDate().format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")): null);
+        // 瀹℃壒鎰忚
+        processMethodVerifyExportWordDto.setApprovalResultStr(buildOpinionCheckBox(processMethodVerify.getApprovalResult()));
+        processMethodVerifyExportWordDto.setApprovalDateStr(processMethodVerify.getApprovalDate() != null ? processMethodVerify.getApprovalDate().format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")): null);
         return processMethodVerifyExportWordDto;
     }
 
+    /**
+     * 鎷兼帴"鍚屾剰浣跨敤/涓嶈兘浣跨敤/闄愬埗浣跨敤"鍕鹃�夐」灞曠ず涓�
+     */
+    private String buildOpinionCheckBox(String result) {
+        return ("鍚屾剰浣跨敤".equals(result) ? "鈽�" : "鈻�") + "鍚屾剰浣跨敤銆�"
+                + ("涓嶈兘浣跨敤".equals(result) ? "鈽�" : "鈻�") + "涓嶈兘浣跨敤銆�"
+                + ("闄愬埗浣跨敤".equals(result) ? "鈽�" : "鈻�") + "闄愬埗浣跨敤";
+    }
+
 
     /**
      * 娣诲姞涓婂矖璇�
diff --git a/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java b/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java
index e4d082e..f665e13 100644
--- a/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java
+++ b/cnas-process/src/main/java/com/ruoyi/process/service/impl/QualitySuperviseServiceImpl.java
@@ -20,7 +20,6 @@
 import com.ruoyi.common.constant.MenuJumpPathConstants;
 import com.ruoyi.common.core.domain.entity.InformationNotification;
 import com.ruoyi.common.core.domain.entity.User;
-import com.ruoyi.common.utils.DateImageUtil;
 import com.ruoyi.common.utils.QueryWrappers;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.WxCpUtils;
@@ -57,7 +56,9 @@
 import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 
@@ -214,6 +215,92 @@
     }
 
     /**
+     * 鐩戠潱璁″垝涓嬪彂
+     * @param qualitySupervise
+     * @return
+     */
+    @Override
+    public boolean issueQualitySupervise(QualitySupervise qualitySupervise) {
+        if (qualitySupervise.getSuperviseId() == null) {
+            throw new ErrorException("缂哄皯鐩戠潱璁″垝id");
+        }
+        QualitySupervise supervise = baseMapper.selectById(qualitySupervise.getSuperviseId());
+        if (supervise == null) {
+            throw new ErrorException("鏈壘鍒扮洃鐫h鍒�");
+        }
+        if (!Integer.valueOf(1).equals(supervise.getRatifyStatus())) {
+            throw new ErrorException("璁″垝鏈壒鍑嗭紝涓嶈兘涓嬪彂");
+        }
+        if (Integer.valueOf(1).equals(supervise.getIssueStatus())) {
+            throw new ErrorException("璁″垝宸蹭笅鍙戯紝涓嶈兘閲嶅涓嬪彂");
+        }
+
+        baseMapper.update(null, Wrappers.<QualitySupervise>lambdaUpdate()
+                .eq(QualitySupervise::getSuperviseId, supervise.getSuperviseId())
+                .set(QualitySupervise::getIssueStatus, 1)
+                .set(QualitySupervise::getIssueTime, LocalDateTime.now())
+        );
+
+        // 褰撳墠鐧诲綍鐢ㄦ埛
+        Integer userId = SecurityUtils.getUserId().intValue();
+        User user = userMapper.selectById(userId);
+
+        // 鎺ユ敹浜�: 璁″垝鐩戠潱鍛� + 鎵�鏈夋槑缁嗙殑琚洃鐫d汉(鍘婚噸)
+        LinkedHashSet<Integer> receiveUserIds = new LinkedHashSet<>();
+        if (StringUtils.isNotBlank(supervise.getRecordUserIds())) {
+            for (String idStr : supervise.getRecordUserIds().split(",")) {
+                if (StringUtils.isNotBlank(idStr)) {
+                    receiveUserIds.add(Integer.valueOf(idStr.trim()));
+                }
+            }
+        }
+        List<QualitySuperviseDetails> detailsList = qualitySuperviseDetailsMapper.selectList(Wrappers.<QualitySuperviseDetails>lambdaQuery()
+                .eq(QualitySuperviseDetails::getSuperviseId, supervise.getSuperviseId()));
+        for (QualitySuperviseDetails detail : detailsList) {
+            if (detail.getSupervisedUserId() != null) {
+                receiveUserIds.add(detail.getSupervisedUserId());
+            }
+        }
+
+        // 娑堟伅鍙戦��
+        for (Integer receiveUserId : receiveUserIds) {
+            InformationNotification info = new InformationNotification();
+            // 鍙戦�佷汉
+            info.setCreateUser(user.getName());
+            info.setMessageType("6");
+            info.setTheme("CNAS璐ㄩ噺鐩戠潱璁″垝涓嬪彂閫氱煡");
+            info.setContent(supervise.getSuperviseName() + " 璐ㄩ噺鐩戠潱璁″垝宸蹭笅鍙戯紝璇锋寜璁″垝寮�灞曡川閲忕洃鐫o紝骞跺強鏃跺~鍐欐棩甯哥洃鐫f鏌ヨ褰�");
+            info.setSenderId(userId);
+            // 鎺ユ敹浜�
+            info.setConsigneeId(receiveUserId);
+            info.setJumpPath(MenuJumpPathConstants.QUALITY_SUPERVISE);
+            informationNotificationService.addInformationNotification(info);
+        }
+
+        // 鍙戦�佷紒涓氬井淇¢�氱煡
+        threadPoolTaskExecutor.execute(() -> {
+            String message = "";
+            message += "CNAS璐ㄩ噺鐩戠潱璁″垝涓嬪彂閫氱煡";
+            message += "\n璇峰幓杩囩▼瑕佹眰-璐ㄩ噺鐩戠潱璁″垝";
+            message += "\n" + supervise.getSuperviseName() + " 璐ㄩ噺鐩戠潱璁″垝宸蹭笅鍙戯紝璇锋寜璁″垝寮�灞曡川閲忕洃鐫o紝骞跺強鏃跺~鍐欐棩甯哥洃鐫f鏌ヨ褰�";
+            for (Integer receiveUserId : receiveUserIds) {
+                User receiveUser = userMapper.selectById(receiveUserId);
+                if (receiveUser == null) {
+                    continue;
+                }
+                //鍙戦�佷紒涓氬井淇℃秷鎭�氱煡
+                try {
+                    WxCpUtils.inform(receiveUser.getAccount(), message, null);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+        return true;
+    }
+
+    /**
      * 鐩戠潱璁″垝鍒楄〃
      * @param page
      * @param qualitySupervise
@@ -283,10 +370,8 @@
             for (String userIdStr : userIds) {
                 // 杞崲涓篿nt绫诲瀷
                 Integer userId = Integer.valueOf(userIdStr);
-                // 鑾峰彇浜哄憳绛惧悕瀵硅薄
-                PictureRenderData finalUserSignatureUrl = UserUtils.getFinalUserSignatureUrl(userId);
-                // 灏嗕汉鍛樼鍚嶅璞℃坊鍔犲埌闆嗗悎涓�
-                recordUserDataList.add(finalUserSignatureUrl);
+                // 鑾峰彇浜哄憳绛惧悕瀵硅薄(缂哄け鏃跺厹搴曢�忔槑鍥�, 閬垮厤瀵煎嚭澶辫触)
+                recordUserDataList.add(signatureOrTransparent(userId));
             }
         }
 
@@ -302,6 +387,8 @@
         int index = 1;
         for (QualitySuperviseDetails qualitySuperviseDetail : qualitySuperviseDetails) {
             qualitySuperviseDetail.setIndex(index);
+            qualitySuperviseDetail.setSuperviseFrequency(buildSuperviseFrequency(qualitySuperviseDetail.getSuperviseTime()));
+            qualitySuperviseDetail.setSuperviseTime(toMonthText(qualitySuperviseDetail.getSuperviseTime()));
             index++;
         }
 
@@ -315,14 +402,14 @@
                 new HashMap<String, Object>() {{
                     put("year", qualitySupervise.getSuperviseYear());
                     put("superviseDetailList", qualitySuperviseDetails);
-                    put("writeUrl", StringUtils.isNotBlank(writeUrl) ? Pictures.ofLocal(imgUrl + "/" + writeUrl).create() : null);
-                    put("ratifyUrl", StringUtils.isNotBlank(finalRatifyUrl) ? Pictures.ofLocal(imgUrl + "/" + finalRatifyUrl).create() : null);
-                    put("writeDateUrl", qualitySupervise.getWriteTime() != null ?
-                            Pictures.ofStream(DateImageUtil.createDateImage(qualitySupervise.getWriteTime())).create() : null);
-                    put("ratifyDateUrl", qualitySupervise.getRatifyTime() != null ?
-                            Pictures.ofStream(DateImageUtil.createDateImage(qualitySupervise.getRatifyTime())).create() : null);
-                    put("recordUserUrl1", recordUserDataList.get(0));
-                    put("recordUserUrl2", recordUserDataList.get(1));
+                    put("writeUrl", orTransparentPicture(StringUtils.isNotBlank(writeUrl) ? Pictures.ofLocal(imgUrl + "/" + writeUrl).create() : null));
+                    put("ratifyUrl", orTransparentPicture(StringUtils.isNotBlank(finalRatifyUrl) ? Pictures.ofLocal(imgUrl + "/" + finalRatifyUrl).create() : null));
+                    put("writeDateStr", qualitySupervise.getWriteTime() != null ?
+                            qualitySupervise.getWriteTime().format(SUPERVISE_DATE_FORMATTER) : "");
+                    put("ratifyDateStr", qualitySupervise.getRatifyTime() != null ?
+                            qualitySupervise.getRatifyTime().format(SUPERVISE_DATE_FORMATTER) : "");
+                    put("recordUserUrl1", orTransparentPicture(recordUserDataList.get(0)));
+                    put("recordUserUrl2", orTransparentPicture(recordUserDataList.get(1)));
                 }});
 
         try {
@@ -342,6 +429,49 @@
         }
 
 
+    }
+
+    /**
+     * 鐩戠潱棰戞: 鎸夌洃鐫f椂闂翠腑鐨勬湀浠戒釜鏁拌绠�, 濡� "2026.3" -> "1娆�/骞�", "3鏈堛��12鏈�" -> "2娆�/骞�"
+     */
+    private static String buildSuperviseFrequency(String superviseTime) {
+        if (StringUtils.isBlank(superviseTime)) {
+            return "";
+        }
+        int count = 0;
+        for (String part : superviseTime.split("[銆�,锛�;锛�/\\s]+")) {
+            if (part.matches(".*\\d.*")) {
+                count++;
+            }
+        }
+        return count > 0 ? count + "娆�/骞�" : "";
+    }
+
+    /**
+     * 鐩戠潱鏃堕棿: 琛ㄦ牸涓彧灞曠ず鏈堜唤, 濡� "2026.3" -> "3鏈�", "3鏈堛��12鏈�" -> "3鏈堛��12鏈�"
+     */
+    private static String toMonthText(String superviseTime) {
+        if (StringUtils.isBlank(superviseTime)) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        for (String part : superviseTime.split("[銆�,锛�;锛沒+")) {
+            String s = part.trim();
+            if (s.isEmpty()) {
+                continue;
+            }
+            int idx = s.lastIndexOf('.');
+            String month = (idx >= 0 ? s.substring(idx + 1) : s).replaceAll("\\D", "");
+            if (month.isEmpty() || month.length() > 2) {
+                return superviseTime;
+            }
+            month = month.replaceFirst("^0+(?=\\d)", "");
+            if (sb.length() > 0) {
+                sb.append("銆�");
+            }
+            sb.append(month).append("鏈�");
+        }
+        return sb.length() > 0 ? sb.toString() : superviseTime;
     }
 
     /************************************************ 璁板綍 ******************************************************/
@@ -408,13 +538,9 @@
             detailsRecord.setSuperviseDetailsId(superviseDetailsId);
             detailsRecord.setTestMember(qualitySuperviseDetails.getSupervisee());
             detailsRecord.setSupervisor(supervisor);
-
-            detailsRecord.setPersonnel(SecurityUtils.getLoginUser().getUser().getNickName() + "鏈夌浉搴旀娴嬪憳鐨勪笂宀楄瘉");
-            detailsRecord.setEnvironment("娓╁害锛�()鈩� 婀垮害锛�()%");
-            detailsRecord.setInspectionRecord("妫�娴嬩汉鍛�" + SecurityUtils.getLoginUser().getUser().getNickName() + "杩涜妫�娴嬭褰曪紝璁板綍鍐呭鐪熷疄鏈夋晥");
-            detailsRecord.setExaminingReport("鐢�" + SecurityUtils.getLoginUser().getUser().getNickName() + "鍑虹ず鐨勬娴嬫姤鍛婄鍚堣鑼冭姹�");
-            detailsRecord.setSupervisionEvaluation("妫�娴嬫寜鐓ц姹傝繘琛岋紝鍒ゅ畾涓烘弧鎰�");
-            detailsRecord.setHandlingAdvice("/");
+            // 榛樿鐩戠潱妫�娴嬫棩鏈熶负褰撳ぉ
+            detailsRecord.setTestDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy.M.d")));
+            detailsRecord.setProblemDesc("鏃�");
 
         }
         // 娣诲姞鎵瑰噯浜哄悕绉�
@@ -517,7 +643,7 @@
     }
 
     /**
-     * 瀵煎嚭鐩戠潱璁板綍琛�
+     * 瀵煎嚭鐩戠潱璁板綍琛�(鏃ュ父鐩戠潱妫�鏌ヨ褰曡〃)
      * @param superviseDetailsId
      * @param response
      */
@@ -525,33 +651,26 @@
     public void exportSuperviseDetailRecord(Integer superviseDetailsId, HttpServletResponse response) {
         QualitySuperviseDetailsRecord recordDto = qualitySuperviseDetailsRecordMapper.selectSuperviseDetailRecord(superviseDetailsId);
 
-        // 鏌ヨ妫�娴嬩汉鍛�
-        User tserUser = new User();
-        if (StringUtils.isNotBlank(recordDto.getTestMember())) {
-            tserUser = userMapper.selectOne(Wrappers.<User>lambdaQuery()
-                    .eq(User::getName, recordDto.getTestMember())
-                    .last("limit 1"));
-        }
+        // 鐩戠潱鍐呭鍕鹃�夊睍绀轰覆(鐓х焊寮犺〃鎺掑竷)
+        recordDto.setSuperviseContentStr(buildSuperviseContentStr(recordDto.getSuperviseContent()));
 
         // 鑾峰彇璺緞
-        InputStream inputStream = this.getClass().getResourceAsStream("/static/supervision-detail-record.docx");
+        InputStream inputStream = this.getClass().getResourceAsStream("/static/daily-supervise-record.docx");
         ConfigureBuilder builder = Configure.builder();
         builder.useSpringEL(true);
-        User finalTserUser = tserUser;
         XWPFTemplate template = XWPFTemplate.compile(inputStream, builder.build()).render(
                 new HashMap<String, Object>() {{
                     put("supervision", recordDto);
-                    put("testMemberUrl", UserUtils.getFinalUserSignatureUrl(finalTserUser.getId()));
-                    put("supervisoruUrl", UserUtils.getFinalUserSignatureUrl(recordDto.getSupervisor()));
-                    put("technicalDirectorUrl", UserUtils.getFinalUserSignatureUrl(recordDto.getRatifyUserId()));
-                    put("technicalDirectorDateUrl", recordDto.getRatifyTime() != null ?
-                            Pictures.ofStream(DateImageUtil.createDateImage(recordDto.getRatifyTime())).create() : null);
+                    put("supervisorUrl", signatureOrTransparent(recordDto.getSupervisor()));
+                    put("qualityUrl", signatureOrTransparent(recordDto.getRatifyUserId()));
+                    put("qualityDateStr", recordDto.getRatifyTime() != null ?
+                            recordDto.getRatifyTime().format(RECORD_DATE_FORMATTER) : "");
                 }});
 
         try {
             response.setContentType("application/msword");
             String fileName = URLEncoder.encode(
-                    "瀵煎嚭鐩戠潱璁板綍琛�", "UTF-8");
+                    "鏃ュ父鐩戠潱妫�鏌ヨ褰曡〃", "UTF-8");
             response.setHeader("Content-disposition",
                     "attachment;filename=" + fileName + ".docx");
             OutputStream os = response.getOutputStream();
@@ -562,6 +681,85 @@
         } catch (Exception e) {
             e.printStackTrace();
             throw new RuntimeException("瀵煎嚭澶辫触");
+        }
+    }
+
+    /**
+     * 鐩戠潱鍐呭(9椤�, 鎸夌焊寮犺〃妯帓椤哄簭)
+     */
+    private static final String[] SUPERVISE_CONTENT_ITEMS = {
+            "浜哄憳鎸佽瘉鍙婂煿璁�", "璁炬柦鍙婄幆澧冩潯浠�", "妫�娴嬫柟娉�",
+            "浠櫒璁惧绠$悊", "娴嬮噺婧簮鎬�", "鏍囧噯鐗╄川绠$悊",
+            "鏍峰搧鍒跺鍜屽缃�", "妫�娴嬫暟鎹鐞�", "缁撴灉鎶ュ憡缁撴灉"
+    };
+
+    /**
+     * 鎷兼帴"鐩戠潱鍐呭"鍕鹃�夊睍绀轰覆, 姣�3椤逛竴琛�
+     */
+    private String buildSuperviseContentStr(String superviseContent) {
+        String content = StringUtils.isNotBlank(superviseContent) ? superviseContent : "";
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < SUPERVISE_CONTENT_ITEMS.length; i++) {
+            String item = SUPERVISE_CONTENT_ITEMS[i];
+            sb.append(content.contains(item) ? "鈽�" : "鈻�").append(item).append("銆�銆�");
+            if (i % 3 == 2) {
+                sb.append("\n");
+            }
+        }
+        return sb.toString().trim();
+    }
+
+    /**
+     * 鍏ㄩ�忔槑 1x1 PNG(宸查獙璇佸儚绱� A=0, 鎷変几鍒板師鏍囩灏哄鍚庝笉鍙), 鍥剧墖缂哄け鏃跺厹搴�
+     */
+    private static final byte[] TRANSPARENT_PNG = Base64.getDecoder().decode(
+            "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAANSURBVBhXY2BgYGAAAAAFAAGKM+MAAAAAAElFTkSuQmCC");
+
+    /**
+     * 鍥剧墖鏍囩鍊煎厹搴�: null 鎴栨湰鍦板浘鐗囪鍙栧け璐�(濡傜鍚嶆枃浠剁己澶�)鏃惰繑鍥為�忔槑鍥剧墖
+     */
+    private PictureRenderData orTransparentPicture(PictureRenderData picture) {
+        if (picture != null) {
+            try {
+                byte[] data = picture.readPictureData();
+                if (data != null && data.length > 0) {
+                    return picture;
+                }
+            } catch (Exception ignored) {
+            }
+        }
+        return Pictures.ofBytes(TRANSPARENT_PNG).create();
+    }
+
+    /**
+     * 瀵煎嚭鏃ユ湡鏂囧瓧鏍煎紡(濡� 2026骞�1鏈�9鏃�)
+     */
+    private static final DateTimeFormatter SUPERVISE_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy骞碝鏈坉鏃�");
+
+    /**
+     * 璁板綍琛ㄦ棩鏈熸枃瀛楁牸寮�(涓庤〃鍐�"妫�娴嬫棩鏈�"瀛楁涓�鑷�, 濡� 2026.10.14)
+     */
+    private static final DateTimeFormatter RECORD_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy.M.d");
+
+    /**
+     * 鐢ㄦ埛绛惧悕鍏滃簳(鎸塈D): 浜哄憳涓嶅瓨鍦ㄦ垨绛惧悕鏈厤缃椂鎺ュ彛浼氱洿鎺ユ姏閿�, 姝ゅ杩斿洖閫忔槑鍥剧墖
+     */
+    private PictureRenderData signatureOrTransparent(Integer userId) {
+        try {
+            return orTransparentPicture(UserUtils.getFinalUserSignatureUrl(userId));
+        } catch (Exception e) {
+            return Pictures.ofBytes(TRANSPARENT_PNG).create();
+        }
+    }
+
+    /**
+     * 鐢ㄦ埛绛惧悕鍏滃簳(鎸夊鍚�): 浜哄憳涓嶅瓨鍦ㄦ垨绛惧悕鏈厤缃椂鎺ュ彛浼氱洿鎺ユ姏閿�, 姝ゅ杩斿洖閫忔槑鍥剧墖
+     */
+    private PictureRenderData signatureOrTransparent(String userName) {
+        try {
+            return orTransparentPicture(UserUtils.getFinalUserSignatureUrl(userName));
+        } catch (Exception e) {
+            return Pictures.ofBytes(TRANSPARENT_PNG).create();
         }
     }
 
@@ -861,10 +1059,10 @@
         XWPFTemplate template = XWPFTemplate.compile(inputStream, builder.build()).render(
                 new HashMap<String, Object>() {{
                     put("control", exportDto);
-                    put("discovererUrl", StringUtils.isNotBlank(finalDiscovererUrl) ? Pictures.ofLocal(imgUrl + "/" + finalDiscovererUrl).create() : null);
-                    put("responsibleUrl", StringUtils.isNotBlank(finalResponsibleUrl) ? Pictures.ofLocal(imgUrl + "/" + finalResponsibleUrl).create() : null);
-                    put("correctiveUrl", StringUtils.isNotBlank(finalCorrectiveUrl) ? Pictures.ofLocal(imgUrl + "/" + finalCorrectiveUrl).create() : null);
-                    put("qualityUrl", StringUtils.isNotBlank(finalQualityUrl) ? Pictures.ofLocal(imgUrl + "/" + finalQualityUrl).create() : null);
+                    put("discovererUrl", orTransparentPicture(StringUtils.isNotBlank(finalDiscovererUrl) ? Pictures.ofLocal(imgUrl + "/" + finalDiscovererUrl).create() : null));
+                    put("responsibleUrl", orTransparentPicture(StringUtils.isNotBlank(finalResponsibleUrl) ? Pictures.ofLocal(imgUrl + "/" + finalResponsibleUrl).create() : null));
+                    put("correctiveUrl", orTransparentPicture(StringUtils.isNotBlank(finalCorrectiveUrl) ? Pictures.ofLocal(imgUrl + "/" + finalCorrectiveUrl).create() : null));
+                    put("qualityUrl", orTransparentPicture(StringUtils.isNotBlank(finalQualityUrl) ? Pictures.ofLocal(imgUrl + "/" + finalQualityUrl).create() : null));
                 }});
 
         try {
@@ -1240,10 +1438,10 @@
         XWPFTemplate template = XWPFTemplate.compile(inputStream, builder.build()).render(
                 new HashMap<String, Object>() {{
                     put("correct", detailsCorrectDto);
-                    put("raiseUrl", StringUtils.isNotBlank(finalRaiseUrl) ? Pictures.ofLocal(imgUrl + "/" + finalRaiseUrl).create() : null);
-                    put("causeUrl", StringUtils.isNotBlank(finalCauseUrl) ? Pictures.ofLocal(imgUrl + "/" + finalCauseUrl).create() : null);
-                    put("correctUrl", StringUtils.isNotBlank(finalCorrectUrl) ? Pictures.ofLocal(imgUrl + "/" + finalCorrectUrl).create() : null);
-                    put("validationUrl", StringUtils.isNotBlank(finalValidationUrl) ? Pictures.ofLocal(imgUrl + "/" + finalValidationUrl).create() : null);
+                    put("raiseUrl", orTransparentPicture(StringUtils.isNotBlank(finalRaiseUrl) ? Pictures.ofLocal(imgUrl + "/" + finalRaiseUrl).create() : null));
+                    put("causeUrl", orTransparentPicture(StringUtils.isNotBlank(finalCauseUrl) ? Pictures.ofLocal(imgUrl + "/" + finalCauseUrl).create() : null));
+                    put("correctUrl", orTransparentPicture(StringUtils.isNotBlank(finalCorrectUrl) ? Pictures.ofLocal(imgUrl + "/" + finalCorrectUrl).create() : null));
+                    put("validationUrl", orTransparentPicture(StringUtils.isNotBlank(finalValidationUrl) ? Pictures.ofLocal(imgUrl + "/" + finalValidationUrl).create() : null));
                 }});
 
         try {
diff --git a/cnas-process/src/main/resources/static/daily-supervise-record.docx b/cnas-process/src/main/resources/static/daily-supervise-record.docx
new file mode 100644
index 0000000..d58c164
--- /dev/null
+++ b/cnas-process/src/main/resources/static/daily-supervise-record.docx
Binary files differ
diff --git a/cnas-process/src/main/resources/static/method-verify.docx b/cnas-process/src/main/resources/static/method-verify.docx
index 8ab5461..2276f1f 100644
--- a/cnas-process/src/main/resources/static/method-verify.docx
+++ b/cnas-process/src/main/resources/static/method-verify.docx
Binary files differ
diff --git a/cnas-process/src/main/resources/static/quality-supervise.docx b/cnas-process/src/main/resources/static/quality-supervise.docx
index 2d94d9c..7b5fe20 100644
--- a/cnas-process/src/main/resources/static/quality-supervise.docx
+++ b/cnas-process/src/main/resources/static/quality-supervise.docx
Binary files differ

--
Gitblit v1.9.3