From 82ce59218139d9fefeae7b9e5fbc88b499ff023f Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期四, 08 十月 2026 13:35:06 +0800
Subject: [PATCH] feat(inspect): 新增新聚检验订单编辑功能并优化报告生成流程 - 新增 updateNewJuInsOrder 接口支持新聚检验订单修改 - 增加文件上传大小限制至200MB,请求大小限制至400MB - 在设备信息中新增出厂编号字段显示 - 优化温湿度处理逻辑,报告中仅显示温度信息 - 新增印章管理功能,支持MA标志章、报告章和骑缝章配置 - 完善检验报告生成流程,增加多种报告类型常量定义 - 优化附件上传功能,增加空值检查和返回值处理 - 调整委托编号生成逻辑,完善新聚订单可编辑性判断 - 更新CNAS流程中报告编号使用正式报告编号替代委托编号

---
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java |  428 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 336 insertions(+), 92 deletions(-)

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 6d549f7..4ae8fce 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
@@ -6,6 +6,7 @@
 import com.alibaba.excel.ExcelWriter;
 import com.alibaba.excel.write.metadata.WriteSheet;
 import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.aspose.words.FontSettings;
 import com.aspose.words.License;
 import com.aspose.words.SaveFormat;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -17,6 +18,9 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.deepoove.poi.XWPFTemplate;
+import com.deepoove.poi.config.Configure;
+import com.deepoove.poi.data.PictureRenderData;
+import com.deepoove.poi.data.PictureType;
 import com.deepoove.poi.data.Pictures;
 import com.itextpdf.text.BadElementException;
 import com.itextpdf.text.DocumentException;
@@ -24,7 +28,9 @@
 import com.itextpdf.text.pdf.PdfReader;
 import com.itextpdf.text.pdf.PdfStamper;
 import com.ruoyi.basic.mapper.IfsInventoryQuantityMapper;
+import com.ruoyi.basic.mapper.SealConfigMapper;
 import com.ruoyi.basic.pojo.IfsInventoryQuantity;
+import com.ruoyi.basic.pojo.SealConfig;
 import com.ruoyi.basic.vo.IfsInventoryQuantityVO;
 import com.ruoyi.common.config.WechatProperty;
 import com.ruoyi.common.constant.InsOrderTypeConstants;
@@ -44,6 +50,9 @@
 import com.ruoyi.inspect.service.InsOrderService;
 import com.ruoyi.inspect.service.InsReportService;
 import com.ruoyi.inspect.service.RawMaterialOrderService;
+import com.ruoyi.inspect.util.PreserveReportPicturePlaceholderHandler;
+import com.ruoyi.inspect.util.ReportSealLayoutUtil;
+import com.ruoyi.inspect.util.ReportSignaturePictureUtils;
 import com.ruoyi.system.mapper.UserMapper;
 import com.ruoyi.system.service.InformationNotificationService;
 import lombok.extern.slf4j.Slf4j;
@@ -84,6 +93,15 @@
 @Slf4j
 public class InsReportServiceImpl extends ServiceImpl<InsReportMapper, InsReport>
         implements InsReportService {
+    static {
+        // Linux 鏈嶅姟鍣ㄧ己灏戜腑鏂囧瓧浣擄紝鎶ュ憡杞� PDF 鏃朵腑鏂囦細鍙樻垚鏂瑰潡锛涘皢妯℃澘瀛椾綋鏄犲皠鍒� Noto CJK 鍏滃簳銆�
+        FontSettings.addFontSubstitutes("瀹嬩綋", "Noto Serif CJK SC");
+        FontSettings.addFontSubstitutes("榛戜綋", "Noto Sans CJK SC");
+    }
+
+    private static final int DETECTION_REPORT = 0;
+    private static final int INSPECTION_REPORT = 1;
+
     @Resource
     private UserMapper userMapper;
     @Resource
@@ -103,6 +121,8 @@
     private InsOrderMapper insOrderMapper;
     @Resource
     private IfsInventoryQuantityMapper ifsInventoryQuantityMapper;
+    @Resource
+    private SealConfigMapper sealConfigMapper;
     @Resource
     private InsUnqualifiedHandlerMapper insUnqualifiedHandlerMapper;
     @Resource
@@ -207,30 +227,30 @@
         info.setViewStatus(false);
         info.setJumpPath(MenuJumpPathConstants.REPORT_PREPARATION);
         informationNotificationService.addInformationNotification(info);
-        //绯荤粺鐢熸垚鎶ュ憡鍦板潃
-        String url = insReport.getUrl();
-        //鎵嬪姩涓婁紶鎶ュ憡鍦板潃
-        String urlS = insReport.getUrlS();
+        String primaryReportUrl = getPrimaryReportUrl(insReport);
 
         // 鍒ゆ柇鏄惁鏄師鏉愭枡  闇�瑕佹浛鎹�****鎴愪緵搴斿晢
         IfsInventoryQuantity one = ifsInventoryQuantityMapper.selectOne(new LambdaQueryWrapper<IfsInventoryQuantity>()
                 .eq(IfsInventoryQuantity::getId, order.getIfsInventoryId()));
         if (one != null) {
             if (isRawMater && order.getOrderType().equals(InsOrderTypeConstants.ENTER_THE_FACTORY)) {
-                changeText(new HashMap<String, String>() {{
-                    put("**********", one.getSupplierName());
-                }}, (StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
+                for (String reportUrl : getApprovalReportUrls(insReport)) {
+                    changeText(new HashMap<String, String>() {{
+                        put("**********", one.getSupplierName());
+                    }}, reportUrl.replace("/word", wordUrl));
+                }
             }
         }
 
-        wordInsertUrl(new HashMap<String, Object>() {{
-            put("writeUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
+        Map<String, Object> writeMarks = new HashMap<String, Object>() {{
+            put("writeUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
             put("writeDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
-            put("insUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
-        }}, (StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
+            put("insUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
+        }};
+        writeMarksToReportFiles(insReport, writeMarks);
 
         // 淇敼涓存椂pdf
-        String tempUrlPdf = wordToPdfTemp((StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
+        String tempUrlPdf = wordToPdfTemp(primaryReportUrl.replace("/word", wordUrl));
         insReport.setTempUrlPdf("/word/" + tempUrlPdf);
 
         insReportMapper.updateById(insReport);
@@ -301,6 +321,9 @@
             if (userId == null) {
                 throw new ErrorException("缂哄皯鎵瑰噯浜�");
             }
+            if (Objects.equals(insReport.getExamineUserId(), userId)) {
+                throw new ErrorException("瀹℃牳浜哄拰鎵瑰噯浜轰笉鑳戒负鍚屼竴浜猴紝璇烽噸鏂伴�夋嫨鎵瑰噯浜�");
+            }
         }
         insReport.setRatifyUserId(userId);//鎵瑰噯浜�
         //鑾峰彇瀹℃牳浜虹殑绛惧悕鍦板潃
@@ -328,17 +351,15 @@
         info.setViewStatus(false);
         info.setJumpPath(MenuJumpPathConstants.REPORT_PREPARATION);
         informationNotificationService.addInformationNotification(info);
-        //绯荤粺鐢熸垚鎶ュ憡鍦板潃
-        String url = insReport.getUrl();
-        //鎵嬪姩涓婁紶鎶ュ憡鍦板潃
-        String urlS = insReport.getUrlS();
-        wordInsertUrl(new HashMap<String, Object>() {{
-            put("examineUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
+        String primaryReportUrl = getPrimaryReportUrl(insReport);
+        Map<String, Object> examineMarks = new HashMap<String, Object>() {{
+            put("examineUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
             put("examineDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
-        }}, (StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
+        }};
+        writeMarksToReportFiles(insReport, examineMarks);
 
         // 淇敼涓存椂pdf
-        String tempUrlPdf = wordToPdfTemp((StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl));
+        String tempUrlPdf = wordToPdfTemp(primaryReportUrl.replace("/word", wordUrl));
         insReport.setTempUrlPdf("/word/" + tempUrlPdf);
 
         // 鍙戦�佷紒涓氬井淇¢�氱煡(閫氱煡鎵瑰噯浜哄鎵�)
@@ -383,8 +404,12 @@
     //鎵瑰噯
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public int ratifyReport(Integer id, Integer isRatify, String ratifyTell) {
+    public int ratifyReport(Integer id, Integer isRatify, String ratifyTell, String sealIds,
+                            Integer maSealId, Integer reportSealId, Integer seamSealId) {
         InsReport insReport = insReportMapper.selectById(id);
+        if (Objects.equals(insReport.getExamineUserId(), SecurityUtils.getUserId().intValue())) {
+            throw new ErrorException("瀹℃牳浜哄拰鎵瑰噯浜轰笉鑳戒负鍚屼竴浜猴紝璇烽噸鏂伴�夋嫨鎵瑰噯浜�");
+        }
         insReport.setIsRatify(isRatify);
         if (ObjectUtils.isNotEmpty(ratifyTell)) {
             insReport.setRatifyTell(ratifyTell);
@@ -454,45 +479,79 @@
         InsOrder order = insOrderMapper.selectById(insOrderId);
         boolean isRawMater = order.getTypeSource() != null && order.getTypeSource().equals(1);
 
-        //鑾峰彇鍦烘墍鐨勬姤鍛婁笓鐢ㄧ珷
-        String sealUrl;
-        String laboratory = insOrderMapper.selectById(insReport.getInsOrderId()).getLaboratory();
-        try {
-            String type = "";
-            if (isRawMater && order.getOrderType().equals(InsOrderTypeConstants.ENTER_THE_FACTORY)) {
-                type = "杩涘巶鎶ュ憡";
-            } else {
-                type = "濮旀墭鎶ュ憡";
-            }
-            sealUrl = insReportMapper.getLaboratoryByName(laboratory, type);
-        } catch (Exception e) {
-            throw new ErrorException(laboratory + "鎵句笉鍒版姤鍛婁笓鐢ㄧ珷");
+        // 鏂扮増鎸夌敤閫旈�夋嫨锛歁A绔犮�佹姤鍛婄珷锛堟ā鏉� seal1/seal2锛夈�丳DF楠戠紳绔犮��
+        // 鍏煎鏃у墠绔細鍙紶 sealIds 鏃讹紝绗竴鏋氱珷缁х画浣滀负鎶ュ憡绔犲拰楠戠紳绔狅紝MA绔犵暀绌恒��
+        SealConfig maSeal;
+        SealConfig reportSeal;
+        SealConfig seamSeal;
+        boolean positionMode = maSealId != null || reportSealId != null || seamSealId != null;
+        if (positionMode) {
+            maSeal = resolveSeal(maSealId);
+            reportSeal = resolveSeal(reportSealId);
+            seamSeal = resolveSeal(seamSealId);
+        } else {
+            SealConfig legacySeal = resolveSeals(sealIds).get(0);
+            maSeal = null;
+            reportSeal = legacySeal;
+            seamSeal = legacySeal;
         }
-        if (StringUtils.isBlank(sealUrl)) {
-            throw new ErrorException(laboratory + "鎵句笉鍒版姤鍛婁笓鐢ㄧ珷");
-        }
-        //绯荤粺鐢熸垚鎶ュ憡鍦板潃
-        String url = insReport.getUrl();
-        //鎵嬪姩涓婁紶鎶ュ憡鍦板潃
-        String urlS = insReport.getUrlS();
-        String finalUrl = (StrUtil.isBlank(urlS) ? url : urlS).replace("/word", wordUrl);
 
-        wordInsertUrl(new HashMap<String, Object>() {{
-            put("ratifyUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
-            put("ratifyDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
-            put("seal1", Pictures.ofLocal(imgUrl + "/" + sealUrl).create());
-            put("seal2", Pictures.ofLocal(imgUrl + "/" + sealUrl).create());
-        }}, finalUrl);
+        LinkedHashMap<Integer, SealConfig> chosenById = new LinkedHashMap<>();
+        Arrays.asList(maSeal, reportSeal, seamSeal).stream()
+                .filter(Objects::nonNull)
+                .forEach(seal -> chosenById.put(seal.getId(), seal));
+        List<SealConfig> chosenSeals = new ArrayList<>(chosenById.values());
+        if (chosenSeals.isEmpty()) {
+            throw new ErrorException("璇疯嚦灏戦�夋嫨涓�绉嶆姤鍛婂嵃绔�");
+        }
+
+        insReport.setSealIds(chosenSeals.stream().map(s -> String.valueOf(s.getId())).collect(Collectors.joining(",")));
+        insReport.setSealNames(chosenSeals.stream().map(SealConfig::getName).collect(Collectors.joining(",")));
+        insReport.setMaSealId(maSeal == null ? null : maSeal.getId());
+        insReport.setMaSealName(maSeal == null ? null : maSeal.getName());
+        insReport.setReportSealId(reportSeal == null ? null : reportSeal.getId());
+        insReport.setReportSealName(reportSeal == null ? null : reportSeal.getName());
+        insReport.setSeamSealId(seamSeal == null ? null : seamSeal.getId());
+        insReport.setSeamSealName(seamSeal == null ? null : seamSeal.getName());
+        String primaryReportUrl = getPrimaryReportUrl(insReport);
+        String finalUrl = primaryReportUrl.replace("/word", wordUrl);
+
+        Map<String, Object> ratifyMarks = new HashMap<>();
+        ratifyMarks.put("ratifyUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
+        ratifyMarks.put("ratifyDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
+        if (reportSeal != null) {
+            ratifyMarks.put("seal1", createSealPicture(reportSeal.getAddress()));
+            ratifyMarks.put("seal2", createSealPicture(reportSeal.getAddress()));
+        }
+        writeApprovalMarksToReportFiles(insReport, ratifyMarks);
+
+        // 鍗扮珷蹇呴』浣跨敤娴姩瀹氫綅锛屽惁鍒欒鍐呭浘鐗囦細鎾戦珮娈佃惤/琛ㄦ牸骞舵敼鍙樺師鎶ュ憡鍒嗛〉銆�
+        for (String reportUrl : getApprovalReportUrls(insReport)) {
+            try {
+                ReportSealLayoutUtil.apply(
+                        reportUrl.replace("/word", wordUrl),
+                        reportSeal == null ? null : Paths.get(imgUrl, reportSeal.getAddress()).toString(),
+                        maSeal == null ? null : Paths.get(imgUrl, maSeal.getAddress()).toString());
+            } catch (Exception e) {
+                log.error("鎶ュ憡鍗扮珷娴姩瀹氫綅澶辫触: {}", reportUrl, e);
+                throw new ErrorException("鎶ュ憡鐩栫珷澶辫触锛岃妫�鏌ュ嵃绔犲浘鐗囧拰鎶ュ憡鏂囦欢");
+            }
+        }
 
         // 淇敼涓存椂pdf
-        insReport.setTempUrlPdf((StrUtil.isBlank(urlS) ? url : urlS).replace(".docx", ".pdf"));
+        insReport.setTempUrlPdf(primaryReportUrl.replace(".docx", ".pdf"));
 
         InsOrder insOrder = new InsOrder();
         insOrder.setId(insOrderId);
         insOrder.setState(4);
         insOrderMapper.updateById(insOrder);
 
-        wordToPdf(finalUrl, sealUrl, isRawMater && order.getOrderType().equals(InsOrderTypeConstants.ENTER_THE_FACTORY));
+        for (String reportUrl : getApprovalReportUrls(insReport)) {
+            wordToPdf(reportUrl.replace("/word", wordUrl),
+                    null,
+                    seamSeal == null ? null : seamSeal.getAddress(),
+                    isRawMater && order.getOrderType().equals(InsOrderTypeConstants.ENTER_THE_FACTORY));
+        }
 
         // 鍒ゆ柇鏄惁涓哄師鏉愭枡
         if (isRawMater) {
@@ -521,15 +580,132 @@
         return insReportMapper.updateById(insReport);
     }
 
+    /**
+     * 瑙f瀽鎵瑰噯鏃堕�夋嫨鐨勫嵃绔狅紙閫楀彿鍒嗛殧鐨勫嵃绔爄d锛夈��
+     * 鏈紶鎴栧叏閮ㄦ棤鏁堟椂鍥為��鍒扮涓�涓惎鐢ㄥ嵃绔狅紙榛樿鈥�1鍙风珷鈥濓級銆�
+     */
+    private List<SealConfig> resolveSeals(String sealIds) {
+        List<SealConfig> chosen = new ArrayList<>();
+        if (StringUtils.isNotBlank(sealIds)) {
+            List<Integer> ids = new ArrayList<>();
+            for (String s : sealIds.split(",")) {
+                if (StringUtils.isNotBlank(s)) {
+                    ids.add(Integer.valueOf(s.trim()));
+                }
+            }
+            if (!ids.isEmpty()) {
+                Map<Integer, SealConfig> byId = sealConfigMapper.selectBatchIds(ids).stream()
+                        .collect(Collectors.toMap(SealConfig::getId, x -> x));
+                for (Integer sid : ids) {
+                    SealConfig seal = byId.get(sid);
+                    if (seal != null && Objects.equals(seal.getStatus(), 1)
+                            && StringUtils.isNotBlank(seal.getAddress())) {
+                        chosen.add(seal);
+                    }
+                }
+            }
+        }
+        if (chosen.isEmpty()) {
+            List<SealConfig> enabled = sealConfigMapper.selectList(Wrappers.<SealConfig>lambdaQuery()
+                    .eq(SealConfig::getStatus, 1).orderByAsc(SealConfig::getCode));
+            if (!enabled.isEmpty()) {
+                chosen.add(enabled.get(0));
+            }
+        }
+        if (chosen.isEmpty()) {
+            throw new ErrorException("鏈壘鍒板彲鐢ㄥ嵃绔狅紝璇峰厛鍦ㄥ嵃绔犵鐞嗕腑缁存姢骞跺惎鐢ㄥ嵃绔�");
+        }
+        return chosen;
+    }
+
+    private SealConfig resolveSeal(Integer sealId) {
+        if (sealId == null) {
+            return null;
+        }
+        SealConfig seal = sealConfigMapper.selectById(sealId);
+        if (seal == null) {
+            throw new ErrorException("鎵�閫夊嵃绔犱笉瀛樺湪锛岃閲嶆柊閫夋嫨");
+        }
+        if (!Objects.equals(seal.getStatus(), 1)) {
+            throw new ErrorException("鍗扮珷鈥�" + seal.getName() + "鈥濆凡鍋滅敤锛岃閲嶆柊閫夋嫨");
+        }
+        if (StringUtils.isBlank(seal.getAddress())) {
+            throw new ErrorException("鍗扮珷鈥�" + seal.getName() + "鈥濇湭涓婁紶鍥剧墖锛岃閲嶆柊閫夋嫨");
+        }
+        return seal;
+    }
+
+    /**
+     * 鎸夊浘鐗囧唴瀹硅瘑鍒嵃绔犳牸寮忥紝鍏煎鍘嗗彶鏁版嵁涓墿灞曞悕琚繚瀛樹负鈥淿png鈥濈瓑闈炴爣鍑嗘枃浠跺悕鐨勬儏鍐点��
+     */
+    private PictureRenderData createSealPicture(String sealUrl) {
+        Path sealPath = Paths.get(imgUrl, sealUrl);
+        if (!Files.isRegularFile(sealPath)) {
+            throw new ErrorException("鍗扮珷鍥剧墖鏂囦欢涓嶅瓨鍦紝璇烽噸鏂颁笂浼犲嵃绔犲浘鐗�");
+        }
+        try {
+            byte[] imageBytes = Files.readAllBytes(sealPath);
+            PictureType pictureType = PictureType.suggestFileType(imageBytes);
+            return Pictures.ofBytes(imageBytes, pictureType).create();
+        } catch (Exception e) {
+            log.error("璇诲彇鍗扮珷鍥剧墖澶辫触: {}", sealPath, e);
+            throw new ErrorException("鍗扮珷鍥剧墖鏃犳硶璇嗗埆锛岃閲嶆柊涓婁紶 jpg 鎴� png 鍥剧墖");
+        }
+    }
+
     @Override
     public int wordInsertUrl(Map<String, Object> map, String url) {
-        XWPFTemplate template = XWPFTemplate.compile(url).render(map);
+        Configure configure = Configure.builder()
+                .setValidErrorHandler(new PreserveReportPicturePlaceholderHandler())
+                .build();
+        XWPFTemplate template = XWPFTemplate.compile(url, configure).render(map);
         try {
             template.writeAndClose(Files.newOutputStream(Paths.get(url)));
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
         return 1;
+    }
+
+    private int wordInsertApprovalMarks(Map<String, Object> map, String url) {
+        Configure configure = Configure.builder()
+                .setValidErrorHandler(new PreserveReportPicturePlaceholderHandler(
+                        new HashSet<>(Arrays.asList("seal1", "seal2"))))
+                .build();
+        XWPFTemplate template = XWPFTemplate.compile(url, configure).render(map);
+        try {
+            template.writeAndClose(Files.newOutputStream(Paths.get(url)));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return 1;
+    }
+
+    private String getPrimaryReportUrl(InsReport report) {
+        String reportUrl = StringUtils.isNotBlank(report.getUrlS()) ? report.getUrlS() : report.getUrl();
+        if (StringUtils.isBlank(reportUrl)) {
+            throw new ErrorException("妫�娴嬫姤鍛婃枃浠朵笉瀛樺湪");
+        }
+        return reportUrl;
+    }
+
+    private List<String> getApprovalReportUrls(InsReport report) {
+        return Arrays.asList(getPrimaryReportUrl(report), report.getInspectionUrl()).stream()
+                .filter(StringUtils::isNotBlank)
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
+    private void writeMarksToReportFiles(InsReport report, Map<String, Object> marks) {
+        for (String reportUrl : getApprovalReportUrls(report)) {
+            wordInsertUrl(marks, reportUrl.replace("/word", wordUrl));
+        }
+    }
+
+    private void writeApprovalMarksToReportFiles(InsReport report, Map<String, Object> marks) {
+        for (String reportUrl : getApprovalReportUrls(report)) {
+            wordInsertApprovalMarks(marks, reportUrl.replace("/word", wordUrl));
+        }
     }
 
 
@@ -569,6 +745,53 @@
             e.printStackTrace();
         }
         return "/word/zip/output.zip";
+    }
+
+    @Override
+    public void download(Integer id, Integer reportType, Integer createOrderUser, HttpServletResponse response) {
+        if (id == null) {
+            throw new ErrorException("鎶ュ憡涓嶈兘涓虹┖");
+        }
+        reportType = reportType == null ? DETECTION_REPORT : reportType;
+        if (!Objects.equals(reportType, DETECTION_REPORT) && !Objects.equals(reportType, INSPECTION_REPORT)) {
+            throw new ErrorException("鎶ュ憡绫诲瀷涓嶆纭�");
+        }
+        InsReport report = insReportMapper.selectDownloadableReport(id, createOrderUser);
+        if (report == null) {
+            throw new ErrorException("鎶ュ憡涓嶅瓨鍦ㄣ�佸皻鏈敓鎴愭垨鏃犳潈涓嬭浇");
+        }
+        String reportUrl = Objects.equals(reportType, INSPECTION_REPORT)
+                ? report.getInspectionUrl() : getPrimaryReportUrl(report);
+        if (StringUtils.isBlank(reportUrl) || !reportUrl.replace('\\', '/').startsWith("/word/")) {
+            throw new ErrorException((Objects.equals(reportType, INSPECTION_REPORT) ? "妫�楠屾姤鍛�" : "妫�娴嬫姤鍛�")
+                    + "鏂囦欢涓嶅瓨鍦紝璇疯仈绯荤鐞嗗憳");
+        }
+        Path root = Paths.get(wordUrl).toAbsolutePath().normalize();
+        Path file = root.resolve(reportUrl.replace('\\', '/').substring("/word/".length())).normalize();
+        if (!file.startsWith(root) || !Files.isRegularFile(file)) {
+            throw new ErrorException("鎶ュ憡鏂囦欢涓嶅瓨鍦紝璇疯仈绯荤鐞嗗憳");
+        }
+        try {
+            String filename = file.getFileName().toString();
+            String encodedName = URLEncoder.encode(filename, "UTF-8").replace("+", "%20");
+            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+            response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedName);
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
+            response.setHeader("download-filename", encodedName);
+            response.setContentLengthLong(Files.size(file));
+            try (InputStream inputStream = Files.newInputStream(file);
+                 OutputStream outputStream = response.getOutputStream()) {
+                byte[] buffer = new byte[8192];
+                int length;
+                while ((length = inputStream.read(buffer)) != -1) {
+                    outputStream.write(buffer, 0, length);
+                }
+                outputStream.flush();
+            }
+        } catch (IOException e) {
+            log.error("涓嬭浇鎶ュ憡澶辫触锛宺eportId={}", id, e);
+            throw new ErrorException("鎶ュ憡涓嬭浇澶辫触");
+        }
     }
 
     //鎵归噺涓婁紶
@@ -686,16 +909,17 @@
     }
 
     @Override
-    public void wordToPdf(String path, String sealUrl, boolean isRawMater) {
+    public void wordToPdf(String path, String maSealUrl, String seamSealUrl, boolean isRawMater) {
         try {
-            wordToPdf(path, path.replace(".docx", ".pdf"), sealUrl, isRawMater);
+            wordToPdf(path, path.replace(".docx", ".pdf"), maSealUrl, seamSealUrl, isRawMater);
         } catch (Exception e) {
             throw new ErrorException("杞崲澶辫触");
         }
     }
 
 
-    public String wordToPdf(String wordPath, String pdfPath, String sealUrl, boolean isRawMater) {
+    public String wordToPdf(String wordPath, String pdfPath, String maSealUrl,
+                            String seamSealUrl, boolean isRawMater) {
         FileOutputStream os = null;
         try {
             //鍑瘉 涓嶇劧鍒囨崲鍚庢湁姘村嵃
@@ -706,27 +930,31 @@
                 log.info("License楠岃瘉涓嶉�氳繃...");
                 return null;
             }
-            //鐢熸垚涓�涓┖鐨凱DF鏂囦欢
-            File file;
-            //鍒ゆ柇鏄惁鏄繘鍘傛姤鍛�
-            if (!isRawMater) {
-                file = new File(pdfPath.replace(".pdf", "-1.pdf"));
-            } else {
-                file = new File(pdfPath.replace(".pdf", ".pdf"));
-            }
+            String effectiveSeamSealUrl = isRawMater ? null : seamSealUrl;
+            boolean addPdfMarks = StringUtils.isNotBlank(maSealUrl)
+                    || StringUtils.isNotBlank(effectiveSeamSealUrl);
+            String sourcePdfPath = addPdfMarks ? pdfPath.replace(".pdf", "-stamp-source.pdf") : pdfPath;
+            File file = new File(sourcePdfPath);
             os = new FileOutputStream(file);
             //瑕佽浆鎹㈢殑word鏂囦欢
             com.aspose.words.Document doc = new com.aspose.words.Document(wordPath);
             doc.save(os, SaveFormat.PDF);
+            os.close();
+            os = null;
 
-            //娣诲姞楠戠紳绔�
-            if (!isRawMater) {
-                stamperCheckMarkPDF(pdfPath.replace(".pdf", "-1.pdf"), pdfPath, imgUrl + "/" + sealUrl);
+            // MA绔犲浐瀹氬湪绗�1椤靛乏涓婅锛涢獞缂濈珷鎸夐〉鍒囩墖鍥哄畾鍦ㄥ彸渚т腑閮ㄣ��
+            if (addPdfMarks) {
+                stamperReportMarksPDF(
+                        sourcePdfPath,
+                        pdfPath,
+                        StringUtils.isBlank(maSealUrl) ? null : Paths.get(imgUrl, maSealUrl).toString(),
+                        StringUtils.isBlank(effectiveSeamSealUrl)
+                                ? null : Paths.get(imgUrl, effectiveSeamSealUrl).toString());
             }
-
-
+            return new File(pdfPath).getName();
         } catch (Exception e) {
-            e.printStackTrace();
+            log.error("鐢熸垚鐩栫珷PDF澶辫触: {}", wordPath, e);
+            throw new ErrorException("鎶ュ憡杞琍DF鎴栫洊绔犲け璐�");
         } finally {
             if (os != null) {
                 try {
@@ -736,7 +964,6 @@
                 }
             }
         }
-        return null;
     }
 
     /**
@@ -761,7 +988,8 @@
                 subImg = img.getSubimage(i * sw, 0, sw, h);
             }
             ByteArrayOutputStream out = new ByteArrayOutputStream();
-            ImageIO.write(subImg, Path.substring(Path.lastIndexOf('.') + 1), out);
+            // 缁熶竴缂栫爜涓� PNG锛屽吋瀹瑰巻鍙测�淿png鈥濈瓑娌℃湁鏍囧噯鎵╁睍鍚嶇殑鍥剧墖鏂囦欢銆�
+            ImageIO.write(subImg, "png", out);
             nImage[i] = com.itextpdf.text.Image.getInstance(out.toByteArray());
 
         }
@@ -769,33 +997,46 @@
     }
 
     /**
-     * 鐩栭獞缂濈珷
+     * 鎸夊弬鑰冩姤鍛婄洊 PDF 鏍囧織绔狅細MA绔犱綅浜庣1椤靛乏涓婅锛岄獞缂濈珷浣嶄簬姣忛〉鍙充晶涓儴銆�
      *
      * @param infilePath  鍘烶DF璺緞
      * @param outFilePath 杈撳嚭PDF璺緞
      */
-    public static void stamperCheckMarkPDF(String infilePath, String outFilePath, String picPath) throws IOException, DocumentException {
+    public static void stamperReportMarksPDF(String infilePath, String outFilePath,
+                                             String maPicPath, String seamPicPath)
+            throws IOException, DocumentException {
         PdfReader reader = new PdfReader(infilePath);//閫夋嫨闇�瑕佸嵃绔犵殑pdf
         PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//鍔犲畬鍗扮珷鍚庣殑pdf
 
-
-        com.itextpdf.text.Rectangle pageSize = reader.getPageSize(1);//鑾峰緱绗竴椤�
-        float height = pageSize.getHeight();
-        float width = pageSize.getWidth();
-
         int nums = reader.getNumberOfPages();
-        com.itextpdf.text.Image[] nImage = slicingImages(picPath, nums);//鐢熸垚楠戠紳绔犲垏鍓插浘鐗�
+        boolean hasMaSeal = maPicPath != null && !maPicPath.trim().isEmpty();
+        boolean hasSeamSeal = seamPicPath != null && !seamPicPath.trim().isEmpty();
+        com.itextpdf.text.Image[] seamImages = hasSeamSeal ? slicingImages(seamPicPath, nums) : null;
 
         for (int n = 1; n <= nums; n++) {
+            com.itextpdf.text.Rectangle pageSize = reader.getPageSize(n);
+            float height = pageSize.getHeight();
+            float width = pageSize.getWidth();
             PdfContentByte over = stamp.getOverContent(n);//璁剧疆鍦ㄧ鍑犻〉鎵撳嵃鍗扮珷
-            com.itextpdf.text.Image img = nImage[n - 1];//閫夋嫨鍥剧墖
-            float newHeight = 100f;
-            float newWidth = img.getWidth() / (img.getHeight() / 100);
-            img.scaleAbsolute(newWidth, newHeight);//鎺у埗鍥剧墖澶у皬
-            img.setAbsolutePosition(width - newWidth, height / 2 - newHeight / 2);//鎺у埗鍥剧墖浣嶇疆
-            over.addImage(img);
+
+            if (n == 1 && hasMaSeal) {
+                com.itextpdf.text.Image maImage = com.itextpdf.text.Image.getInstance(maPicPath);
+                maImage.scaleToFit(100f, 90f);
+                maImage.setAbsolutePosition(30f, height - maImage.getScaledHeight() - 30f);
+                over.addImage(maImage);
+            }
+
+            if (hasSeamSeal) {
+                com.itextpdf.text.Image seamImage = seamImages[n - 1];
+                float newHeight = 100f;
+                float newWidth = seamImage.getWidth() / (seamImage.getHeight() / newHeight);
+                seamImage.scaleAbsolute(newWidth, newHeight);
+                seamImage.setAbsolutePosition(width - newWidth, height / 2 - newHeight / 2);
+                over.addImage(seamImage);
+            }
         }
         stamp.close();
+        reader.close();
     }
 
     @Override
@@ -814,7 +1055,8 @@
         // 鍒ゆ柇鏄惁鏈変笉鍚堟牸
         Long unqualifiedCount = getUnqualifiedCount(insOrder);
 
-        if (count.equals(0L) && unqualifiedCount.equals(0L) && one.getIsFinish().equals(0) && one.getIsSource().equals(1) && registerInsResults) {
+        if (count.equals(0L) && unqualifiedCount.equals(0L) && one.getIsFinish().equals(0)
+                && one.getIsSource().equals(1) && Boolean.TRUE.equals(registerInsResults)) {
             // 鍘熸潗鏂欑Щ搴�
             //濡傛灉鏄媶鍒嗙殑璁㈠崟锛屽垯鎶婃媶鍒嗙殑鎵�鏈夋壒娆¢兘绉诲簱
             if(one.getIsSplitOrder()==1 && !hasExemption){
@@ -928,20 +1170,22 @@
     @Transactional(rollbackFor = Exception.class)
     public boolean sendBackTask(Integer id) {
         InsReport report = insReportMapper.selectById(id);
-        // 鏍规嵁璁㈠崟鏌ヨ璇曢獙瀹�
-        String laboratory = insOrderMapper.selectLaboratoryByOrderId(report.getInsOrderId());
+        if (report == null || report.getInsOrderId() == null) {
+            throw new ErrorException("鎶ュ憡涓嶅瓨鍦ㄦ垨鏈叧鑱旀楠屽崟");
+        }
 
-        // 淇敼璁㈠崟鐘舵��
+        // 鎶ュ憡鐢辫鍗曚笅鍚勮瘯楠屽鍏卞悓褰㈡垚锛涢��鍥炴椂鍏ㄩ儴鎭㈠涓哄緟澶嶆牳锛岄伩鍏嶅彧闅忔満閫�鍥炰竴涓瘯楠屽銆�
         insOrderStateMapper.update(null, Wrappers.<InsOrderState>lambdaUpdate()
                 .eq(InsOrderState::getInsOrderId, report.getInsOrderId())
-                .eq(InsOrderState::getLaboratory, laboratory)
                 .set(InsOrderState::getInsState, 4));
 
-        Integer insSampleId = insSampleUserMapper.selectOne(Wrappers.<InsSampleUser>lambdaQuery()
+        InsSampleUser sampleUser = insSampleUserMapper.selectOne(Wrappers.<InsSampleUser>lambdaQuery()
                 .eq(InsSampleUser::getInsSampleId, report.getInsOrderId())
                 .orderByDesc(InsSampleUser::getId)
-                .last("limit 1")).getId();
-        insSampleUserMapper.deleteById(insSampleId);
+                .last("limit 1"));
+        if (sampleUser != null) {
+            insSampleUserMapper.deleteById(sampleUser.getId());
+        }
 
         // 淇敼鎶ュ憡琛屼负鏈樉绀�
         insReportMapper.update(null, Wrappers.<InsReport>lambdaUpdate()

--
Gitblit v1.9.3