From 3fdea1ab6ab545de0a25573318ecd838de3be576 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期四, 17 九月 2026 15:54:13 +0800
Subject: [PATCH] feat: 1.检验任务查询优化 2.模板时间和地点保存

---
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java | 2314 +++++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 1,763 insertions(+), 551 deletions(-)

diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
index 8daa256..a31cca9 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
@@ -2,6 +2,7 @@
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
@@ -36,6 +37,7 @@
 import com.ruoyi.common.core.domain.entity.Custom;
 import com.ruoyi.common.core.domain.entity.InformationNotification;
 import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.common.enums.OrderType;
 import com.ruoyi.common.utils.*;
 import com.ruoyi.framework.exception.ErrorException;
 import com.ruoyi.inspect.dto.*;
@@ -43,15 +45,13 @@
 import com.ruoyi.inspect.pojo.*;
 import com.ruoyi.inspect.service.*;
 import com.ruoyi.inspect.util.HackLoopTableRenderPolicy;
+import com.ruoyi.inspect.util.PreserveReportPicturePlaceholderHandler;
 import com.ruoyi.inspect.vo.InsOrderPlanTaskSwitchVo;
 import com.ruoyi.inspect.vo.InsOrderPlanVO;
+import com.ruoyi.inspect.vo.InsSampleUserVO;
 import com.ruoyi.performance.mapper.AuxiliaryOutputWorkingHoursMapper;
-import com.ruoyi.performance.mapper.PerformanceShiftMapper;
-import com.ruoyi.performance.mapper.ShiftTimeMapper;
 import com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours;
-import com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHoursTemporary;
 import com.ruoyi.performance.service.AuxiliaryOutputWorkingHoursService;
-import com.ruoyi.performance.service.AuxiliaryOutputWorkingHoursTemporaryService;
 import com.ruoyi.system.mapper.CustomMapper;
 import com.ruoyi.system.mapper.UserMapper;
 import com.ruoyi.system.service.ISysDictTypeService;
@@ -72,10 +72,9 @@
 import java.math.RoundingMode;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.text.DecimalFormat;
 import java.text.SimpleDateFormat;
-import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -83,12 +82,17 @@
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 妫�楠屼换鍔�-涓氬姟瀹炵幇灞�
  */
 @Service
 public class InsOrderPlanServiceImpl extends ServiceImpl<InsOrderMapper, InsOrder> implements InsOrderPlanService {
+
+    private static final int DETECTION_REPORT = 0;
+    private static final int INSPECTION_REPORT = 1;
+    private static final String DIRECT_TEMPLATE_LABORATORY = "鏂拌仛";
 
     @Resource
     private InsSampleMapper insSampleMapper;
@@ -116,8 +120,6 @@
     @Resource
     private AuxiliaryOutputWorkingHoursService auxiliaryOutputWorkingHoursService;
     @Resource
-    private AuxiliaryOutputWorkingHoursTemporaryService auxiliaryOutputWorkingHoursTemporaryService;
-    @Resource
     private AuxiliaryOutputWorkingHoursMapper auxiliaryOutputWorkingHoursMapper;
     @Resource
     private InformationNotificationService informationNotificationService;
@@ -131,6 +133,8 @@
     private InsOrderFileMapper insOrderFileMapper;
     @Resource
     private IfsInventoryQuantityMapper ifsInventoryQuantityMapper;
+    @Resource
+    private IfsPartPropsRecordMapper ifsPartPropsRecordMapper;
     @Resource
     private InsReportService insReportService;
     @Resource
@@ -153,6 +157,8 @@
     @Resource
     private InsOrderDeviceRecordMapper insOrderDeviceRecordMapper;
     @Resource
+    private InsOrderTemplateDeviceMapper insOrderTemplateDeviceMapper;
+    @Resource
     private InsOrderDeviceRecordService insOrderDeviceRecordService;
     @Resource
     private ISysDictTypeService iSysDictTypeService;
@@ -168,9 +174,7 @@
     public IPage<InsOrderPlanVO> selectInsOrderPlanList(Page page, InsOrderPlanDTO insOrderPlanDTO) {
         // todo: 浠呯湅鑷繁鎴栬�呭疄楠屽
         //鑾峰彇褰撳墠浜烘墍灞炲疄楠屽id
-
         String laboratory = null;
-
         String userName = null;
         Integer userId = null;
         if (ObjectUtil.isNotEmpty(insOrderPlanDTO.getUserId())) {
@@ -222,14 +226,8 @@
 
     @Override
     public Map<String, Object> doInsOrder(Integer id, String laboratory) {
-        InsOrder insOrder = new InsOrder();
-        insOrder.setId(id);
+        ensureDirectTemplateOrderState(id);
         InsOrder order = insOrderMapper.selectById(id);
-        if (BeanUtil.isEmpty(order.getInsTime())) {
-            insOrder.setInsTime(LocalDateTime.now());
-            insOrderMapper.updateById(insOrder);
-            insOrderStateMapper.update(null, Wrappers.<InsOrderState>lambdaUpdate().eq(InsOrderState::getInsOrderId, id).eq(InsOrderState::getLaboratory, laboratory).set(InsOrderState::getInsTime, LocalDateTime.now()).set(InsOrderState::getInsState, 1));
-        }
         Map<String, Object> map = insOrderService.getInsOrderAndSample(id, laboratory);
         List<SampleProductDto> list = JSON.parseArray(JSON.toJSONString(map.get("sampleProduct")), SampleProductDto.class);
         map.put("sampleProduct", list);
@@ -259,55 +257,119 @@
         List<InsProduct> insProducts = new ArrayList<>();
         switch (dto.getType()) {
             case 0:
-                insProducts = insSampleMapper.getInsProduct1(dto.getId(), dto.getLaboratory(), dto.getCableTag(), dto.getRepetitionTag(), null);
-                //鏍峰搧
-                break;
             case 4:
-                //鐢电紗閰嶇疆
-                insProducts = insSampleMapper.getInsProduct1(dto.getId(), dto.getLaboratory(), dto.getCableTag(), dto.getRepetitionTag(), null);
+                //濮旀墭
+                insProducts = insSampleMapper.getInsProduct1(dto.getId(), dto.getLaboratory(), dto.getCableTag(), dto.getRepetitionTag());
                 break;
             case 5:
                 //鍘熸潗鏂欎笅鍗�
-                insProducts = insSampleMapper.getInsProduct6(dto.getId(), dto.getLaboratory(), dto.getRawMaterialTag(), null);
+                insProducts = insSampleMapper.getInsProduct6(dto.getId(), dto.getLaboratory(), dto.getRawMaterialTag());
                 break;
-        }
-        if (BeanUtil.isEmpty(insProducts)) {
-            return null;
         }
         // 鏌ヨ璁㈠崟Id
         InsOrder order = insOrderMapper.selectFirstSubmit(dto.getId());
-        getTemplateThing(order, insProducts);
+        if (order == null) {
+            return BeanUtil.isEmpty(insProducts) ? null : insProducts;
+        }
+        insProducts = mergeDirectTemplateSnapshots(order, dto.getId(), dto.getLaboratory(), insProducts);
+        if (BeanUtil.isEmpty(insProducts)) {
+            return null;
+        }
+        getTemplateThing(order, insProducts, dto.getLaboratory());
         return insProducts;
     }
 
-    @Override
-    public List<String> checkSubmitPlan(Integer orderId, String laboratory) {
-        List<String> collect = new ArrayList<>();
-        List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery().eq(InsSample::getInsOrderId, orderId).select(InsSample::getId));
-        List<Integer> ids = insSamples.stream().map(a -> a.getId()).collect(Collectors.toList());
-        List<InsProduct> insProducts = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
-                .in(InsProduct::getInsSampleId, ids)
-                .eq(InsProduct::getSonLaboratory, laboratory)
-                .eq(InsProduct::getState, 1)
-                .eq(InsProduct::getInsResult, 0));
-
-        // 杩囨护鍒ゆ柇鏄湁澶嶆祴鐨勫�兼槸鍚堟牸鐨�
-        List<InsProduct> productList = insProducts.stream().filter(insProduct -> {
-            // 鏌ヨ涓嶅悎鏍煎娴�
-            Long count = insUnqualifiedRetestProductMapper.selectCount(Wrappers.<InsUnqualifiedRetestProduct>lambdaQuery()
-                    .eq(InsUnqualifiedRetestProduct::getInsProductId, insProduct.getId())
-                    .ne(InsUnqualifiedRetestProduct::getInsResult, 0));
-            if (count != 2) {
-                return true;
-            }
-            return false;
-        }).collect(Collectors.toList());
-        if (productList.size() > 0) {
-            collect = productList.stream().map(insProduct -> {
-                return insProduct.getInspectionItem() + "-" + insProduct.getInspectionItemSubclass();
-            }).collect(Collectors.toList());
+    /**
+     * 鐩寸粦妯℃澘璁㈠崟鐨勯〉绛炬潵婧愭槸璁㈠崟妯℃澘蹇収锛岃�屼笉鏄凡鐢熸垚鐨勬楠岄」銆�
+     *
+     * 浠嶄繚鐣欐瘡涓ā鏉夸笅宸叉湁鐨勬楠岄」璁板綍锛涘鏋滄煇涓ā鏉挎病鏈夆�滄楠岄」鈥濇爣璁帮紝琛ヤ竴鏉′粎鐢ㄤ簬
+     * 鎵胯浇妯℃澘鍐呭鐨勮繑鍥炲璞★紝浣垮墠绔篃鑳藉睍绀恒�佸~鍐欒妯℃澘銆�
+     */
+    private List<InsProduct> mergeDirectTemplateSnapshots(InsOrder order, Integer sampleId,
+                                                           String laboratory, List<InsProduct> products) {
+        List<InsProduct> source = products == null ? new ArrayList<>() : products;
+        List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, order.getId())
+                        .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId));
+        if (snapshots.isEmpty()) {
+            return source;
         }
-        return collect;
+        InsSample sample = insSampleMapper.selectById(sampleId);
+        boolean directTemplateOrder = source.stream()
+                .anyMatch(product -> product.getTemplateRowIndex() != null)
+                || isDirectTemplateSample(order, sample);
+        if (!directTemplateOrder) {
+            return source;
+        }
+
+        Map<Integer, List<InsProduct>> productsByTemplate = source.stream()
+                .filter(product -> product.getTemplateId() != null)
+                .collect(Collectors.groupingBy(InsProduct::getTemplateId, LinkedHashMap::new, Collectors.toList()));
+        List<InsProduct> result = new ArrayList<>();
+        for (InsOrderStandardTemplate snapshot : snapshots) {
+            List<InsProduct> templateProducts = productsByTemplate.remove(snapshot.getTemplateId());
+            if (CollectionUtils.isNotEmpty(templateProducts)) {
+                templateProducts.forEach(product -> product.setTemplateSort(snapshot.getSort()));
+                result.addAll(templateProducts);
+                continue;
+            }
+            InsProduct templateCarrier = new InsProduct();
+            templateCarrier.setInsSampleId(sampleId);
+            templateCarrier.setTemplateId(snapshot.getTemplateId());
+            templateCarrier.setSonLaboratory(laboratory);
+            templateCarrier.setState(1);
+            templateCarrier.setSort(snapshot.getSort());
+            templateCarrier.setTemplateSort(snapshot.getSort());
+            result.add(templateCarrier);
+        }
+        // 鍏煎鍘嗗彶寮傚父鏁版嵁锛氳鍗曞揩鐓т互澶栫殑妫�楠岄」浠嶇劧杩斿洖锛屼絾鏀惧湪蹇収椤电涔嬪悗銆�
+        for (List<InsProduct> remaining : productsByTemplate.values()) {
+            result.addAll(remaining);
+        }
+        source.stream().filter(product -> product.getTemplateId() == null).forEach(result::add);
+        return result;
+    }
+
+    private boolean isDirectTemplateSample(InsOrder order, InsSample sample) {
+        return sample != null
+                && Objects.equals(sample.getInsOrderId(), order.getId())
+                && sample.getStandardMethodListId() == null
+                && StringUtils.isBlank(sample.getFactory())
+                && StringUtils.isBlank(sample.getSampleType())
+                && StringUtils.isBlank(sample.getModel())
+                && StringUtils.isBlank(order.getFactory())
+                && StringUtils.isBlank(order.getSampleType());
+    }
+
+    @Override
+    public Map<String,Object> checkSubmitPlan(Integer orderId, String laboratory) {
+        Map<String, Object> map = new HashMap<>();
+        List<String> collect = new ArrayList<>();
+        if (isDirectTemplateOrder(orderId)) {
+            List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateService.list(
+                    Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                            .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                            .orderByAsc(InsOrderStandardTemplate::getSort,
+                                    InsOrderStandardTemplate::getId));
+            for (InsOrderStandardTemplate snapshot : snapshots) {
+                String templateName = StringUtils.defaultIfBlank(snapshot.getName(),
+                        "妯℃澘ID " + snapshot.getTemplateId());
+                if (snapshot.getDetectionTime() == null) {
+                    collect.add("璇烽�夋嫨鈥�" + templateName + "鈥濈殑妫�娴嬫椂闂�");
+                }
+                if (StringUtils.isBlank(snapshot.getDetectionPlace())) {
+                    collect.add("璇峰~鍐欌��" + templateName + "鈥濈殑妫�娴嬪湴鐐�");
+                }
+            }
+            map.put("errorMsg", collect);
+            map.put("missingExportItems", getMissingTemplateExportValues(orderId));
+            map.put("unInsOrderCount", 0L);
+            return map;
+        }
+        map.put("errorMsg", collect);
+        map.put("unInsOrderCount", 0L);
+        return map;
     }
 
     @Override
@@ -365,15 +427,16 @@
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void saveInsContext(Map<String, Object> insContext, Integer currentTable, Integer currentSampleId, Integer orderId, String sonLaboratory) {
+    public void saveInsContext(SaveInsContextDto saveInsContextDto) {
+        Map<String, Object> insContext = JSON.parseObject(saveInsContextDto.getParam(), Map.class);
         Integer userId = SecurityUtils.getUserId().intValue();
-        InsSample insSample = insSampleMapper.selectById(currentSampleId);
+        InsSample insSample = insSampleMapper.selectById(saveInsContextDto.getSampleId());
         insContext.forEach((k, v) -> {
             JSONObject jo = JSON.parseObject(JSON.toJSONString(v));
             InsProduct insProduct = new InsProduct();
             insProduct.setId(Integer.parseInt(k));
             InsProduct product = insProductMapper.selectById(insProduct.getId());
-            if (currentTable.equals(product.getTemplateId()) && currentSampleId.equals(product.getInsSampleId())) {
+            if (saveInsContextDto.getCurrentTable().equals(product.getTemplateId()) && saveInsContextDto.getSampleId().equals(product.getInsSampleId())) {
                 List<InsProductResult> oldResults = insProductResultMapper.selectList(Wrappers.<InsProductResult>lambdaQuery()
                         .eq(InsProductResult::getInsProductId, insProduct.getId()));
                 InsProductResult newResult = new InsProductResult();
@@ -503,23 +566,32 @@
                     }
                 }
 
-                //鏌ヨ妫�楠屽崟淇℃伅
                 // 娣诲姞宸ユ椂
+                // 鍒ゆ柇鏄惁鍙槸鍙備笌璁$畻鍊�, 鍙備笌璁$畻鍊煎疄闄呮病鏈夊~鍐�
                 InsProduct finalInsProduct = insProductMapper.selectById(product.getId());
-                threadPoolTaskExecutor.execute(() -> {
-                    InsOrder insOrder = insOrderMapper.selectById(insSample.getInsOrderId());
-                    this.addAuxiliary(userId, finalInsProduct, insOrder);
-                });
+                InsOrder insOrder = insOrderMapper.selectById(insSample.getInsOrderId());
+                if (StringUtils.isNotBlank(newResult.getInsValue()) && !newResult.getInsValue().equals("[]")) {
+                    threadPoolTaskExecutor.execute(() -> {
+                        this.addAuxiliary(userId, finalInsProduct, insOrder);
+                    });
+                } else {
+                    // 鍒ゆ柇鏄惁鏄病鏈夋楠屽�肩殑鍐呭
+                    if (saveInsContextDto.getIsNoTestValue() != null && saveInsContextDto.getIsNoTestValue() == 1) {
+                        threadPoolTaskExecutor.execute(() -> {
+                            this.addAuxiliary(userId, finalInsProduct, insOrder);
+                        });
+                    }
+                }
 
             }
         });
         String sampleIdStr = insContext.keySet().stream().findFirst().orElse(null);
         if (sampleIdStr != null) {
-            int count = insProductMapper.selectInsProductCountByOrderId(orderId);
+            int count = insProductMapper.selectInsProductCountByOrderId(saveInsContextDto.getOrderId());
             if (count == 0) {
                 insOrderStateMapper.update(new InsOrderState(), Wrappers.<InsOrderState>lambdaUpdate()
-                        .eq(InsOrderState::getInsOrderId, orderId)
-                        .eq(InsOrderState::getLaboratory, sonLaboratory)
+                        .eq(InsOrderState::getInsOrderId, saveInsContextDto.getOrderId())
+                        .eq(InsOrderState::getLaboratory, saveInsContextDto.getSonLaboratory())
                         .set(InsOrderState::getInsState, 2));
             }
         }
@@ -530,6 +602,258 @@
             // 娣诲姞璁惧浣跨敤璁板綍
             addDeviceRecord(insSample, userId);
         });
+    }
+
+    /**
+     * 鏂拌仛璁㈠崟鐨勫灞� key 鏄� templateId锛屼笉鏄� ins_product.id锛涘洜姝ゅ崟鐙寜妯℃澘蹇収淇濆瓨銆�
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void saveTemplateContext(SaveTemplateContextDto dto) {
+        if (dto.getOrderId() == null || dto.getSampleId() == null || dto.getTemplateId() == null) {
+            throw new ErrorException("璁㈠崟銆佹牱鍝佸拰妯℃澘涓嶈兘涓虹┖");
+        }
+        InsSample sample = insSampleMapper.selectById(dto.getSampleId());
+        if (sample == null || !Objects.equals(sample.getInsOrderId(), dto.getOrderId())) {
+            throw new ErrorException("鏍峰搧涓嶅睘浜庡綋鍓嶆楠屽崟");
+        }
+        InsOrderStandardTemplate snapshot = insOrderStandardTemplateService.getOne(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, dto.getOrderId())
+                        .eq(InsOrderStandardTemplate::getTemplateId, dto.getTemplateId())
+                        .last("limit 1"));
+        if (snapshot == null) {
+            throw new ErrorException("鏈壘鍒板綋鍓嶈鍗曠殑鍘熷璁板綍妯℃澘蹇収");
+        }
+        ensureDirectTemplateOrderState(dto.getOrderId());
+        List<InsProduct> products = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
+                .eq(InsProduct::getInsSampleId, dto.getSampleId())
+                .eq(InsProduct::getTemplateId, dto.getTemplateId())
+                .isNotNull(InsProduct::getTemplateRowIndex)
+                .eq(InsProduct::getState, 1));
+
+        JSONObject values = JSON.parseObject(JSON.toJSONString(dto.getValues() == null
+                ? Collections.emptyMap() : dto.getValues()));
+        List<String> exportValueCoordinates = getExportValueCoordinates(snapshot.getThing()).values().stream()
+                .flatMap(Collection::stream)
+                .distinct()
+                .collect(Collectors.toList());
+        if (exportValueCoordinates.isEmpty()) {
+            throw new ErrorException("妯℃澘蹇呴』鑷冲皯閰嶇疆涓�涓鍑哄�兼壒娉�");
+        }
+
+        // 瀵煎嚭鍊兼寜妯℃澘閰嶇疆锛屼笉鍐嶈姹傛瘡涓楠岄」鍖哄潡鍒嗗埆閰嶇疆銆備竴涓ā鏉垮彇绗竴涓鍑哄�间綔涓虹粨鏋溿��
+        String exportValueCoordinate = exportValueCoordinates.get(0);
+        JSONObject exportValueCell = values.getJSONObject(exportValueCoordinate);
+        String exportValue = exportValueCell == null || exportValueCell.get("v") == null
+                ? "" : String.valueOf(exportValueCell.get("v"));
+        Integer userId = SecurityUtils.getUserId().intValue();
+        for (InsProduct product : products) {
+            InsProduct update = new InsProduct();
+            update.setId(product.getId());
+            update.setLastValue(exportValue);
+            update.setUpdateUser(userId);
+            insProductMapper.updateById(update);
+            insProductUserMapper.insert(new InsProductUser(null, userId, LocalDateTime.now(), product.getId()));
+        }
+        snapshot.setRecordValues(values.toJSONString());
+        insOrderStandardTemplateService.updateById(snapshot);
+
+        if (hasSavedTemplateValue(values)) {
+            markInspectionStarted(dto.getOrderId(), products);
+        }
+
+        Long unfinished = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
+                .eq(InsProduct::getInsSampleId, dto.getSampleId())
+                .isNotNull(InsProduct::getTemplateRowIndex)
+                .eq(InsProduct::getState, 1)
+                .and(w -> w.isNull(InsProduct::getLastValue).or().eq(InsProduct::getLastValue, "")));
+        sample.setInsState(unfinished == 0 ? 2 : 1);
+        insSampleMapper.updateById(sample);
+    }
+
+    /**
+     * 绗竴娆℃垚鍔熶繚瀛樹换鎰忛潪绌烘ā鏉垮�兼椂锛岃褰曠湡瀹炴楠屽紑濮嬫椂闂村苟灏嗕换鍔′粠寰呮鏀逛负鍦ㄦ銆�
+     */
+    private void markInspectionStarted(Integer orderId, List<InsProduct> products) {
+        LocalDateTime now = LocalDateTime.now();
+        insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
+                .eq(InsOrder::getId, orderId)
+                .isNull(InsOrder::getFirstInspectDate)
+                .set(InsOrder::getFirstInspectDate, now)
+                // 淇濈暀鍘熷瓧娈典緵妫�楠屼换鍔″垪琛ㄤ腑鐨勨�滄楠屽紑濮嬫椂闂粹�濈户缁睍绀恒��
+                .set(InsOrder::getInsTime, now));
+
+        Set<String> laboratories = products.stream()
+                .map(InsProduct::getSonLaboratory)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toSet());
+        if (laboratories.isEmpty() && isDirectTemplateOrder(orderId)) {
+            laboratories.add(DIRECT_TEMPLATE_LABORATORY);
+        }
+        if (!laboratories.isEmpty()) {
+            insOrderStateMapper.update(null, Wrappers.<InsOrderState>lambdaUpdate()
+                    .eq(InsOrderState::getInsOrderId, orderId)
+                    .in(InsOrderState::getLaboratory, laboratories)
+                    .eq(InsOrderState::getInsState, 0)
+                    .set(InsOrderState::getInsTime, now)
+                    .set(InsOrderState::getInsState, 1));
+        }
+    }
+
+    private boolean hasSavedTemplateValue(JSONObject values) {
+        if (values == null || values.isEmpty()) {
+            return false;
+        }
+        for (Object rawCell : values.values()) {
+            JSONObject cell = rawCell instanceof JSONObject
+                    ? (JSONObject) rawCell
+                    : JSON.parseObject(JSON.toJSONString(rawCell));
+            if (cell != null && hasMeaningfulValue(cell.get("v"))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean hasMeaningfulValue(Object value) {
+        if (value == null) {
+            return false;
+        }
+        if (value instanceof CharSequence) {
+            return StringUtils.isNotBlank(value.toString());
+        }
+        if (value instanceof Collection) {
+            return ((Collection<?>) value).stream().anyMatch(this::hasMeaningfulValue);
+        }
+        if (value instanceof Map) {
+            return ((Map<?, ?>) value).values().stream().anyMatch(this::hasMeaningfulValue);
+        }
+        return true;
+    }
+
+    private NavigableMap<Integer, List<String>> getExportValueCoordinates(String compressedThing) {
+        if (StrUtil.isBlank(compressedThing)) {
+            throw new ErrorException("鍘熷璁板綍妯℃澘涓虹┖");
+        }
+        String thing;
+        try {
+            thing = GZipUtil.uncompress(compressedThing);
+        } catch (Exception ignored) {
+            thing = compressedThing;
+        }
+        JSONArray cellData = JSON.parseObject(thing).getJSONArray("data").getJSONObject(0).getJSONArray("celldata");
+        NavigableMap<Integer, List<String>> result = new TreeMap<>();
+        Integer inspectionResultColumn = null;
+        for (Object item : cellData) {
+            JSONObject cell = JSON.parseObject(JSON.toJSONString(item));
+            Integer column = cell.getInteger("c");
+            JSONObject value = cell.getJSONObject("v");
+            String displayValue = value == null ? null : value.getString("v");
+            if (inspectionResultColumn == null && "妫�楠岀粨鏋�".equals(StringUtils.trim(displayValue))) {
+                inspectionResultColumn = column;
+            }
+        }
+        for (Object item : cellData) {
+            JSONObject cell = JSON.parseObject(JSON.toJSONString(item));
+            JSONObject value = cell.getJSONObject("v");
+            JSONObject ps = value == null ? null : value.getJSONObject("ps");
+            if (ps == null || !"瀵煎嚭鍊�".equals(ps.getString("value"))) {
+                continue;
+            }
+            Integer row = cell.getInteger("r");
+            Integer column = cell.getInteger("c");
+            if (row != null && column != null) {
+                // 鈥滃鍑哄�尖�濇爣鍦ㄦ娴嬮」鐩爣棰樺崟鍏冩牸鏃讹紝鐪熸瀵煎嚭鐨勫�兼槸鍚屼竴琛屸�滄楠岀粨鏋溾�濆垪鐨勫崟鍏冩牸銆�
+                String coordinate = row + "-" + column;
+                String resultCoordinate = row + "-" + inspectionResultColumn;
+                if (inspectionResultColumn != null && !Objects.equals(column, inspectionResultColumn)) {
+                    coordinate = resultCoordinate;
+                }
+                result.computeIfAbsent(row, ignored -> new ArrayList<>()).add(coordinate);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 鐩寸粦妯℃澘璁㈠崟鍙牎楠屾ā鏉夸腑鏍囪涓衡�滃鍑哄�尖�濈殑鍗曞厓鏍硷紝涓嶄娇鐢ㄦ楠岄」鐘舵�佹垨 last_value 鍒ゅ畾銆�
+     */
+    private List<String> getMissingTemplateExportValues(Integer orderId) {
+        List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                        .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId));
+        List<String> missing = new ArrayList<>();
+        if (snapshots.isEmpty()) {
+            missing.add("褰撳墠璁㈠崟鏈壘鍒板師濮嬭褰曟ā鏉垮揩鐓�");
+            return missing;
+        }
+        for (InsOrderStandardTemplate snapshot : snapshots) {
+            Integer templateId = snapshot.getTemplateId();
+            List<String> coordinates = getExportValueCoordinates(snapshot.getThing()).values().stream()
+                    .flatMap(Collection::stream)
+                    .distinct()
+                    .collect(Collectors.toList());
+            String templateName = StringUtils.defaultIfBlank(snapshot.getName(), "妯℃澘ID " + templateId);
+            if (coordinates.isEmpty()) {
+                missing.add(templateName + "锛堟湭閰嶇疆瀵煎嚭鍊硷級");
+                continue;
+            }
+
+            JSONObject recordValues = StrUtil.isBlank(snapshot.getRecordValues())
+                    ? new JSONObject() : JSON.parseObject(snapshot.getRecordValues());
+            // 淇濆瓨鏃跺悓鏍峰彧鍙栨ā鏉夸腑鐨勭涓�涓鍑哄�硷紝鎻愪氦鏍¢獙涓庝繚瀛樺彛寰勪繚鎸佷竴鑷淬��
+            String coordinate = coordinates.get(0);
+            JSONObject cell = recordValues.getJSONObject(coordinate);
+            Object value = cell == null ? null : cell.get("v");
+            if (value == null || StringUtils.isBlank(String.valueOf(value))) {
+                missing.add(templateName + "锛�" + coordinate + "锛�");
+            }
+        }
+        return missing;
+    }
+
+    @Override
+    public List<Integer> getOrderDeviceIds(Integer orderId) {
+        return insOrderDeviceRecordMapper.selectList(Wrappers.<InsOrderDeviceRecord>lambdaQuery()
+                        .eq(InsOrderDeviceRecord::getInsOrderId, orderId))
+                .stream().map(InsOrderDeviceRecord::getDeviceId).filter(Objects::nonNull).distinct()
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void saveOrderDevices(SaveOrderDevicesDto dto) {
+        if (dto.getOrderId() == null || insOrderMapper.selectById(dto.getOrderId()) == null) {
+            throw new ErrorException("妫�楠屽崟涓嶅瓨鍦�");
+        }
+        Set<Integer> deviceIds = dto.getDeviceIds() == null ? Collections.emptySet() : dto.getDeviceIds().stream()
+                .filter(Objects::nonNull).collect(Collectors.toSet());
+        List<InsOrderDeviceRecord> oldRecords = insOrderDeviceRecordMapper.selectList(
+                Wrappers.<InsOrderDeviceRecord>lambdaQuery().eq(InsOrderDeviceRecord::getInsOrderId, dto.getOrderId()));
+        Set<Integer> oldIds = oldRecords.stream().map(InsOrderDeviceRecord::getDeviceId).collect(Collectors.toSet());
+        if (!oldIds.isEmpty()) {
+            insOrderDeviceRecordMapper.delete(Wrappers.<InsOrderDeviceRecord>lambdaQuery()
+                    .eq(InsOrderDeviceRecord::getInsOrderId, dto.getOrderId())
+                    .notIn(!deviceIds.isEmpty(), InsOrderDeviceRecord::getDeviceId, deviceIds));
+        }
+        InsOrder order = insOrderMapper.selectById(dto.getOrderId());
+        User user = userMapper.selectById(SecurityUtils.getUserId().intValue());
+        List<InsOrderDeviceRecord> additions = deviceIds.stream().filter(id -> !oldIds.contains(id)).map(id -> {
+            InsOrderDeviceRecord record = new InsOrderDeviceRecord();
+            record.setInsOrderId(dto.getOrderId());
+            record.setDeviceId(id);
+            record.setSampleCode(order.getEntrustCode());
+            record.setUseBefore(1);
+            record.setUseAfter(1);
+            record.setUsePersonId(user.getId());
+            record.setUsePerson(user.getName());
+            return record;
+        }).collect(Collectors.toList());
+        if (!additions.isEmpty()) {
+            insOrderDeviceRecordService.saveBatch(additions);
+        }
     }
 
     private synchronized void addDeviceRecord(InsSample insSample, Integer userId) {
@@ -605,53 +929,55 @@
      * @param order
      * @param insProducts
      */
-    private void getTemplateThing(InsOrder order, List<InsProduct> insProducts) {
+    private void getTemplateThing(InsOrder order, List<InsProduct> insProducts, String laboratory) {
         Set<Integer> set = new HashSet<>();
-        // 妫�楠岄」鍒嗙被+妫�楠岄」+妫�楠屽瓙椤圭殑鎷兼帴
-//        List<String> itemNameList = insProducts.stream().map(insProduct -> {
-//            String itemName = "";
-//            if (StringUtils.isNotBlank(insProduct.getInspectionItemClass())) {
-//                itemName += insProduct.getInspectionItemClass().trim();
-//            }
-//            if (StringUtils.isNotBlank(insProduct.getInspectionItem())) {
-//                itemName += insProduct.getInspectionItem().trim();
-//            }
-//            if (StringUtils.isNotBlank(insProduct.getInspectionItemSubclass())) {
-//                itemName += insProduct.getInspectionItemSubclass().trim();
-//            }
-//            return itemName;
-//        }).collect(Collectors.toList());
-        // 鏌ヨ璁㈠崟鐘舵�佸垽鏂槸鍚︽槸鏌ュ巻鍙叉ā鏉�
-        if (order.getIsFirstSubmit() != null && order.getIsFirstSubmit().equals(1)) {
-            InsOrderState insOrderState = insOrderStateMapper.selectOne(Wrappers.<InsOrderState>lambdaQuery()
-                    .eq(InsOrderState::getInsOrderId, order.getId())
-                    .last("limit 1"));
-            if (insOrderState != null && (!insOrderState.getInsState().equals(3) || !insOrderState.getInsState().equals(5))) {
-                for (InsProduct product : insProducts) {
-                    if (product.getTemplateId() == null) {
-                        product.setTemplate(new ArrayList<>());
+        Map<Integer, String> recordValuesByTemplate = new HashMap<>();
+        for (InsOrderStandardTemplate snapshot : insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, order.getId()))) {
+            // record_values 鍦ㄩ娆″~鍐欏墠鍏佽涓虹┖锛汣ollectors.toMap 涓嶆帴鍙� null value銆�
+            if (snapshot.getTemplateId() != null && snapshot.getRecordValues() != null) {
+                recordValuesByTemplate.putIfAbsent(snapshot.getTemplateId(), snapshot.getRecordValues());
+            }
+        }
+        boolean directTemplateOrder = insProducts.stream()
+                .anyMatch(product -> product.getTemplateRowIndex() != null);
+        Long snapshotCount = insOrderStandardTemplateService.count(Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                .eq(InsOrderStandardTemplate::getInsOrderId, order.getId()));
+        InsOrderState insOrderState = insOrderStateMapper.selectOne(Wrappers.<InsOrderState>lambdaQuery()
+                .eq(InsOrderState::getInsOrderId, order.getId())
+                .eq(StringUtils.isNotBlank(laboratory), InsOrderState::getLaboratory, laboratory)
+                .last("limit 1"));
+        Integer insState = insOrderState == null ? null : insOrderState.getInsState();
+        boolean hasSnapshot = snapshotCount > 0 && (directTemplateOrder
+                || Objects.equals(order.getIsFirstSubmit(), 1));
+        // 寰呮楠屻�佹楠屼腑浣跨敤鍩虹閰嶇疆鐨勬渶鏂版ā鏉匡紱宸叉楠屽強鍚庣画鐘舵�佷娇鐢ㄨ鍗曞揩鐓с��
+        boolean useSnapshot = hasSnapshot && insState != null && insState >= 2;
+        if (useSnapshot) {
+            for (InsProduct product : insProducts) {
+                if (product.getTemplateId() == null) {
+                    product.setTemplate(new ArrayList<>());
+                    continue;
+                }
+                if (set.add(product.getTemplateId())) {
+                    InsOrderStandardTemplate one = insOrderStandardTemplateService.getOne(Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                            .eq(InsOrderStandardTemplate::getTemplateId, product.getTemplateId())
+                            .eq(InsOrderStandardTemplate::getInsOrderId, order.getId()));
+                    if (one == null || StrUtil.isEmpty(one.getThing())) {
+                        // 蹇収涓嶅畬鏁存椂鍏佽鍚庨潰鐨勬渶鏂版ā鏉挎煡璇㈠厹搴曘��
+                        set.remove(product.getTemplateId());
                         continue;
                     }
-                    String thing = null;
-                    if (product.getTemplateId() != null && set.add(product.getTemplateId())) {
-                        // 鏌ヨ鍘嗗彶妯℃澘
-                        InsOrderStandardTemplate one = insOrderStandardTemplateService.getOne(Wrappers.<InsOrderStandardTemplate>lambdaQuery()
-                                .eq(InsOrderStandardTemplate::getTemplateId, product.getTemplateId())
-                                .eq(InsOrderStandardTemplate::getInsOrderId, order.getId()));
-                        thing = one.getThing();
-                        if (StrUtil.isNotEmpty(thing)) {
-                            thing = GZipUtil.uncompress(thing);
-                            JSONObject sheet = JSON.parseObject(thing).getJSONArray("data").getJSONObject(0);
-                            JSONObject config = sheet.getJSONObject("config");
-                            List<JSONObject> cellData = JSON.parseArray(JSON.toJSONString(sheet.get("celldata")), JSONObject.class);
-                            Map<String, Object> style = new HashMap<>();
-                            style.put("rowlen", config.get("rowlen"));
-                            style.put("columnlen", config.get("columnlen"));
-                            product.setTemplate(cellData);
-                            product.setStyle(style);
-                            product.setTemplateName(one.getName());
-                        }
-                    }
+                    String thing = GZipUtil.uncompress(one.getThing());
+                    JSONObject sheet = JSON.parseObject(thing).getJSONArray("data").getJSONObject(0);
+                    JSONObject config = sheet.getJSONObject("config");
+                    List<JSONObject> cellData = JSON.parseArray(JSON.toJSONString(sheet.get("celldata")), JSONObject.class);
+                    Map<String, Object> style = new HashMap<>();
+                    style.put("rowlen", config.get("rowlen"));
+                    style.put("columnlen", config.get("columnlen"));
+                    product.setTemplate(cellData);
+                    product.setStyle(style);
+                    product.setTemplateName(one.getName());
                 }
             }
         }
@@ -675,6 +1001,7 @@
                 product.setStyle(style);
                 product.setTemplateName(standardTemplateService.getStandTempNameById(product.getTemplateId()));
             }
+            product.setRecordValues(recordValuesByTemplate.get(product.getTemplateId()));
         }
     }
 
@@ -764,8 +1091,14 @@
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public int submitPlan(Integer orderId, String laboratory, Integer verifyUser, String entrustCode) {
-        InsOrder order = insOrderMapper.selectById(orderId);
+    public int submitPlan(Integer orderId, String laboratory, Integer verifyUser, String entrustCode, Boolean registerInsResults) {
+        ensureDirectTemplateOrderState(orderId);
+        int reportType = DETECTION_REPORT;
+        InsOrder order = insOrderMapper.selectOne(Wrappers.<InsOrder>lambdaQuery()
+                .eq(InsOrder::getId, orderId)
+                .last("FOR UPDATE"));
+        boolean isInspectionReport = Objects.equals(INSPECTION_REPORT, reportType);
+        registerInsResults = isInspectionReport && Boolean.TRUE.equals(registerInsResults);
         // 1. 鍒ゆ柇鏄惁鏈夐噸澶嶇紪鍙�, 鏈夐噸澶嶇紪鍙峰仛鎻愰啋
         Long codeCount = insOrderMapper.selectCount(Wrappers.<InsOrder>lambdaQuery()
                 .ne(InsOrder::getState, -1)
@@ -776,28 +1109,44 @@
         }
 
         // 2. 鍒ゆ柇璇ヨ鍗曟槸鍚︽槸绗竴娆$敓浜�(鍚庣画鎶ュ憡鐢熸垚鍙彇绗竴娆℃彁浜ゆ椂闂�)
-        if (!(order.getIsFirstSubmit() != null && order.getIsFirstSubmit().equals(1))) {
+        boolean firstSubmit = !Objects.equals(order.getIsFirstSubmit(), 1);
+        if (firstSubmit) {
             insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
                     .eq(InsOrder::getId, orderId)
                     .set(InsOrder::getIsFirstSubmit, 1)
                     .set(InsOrder::getFirstSubmitDate, LocalDateTime.now()));
         }
 
-        // 3. 鍒ゆ柇鏄惁鏈夋湭妫�椤�
+        // 3. 鐩寸粦妯℃澘浠呮牎楠屸�滃鍑哄�尖�濓紱鏅�氳鍗曟部鐢ㄥ師妫�楠岄」鏍¢獙銆�
         List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
                 .eq(InsSample::getInsOrderId, orderId).select(InsSample::getId));
         List<Integer> InsSampleIds = insSamples.stream().map(InsSample::getId).collect(Collectors.toList());
-        List<InsProduct> insProducts = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
-                .in(InsProduct::getInsSampleId, InsSampleIds)
-                .eq(InsProduct::getSonLaboratory, laboratory)
-                .eq(InsProduct::getState, 1)
-                .and(wrapper -> wrapper
-                        .isNull(InsProduct::getInsResult)
-                        .or()
-                        .eq(InsProduct::getInsResult, 2)
-                )
-                .ne(InsProduct::getIsBinding, 1));
-        insProducts.addAll(insProductMapper.selectFiberInsProduct(InsSampleIds, laboratory));
+        boolean directTemplateOrder = isDirectTemplateOrder(orderId);
+        List<InsProduct> insProducts;
+        if (directTemplateOrder) {
+            List<String> missingExportValues = getMissingTemplateExportValues(orderId);
+            if (!missingExportValues.isEmpty()) {
+                throw new ErrorException("妯℃澘涓殑瀵煎嚭鍊间笉鑳戒负绌猴細\n" + String.join("\n", missingExportValues));
+            }
+            insProducts = Collections.emptyList();
+        } else {
+            insProducts = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
+                    .in(InsProduct::getInsSampleId, InsSampleIds)
+                    .eq(InsProduct::getSonLaboratory, laboratory)
+                    .eq(InsProduct::getState, 1)
+                    .and(wrapper -> {
+                        if (Objects.equals(reportType, DETECTION_REPORT)) {
+                            wrapper.isNull(InsProduct::getLastValue).or().eq(InsProduct::getLastValue, "");
+                        } else {
+                            wrapper.isNull(InsProduct::getInsResult).or().eq(InsProduct::getInsResult, 2);
+                        }
+                    })
+                    .ne(InsProduct::getIsBinding, 1));
+        }
+        if (!directTemplateOrder && Objects.equals(reportType, INSPECTION_REPORT)) {
+            List<InsProduct> insProducts1 = insProductMapper.selectFiberInsProduct(InsSampleIds, laboratory);
+            insProducts.addAll(insProducts1);
+        }
         if (insProducts.size() > 0) {
             String str = "";
             int count = 0;
@@ -860,42 +1209,24 @@
             }
         });
 
-        // 8.鎻愪氦鐢熸垚鎶ュ憡
-        this.generateReport(orderId);
+        // 8.棣栨鎻愪氦鏃跺皢鏈妫�楠屼娇鐢ㄧ殑鏈�鏂版ā鏉垮喕缁撲负璁㈠崟蹇収銆�
+        Long snapshotCount = insOrderStandardTemplateService.count(Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                .eq(InsOrderStandardTemplate::getInsOrderId, orderId));
+        if (firstSubmit || snapshotCount == 0) {
+            this.templateCopy(orderId, InsSampleIds);
+        }
 
-        // 9.娣诲姞涓存椂pdf鐢熸垚鍦板潃
-        InsReport report = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
-                .eq(InsReport::getInsOrderId, orderId));
-        String tempUrlPdf = this.wordToPdfTemp(report.getUrl().replace("/word", wordUrl));
-        report.setTempUrlPdf("/word/" + tempUrlPdf);
-        insReportMapper.updateById(report);
+        // 9. 妫�娴嬫姤鍛婁粎鍦ㄥ叏閮ㄥ鏍搁�氳繃鏃剁敓鎴愶紝鎻愪氦澶嶆牳闃舵涓嶇敓鎴愭姤鍛娿��
 
-        // 10.鍘熷璁板綍妯℃澘澶嶅埗(娣诲姞澶囦唤, 閬垮厤淇敼鍘熷妯℃澘褰卞搷鍒板凡缁忓畬鎴愮殑鍗曞瓙)
-        this.templateCopy(orderId, InsSampleIds);
-
-        // 11.鎴愬搧鎶芥牱娣诲姞鍚堟牸鐘舵��
+        // 10.鎴愬搧鎶芥牱娣诲姞鍚堟牸鐘舵��
         // 鍒ゆ柇鏄惁鏈夋娊鏍蜂俊鎭�
-        if (order.getQuarterItemId() != null) {
+        if (isInspectionReport && order.getQuarterItemId() != null) {
             // 鍒ゆ柇鏄惁鏈変笉鍚堟牸
             this.addProductSpotCheck(insSamples, order);
         }
 
-        // 12.娣诲姞宸ユ椂
-//        // 鍒犻櫎鍘熸湰璁㈠崟宸ユ椂
-//        auxiliaryOutputWorkingHoursService.remove(Wrappers.<AuxiliaryOutputWorkingHours>lambdaQuery()
-//                .eq(AuxiliaryOutputWorkingHours::getOrderId, orderId));
-//        // 鏌ヨ宸ユ椂鏆傚瓨
-//        List<AuxiliaryOutputWorkingHoursTemporary> hoursTemporaries = auxiliaryOutputWorkingHoursTemporaryService.list(Wrappers.<AuxiliaryOutputWorkingHoursTemporary>lambdaQuery()
-//                .eq(AuxiliaryOutputWorkingHoursTemporary::getOrderId, orderId));
-//        List<AuxiliaryOutputWorkingHours> outputWorkingHours = hoursTemporaries.stream().map(hoursTemporary -> {
-//            AuxiliaryOutputWorkingHours workingHours = new AuxiliaryOutputWorkingHours();
-//            BeanUtil.copyProperties(hoursTemporary, workingHours);
-//            workingHours.setId(null);
-//            return workingHours;
-//        }).collect(Collectors.toList());
-//        auxiliaryOutputWorkingHoursService.saveBatch(outputWorkingHours);
 
-        // 13.娣诲姞璁㈠崟璐圭敤缁熻淇℃伅
+        // 11.娣诲姞璁㈠崟璐圭敤缁熻淇℃伅
         List<InsProduct> productList = insProductMapper.selectProductByOrderId(orderId);
         // 鍒犻櫎鍘熸湰璐圭敤淇℃伅
         insOrderRatesService.remove(Wrappers.<InsOrderRates>lambdaQuery()
@@ -918,7 +1249,7 @@
         insOrderRatesService.saveBatch(orderRatesList);
 
 
-        // 14.鍙戦�佷紒涓氬井淇¢�氱煡
+        // 12.鍙戦�佷紒涓氬井淇¢�氱煡
         // 鏌ヨ鍘熸潗鏂�
         IfsInventoryQuantity ifsInventoryQuantity = ifsInventoryQuantityMapper.selectById(order.getIfsInventoryId());
         // 鏌ヨ鏍峰搧淇℃伅
@@ -937,28 +1268,28 @@
             }
             //鍙戦�佷紒涓氬井淇℃秷鎭�氱煡  鎻愪氦澶嶆牳
             try {
-                WxCpUtils.inform(sendUserAccount, message, null);
+//                WxCpUtils.inform(sendUserAccount, message, null);
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
         });
 
-        // 15.ifs绉诲簱(鍘熸潗鏂欓渶瑕佽繘琛岀Щ搴撴搷浣�) --> 鏈�鍚庢墽琛�,鍥犱负澶辫触鏃犳硶鍥炴粴
-        if (ifsInventoryQuantity != null) {
+        // 13.ifs绉诲簱(鍘熸潗鏂欓渶瑕佽繘琛岀Щ搴撴搷浣�) --> 鏈�鍚庢墽琛�,鍥犱负澶辫触鏃犳硶鍥炴粴
+        if (ifsInventoryQuantity != null && isInspectionReport) {
             // 鐧昏妫�楠岀粨鏋�
             // 鍒ゆ柇鏄惁鏈変笉鍚堟牸, 鏈変笉鍚堟牸涓嶈兘绉诲簱
             // todo: ifs绉诲簱
-            insReportService.isRawMaterial(order);
+            insReportService.isRawMaterial(order,registerInsResults,false);
 
-            // 16 鍒ゆ柇褰撳墠鏍峰搧鏄惁涓哄師鏉愭枡, 鍘熸潗鏂欓渶瑕佽繘琛屾暟鎹垎鏋�, 鍒ゆ柇涔嬪墠10鏉℃暟鎹悓涓�涓緵搴斿晢, 鍚屼竴涓楠岄」鐨勫亸宸槸鍚﹁秴杩�10%
+            // 14 鍒ゆ柇褰撳墠鏍峰搧鏄惁涓哄師鏉愭枡, 鍘熸潗鏂欓渶瑕佽繘琛屾暟鎹垎鏋�, 鍒ゆ柇涔嬪墠10鏉℃暟鎹悓涓�涓緵搴斿晢, 鍚屼竴涓楠岄」鐨勫亸宸槸鍚﹁秴杩�10%
             // 鏌ヨifs淇℃伅鑾峰彇鑾峰彇鍓�10涓緵搴斿晢涓�鏍风殑, 妫�楠岄」涓�鏍蜂俊鎭�
             threadPoolTaskExecutor.execute(() -> {
                 // 娣诲姞鍒嗘瀽鏁版嵁
-                addAnalysis(productList, ifsInventoryQuantity, order);
+                addAnalysis(productList, ifsInventoryQuantity, order, sendUserAccount);
             });
 
 
-        } else {
+        } else if (isInspectionReport && !directTemplateOrder) {
             // 淇敼鎴愬搧鐘舵��
             // 鍒ゆ柇鏄惁鏈変笉鍚堟牸
             Long unqualifiedCount = insReportService.getUnqualifiedCount(order);
@@ -982,13 +1313,13 @@
      * @param ifsInventoryQuantity
      * @param order
      */
-    private void addAnalysis(List<InsProduct> productList, IfsInventoryQuantity ifsInventoryQuantity, InsOrder order) {
+    private void addAnalysis(List<InsProduct> productList, IfsInventoryQuantity ifsInventoryQuantity, InsOrder order, String sendUserAccount) {
         for (InsProduct insProduct : productList) {
-            // todo: 鏆傛椂鍒ゆ柇鏄惁鏄�佸寲
-            if (insProduct.getInspectionItem().contains("鑰佸寲") && insProduct.getInsResult().equals(1)) {
+            // 鍒ゆ柇鏄惁鏄暟鍊肩被鍨�
+            if ("1".equals(insProduct.getInspectionValueType()) && Objects.equals(insProduct.getInsResult(), 1)) {
                 List<InsProductDeviationWarningDetail> insProductAnalysisDtoList = insProductMapper.selectAnalysis(insProduct, ifsInventoryQuantity.getSupplierName());
 
-                if (insProductAnalysisDtoList.size() < 10) {
+                if (CollectionUtils.isEmpty(insProductAnalysisDtoList)) {
                     continue;
                 }
 
@@ -997,8 +1328,10 @@
                         .collect(Collectors.toList());
 
                 double deviation = isDeviationOverTenPercent(laseValueList, insProduct.getLastValue());
+                // 鍒ゆ柇瑕佹眰鍊兼槸鍚﹀亸宸秴杩�10%
+                double asked = isDeviationOverTenPercentByAsked(insProduct.getAsk(), insProduct.getLastValue());
                 // 鍒ゆ柇鍋忓樊鏄惁澶т簬10
-                if (deviation > 10) {
+                if (deviation > 10 || asked > 10) {
                     // 鍒ゆ柇涔嬪墠鏄惁娣诲姞杩�, 娣诲姞杩囦笉闇�瑕佹坊鍔�
                     long count = insProductDeviationWarningService.count(Wrappers.<InsProductDeviationWarning>lambdaQuery()
                             .eq(InsProductDeviationWarning::getInsProductId, insProduct.getId()));
@@ -1025,7 +1358,9 @@
                         deviationWarningDetail.setSampleCode(insProduct.getSampleCode());
                         deviationWarningDetail.setSupplierName(ifsInventoryQuantity.getSupplierName());
                         deviationWarningDetail.setTestValue(insProduct.getLastValue());
-                        deviationWarningDetail.setIsIssue(1);
+                        deviationWarningDetail.setDetectionTime(insProduct.getCreateTime());
+                        deviationWarningDetail.setIsIssue(deviation > 10 ? 1 : 0);
+                        deviationWarningDetail.setIsIssueAsked(asked > 10 ? 1 : 0);
 
                         insProductAnalysisDtoList.add(deviationWarningDetail);
 
@@ -1036,22 +1371,26 @@
 
                         insProductDeviationWarningDetailService.saveBatch(insProductAnalysisDtoList);
 
-
-//                    String message = "";
-//                    message += "妫�楠屼换鍔″鏍搁�氱煡";
-//                    message += "\n鎻愪氦浜�: " + userName;
-//                    message += "\n濮旀墭缂栧彿: " + order.getEntrustCode();
-//                    message += "\n鏍峰搧鍚嶇О: " + insSample.getModel();
-//                    message += "\n瑙勬牸鍨嬪彿: " + order.getPartDetail();
-//                    if (ifsInventoryQuantity != null) {
-//                        message += "\n鎵规鍙�: " + ifsInventoryQuantity.getUpdateBatchNo();
-//                    }
-//                    //鍙戦�佷紒涓氬井淇℃秷鎭�氱煡  鎻愪氦澶嶆牳
-//                    try {
-//                        WxCpUtils.inform(sendUserAccount, message, null);
-//                    } catch (Exception e) {
-//                        throw new RuntimeException(e);
-//                    }
+                        //鍙戦�佷紒涓氬井淇℃秷鎭�氱煡  妫�楠岄」棰勮棰勮閫氱煡
+                        try {
+                            String message = "";
+                            message += "妫�楠岄」棰勮棰勮閫氱煡";
+                            message += "\n濮旀墭缂栧彿: " + order.getEntrustCode();
+                            message += "\n鏍峰搧鍚嶇О: " + order.getSample();
+                            message += "\n瑙勬牸鍨嬪彿: " + order.getPartDetail();
+                            message += "\n鎵规鍙�: " + ifsInventoryQuantity.getUpdateBatchNo();
+                            message += "\n渚涘簲鍟嗗悕绉�: " + ifsInventoryQuantity.getSupplierName();
+                            message += "\n妫�楠岄」: " + insProduct.getInspectionItem() + insProduct.getInspectionItemSubclass();
+                            message += "\n鍋忓樊瓒呰繃浜� 10%";
+                            // 鍙戦�佺粰鎻愪氦浜�
+//                            WxCpUtils.inform(sendUserAccount, message, null);
+//
+//                            // todo: 鍙戦�佺粰妫�娴嬩腑蹇冧富浠�(鍥哄畾姝�)
+//                            WxCpUtils.inform("ZT-004704", message, null);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                            log.error("鍋忓樊棰勮浼佷笟寰俊閫氱煡鎶ラ敊");
+                        }
                     }
                 }
             }
@@ -1077,7 +1416,28 @@
         double target = Double.parseDouble(targetStr);
         double deviationPercent = Math.abs(target - average) / average * 100;
 
-        return deviationPercent;
+        // 淇濈暀涓や綅灏忔暟
+        DecimalFormat df = new DecimalFormat("#.00");
+        String formatted = df.format(deviationPercent);
+        return Double.parseDouble(formatted);
+    }
+
+    /**
+     * *****璁$畻鍋忓樊锛堣姹傚�硷級****
+     * @param asked
+     * @param targetStr
+     * @return
+     */
+    public static double isDeviationOverTenPercentByAsked(String asked, String targetStr) {
+        if(!isNumeric(asked)) return 0;
+        double average = Double.parseDouble(asked);
+        double target = Double.parseDouble(targetStr);
+        double deviationPercent = Math.abs(target - average) / average * 100;
+
+        // 淇濈暀涓や綅灏忔暟
+        DecimalFormat df = new DecimalFormat("#.00");
+        String formatted = df.format(deviationPercent);
+        return Double.parseDouble(formatted);
     }
 
     /**
@@ -1086,29 +1446,78 @@
      * @param ids
      */
     private void templateCopy(Integer orderId, List<Integer> ids) {
-        // 鍒犻櫎鍘熸湰妯℃澘
-        insOrderStandardTemplateService.remove(Wrappers.<InsOrderStandardTemplate>lambdaQuery()
-                .eq(InsOrderStandardTemplate::getInsOrderId, orderId));
-        // 澶嶅埗妯℃澘
-        Set<Integer> set = new HashSet<>();
+        // 淇濈暀妯℃澘椤电椤哄簭锛屽苟鍦ㄩ娆℃彁浜ゅ鏍告椂鐢ㄦ楠屾湡闂撮噰鐢ㄧ殑鏈�鏂版ā鏉垮埛鏂板揩鐓с��
+        // 鐩寸粦妯℃澘璁㈠崟蹇呴』浠ュ師璁㈠崟蹇収涓烘ā鏉挎竻鍗曪紝涓嶈兘鍙寜 ins_product 閲嶅缓锛�
+        // 娌℃湁鈥滄楠岄」鈥濇爣璁扮殑妯℃澘涓嶄細鐢熸垚 ins_product锛屽惁鍒欐彁浜ゅ悗浼氳閿欒鍒犻櫎銆�
+        List<InsOrderStandardTemplate> oldSnapshots = insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                        .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId));
+        Map<Integer, Integer> templateSortMap = new HashMap<>();
+        Map<Integer, String> templateRecordValuesMap = new HashMap<>();
+        Map<Integer, String> templateTemperatureMap = new HashMap<>();
+        Map<Integer, String> templateHumidityMap = new HashMap<>();
+        Map<Integer, InsOrderStandardTemplate> oldSnapshotMap = new LinkedHashMap<>();
+        int nextTemplateSort = 0;
+        for (InsOrderStandardTemplate snapshot : oldSnapshots) {
+            if (snapshot.getTemplateId() != null) {
+                oldSnapshotMap.putIfAbsent(snapshot.getTemplateId(), snapshot);
+                if (snapshot.getSort() != null) {
+                    templateSortMap.putIfAbsent(snapshot.getTemplateId(), snapshot.getSort());
+                    nextTemplateSort = Math.max(nextTemplateSort, snapshot.getSort() + 1);
+                }
+                if (snapshot.getRecordValues() != null) {
+                    templateRecordValuesMap.putIfAbsent(snapshot.getTemplateId(), snapshot.getRecordValues());
+                }
+                if (snapshot.getTemperature() != null) {
+                    templateTemperatureMap.putIfAbsent(snapshot.getTemplateId(), snapshot.getTemperature());
+                }
+                if (snapshot.getHumidity() != null) {
+                    templateHumidityMap.putIfAbsent(snapshot.getTemplateId(), snapshot.getHumidity());
+                }
+            }
+        }
+
+        LinkedHashSet<Integer> templateIds = new LinkedHashSet<>();
+        if (isDirectTemplateOrder(orderId)) {
+            // 鍏堝姞鍏ヨ鍗曞師鏉ョ粦瀹氱殑鍏ㄩ儴妯℃澘锛屽寘鎷笉鐢熸垚妫�楠岄」璁板綍鐨勬ā鏉裤��
+            templateIds.addAll(oldSnapshotMap.keySet());
+        }
         List<InsProduct> insProductList = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
                 .in(InsProduct::getInsSampleId, ids)
                 .select(InsProduct::getTemplateId));
+        insProductList.stream()
+                .map(InsProduct::getTemplateId)
+                .filter(Objects::nonNull)
+                .forEach(templateIds::add);
 
-        for (InsProduct product : insProductList) {
-            // 鏌ヨ妯℃澘id
-            if (product.getTemplateId() != null && set.add(product.getTemplateId())) {
-                StandardTemplate standardTemplate = standardTemplateService.getById(product.getTemplateId());
-                if (standardTemplate != null) {
-                    InsOrderStandardTemplate insOrderStandardTemplate = new InsOrderStandardTemplate();
-                    insOrderStandardTemplate.setInsOrderId(orderId);
-                    insOrderStandardTemplate.setTemplateId(standardTemplate.getId());
-                    insOrderStandardTemplate.setNumber(standardTemplate.getNumber());
-                    insOrderStandardTemplate.setName(standardTemplate.getName());
-                    insOrderStandardTemplate.setThing(standardTemplate.getThing());
-                    insOrderStandardTemplateService.save(insOrderStandardTemplate);
-                }
+        List<InsOrderStandardTemplate> refreshedSnapshots = new ArrayList<>();
+        for (Integer templateId : templateIds) {
+            StandardTemplate standardTemplate = standardTemplateService.getById(templateId);
+            InsOrderStandardTemplate oldSnapshot = oldSnapshotMap.get(templateId);
+            if (standardTemplate == null && oldSnapshot == null) {
+                continue;
             }
+            InsOrderStandardTemplate refreshed = new InsOrderStandardTemplate();
+            refreshed.setInsOrderId(orderId);
+            refreshed.setTemplateId(templateId);
+            refreshed.setNumber(standardTemplate == null ? oldSnapshot.getNumber() : standardTemplate.getNumber());
+            refreshed.setName(standardTemplate == null ? oldSnapshot.getName() : standardTemplate.getName());
+            refreshed.setRemark(standardTemplate == null ? oldSnapshot.getRemark() : standardTemplate.getRemark());
+            refreshed.setThing(standardTemplate == null ? oldSnapshot.getThing() : standardTemplate.getThing());
+            refreshed.setRecordValues(templateRecordValuesMap.get(templateId));
+            refreshed.setTemperature(templateTemperatureMap.get(templateId));
+            refreshed.setHumidity(templateHumidityMap.get(templateId));
+            Integer templateSort = templateSortMap.get(templateId);
+            refreshed.setSort(templateSort == null ? nextTemplateSort++ : templateSort);
+            refreshedSnapshots.add(refreshed);
+        }
+
+        // 鏂板揩鐓у凡瀹屾暣缁勮鍚庡啀鏇挎崲锛涗簨鍔″け璐ユ椂浼氭暣浣撳洖婊氥��
+        insOrderStandardTemplateService.remove(Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                .eq(InsOrderStandardTemplate::getInsOrderId, orderId));
+        if (!refreshedSnapshots.isEmpty()) {
+            insOrderStandardTemplateService.saveBatch(refreshedSnapshots);
         }
     }
 
@@ -1124,6 +1533,44 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int rawMaterialVerifyPlan(Integer orderId, String laboratory, Integer type, String tell, Integer userId) {
+        VerifyPlanDto dto = new VerifyPlanDto();
+        dto.setOrderId(orderId);
+        dto.setLaboratory(laboratory);
+        dto.setType(type);
+        dto.setTell(tell);
+        dto.setUserId(userId);
+        return rawMaterialVerifyPlan(dto);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int rawMaterialVerifyPlan(VerifyPlanDto dto) {
+        Integer orderId = dto.getOrderId();
+        String laboratory = dto.getLaboratory();
+        Integer type = dto.getType();
+        String tell = dto.getTell();
+        Integer userId = dto.getUserId();
+        if (orderId == null || laboratory == null || type == null) {
+            throw new ErrorException("澶嶆牳鍙傛暟涓嶅畬鏁�");
+        }
+        ensureDirectTemplateOrderState(orderId);
+        InsOrderState currentState = insOrderStateMapper.selectOne(Wrappers.<InsOrderState>lambdaQuery()
+                .eq(InsOrderState::getInsOrderId, orderId)
+                .eq(InsOrderState::getLaboratory, laboratory)
+                .last("limit 1"));
+        InsReport existingReport = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
+                .eq(InsReport::getInsOrderId, orderId)
+                .last("limit 1"));
+        if (currentState != null && Objects.equals(currentState.getInsState(), 5)
+                && existingReport != null && StringUtils.isNotBlank(existingReport.getUrl())) {
+            // 闃叉澶嶆牳椤甸潰閲嶅鐐瑰嚮鎴栫綉缁滈噸璇曢噸澶嶇敓鎴愭姤鍛娿�侀噸澶嶅彂璧锋姤鍛婂鎵广��
+            return 1;
+        }
+        boolean directTemplateOrder = isDirectTemplateOrder(orderId);
+        if (directTemplateOrder && Objects.equals(type, 1)
+                && !Objects.equals(dto.getInsResult(), 0) && !Objects.equals(dto.getInsResult(), 1)) {
+            throw new ErrorException("璇烽�夋嫨妫�楠屽崟缁撹");
+        }
         Integer num = (type == 1 ? 5 : 4);
         LocalDateTime now = LocalDateTime.now();
         insOrderStateMapper.update(null, Wrappers.<InsOrderState>lambdaUpdate()
@@ -1137,31 +1584,65 @@
                 .eq(InsOrderState::getInsOrderId, orderId)
                 .ne(InsOrderState::getInsState, 5));
         InsReport report = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
-                .eq(InsReport::getInsOrderId, orderId));
+                .eq(InsReport::getInsOrderId, orderId)
+                .last("limit 1"));
+        Integer writeUserId = report != null && report.getWriteUserId() != null
+                ? report.getWriteUserId() : resolveInspectionUserId(orderId, laboratory);
         // 鏌ヨ璁㈠崟
         InsOrder order = insOrderMapper.selectById(orderId);
+        if (directTemplateOrder && Objects.equals(type, 1)) {
+            List<Integer> templateResults = insOrderStandardTemplateService.list(
+                            Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                                    .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                                    .select(InsOrderStandardTemplate::getInsResult))
+                    .stream().map(InsOrderStandardTemplate::getInsResult)
+                    .collect(Collectors.toList());
+            if (templateResults.isEmpty()
+                    || templateResults.stream().anyMatch(result -> !Objects.equals(result, 0)
+                            && !Objects.equals(result, 1))) {
+                throw new ErrorException("璇峰厛濉啓鍏ㄩ儴妯℃澘鐨勬楠岀粨璁�");
+            }
+            Integer aggregateResult = templateResults.stream().allMatch(result -> Objects.equals(result, 1))
+                    ? 1 : 0;
+            insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
+                    .eq(InsOrder::getId, orderId)
+                    .set(InsOrder::getInsResult, aggregateResult));
+            order.setInsResult(aggregateResult);
+        }
         if (count == 0 && num == 5) {
-            // 淇敼鎶ュ憡鐘舵��
-            insReportMapper.update(null, Wrappers.<InsReport>lambdaUpdate()
-                    .eq(InsReport::getInsOrderId, orderId)
-                    .set(InsReport::getIsPass, 1));
-
             // 淇敼璁㈠崟鐘舵��
             insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
                     .eq(InsOrder::getId, orderId)
                     .set(InsOrder::getInsState, 5));
 
+            // 妫�楠屼汉鍛樻彁浜ゅ鏍告椂涓嶅啀鐢熸垚鎶ュ憡锛涗粎鍦ㄥ叏閮ㄨ瘯楠屽澶嶆牳閫氳繃鍚庣敓鎴愭娴嬫姤鍛娿��
+            if (report == null || StringUtils.isBlank(report.getUrl())) {
+                this.generateReport(orderId, DETECTION_REPORT, writeUserId);
+                report = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
+                        .eq(InsReport::getInsOrderId, orderId)
+                        .last("limit 1"));
+            }
+            if (report == null || StringUtils.isBlank(report.getUrl())) {
+                throw new ErrorException("妫�娴嬫姤鍛婄敓鎴愬け璐�");
+            }
+            if (report.getTempUrlPdf() == null) {
+                String tempUrlPdf = this.wordToPdfTemp(report.getUrl().replace("/word", wordUrl));
+                report.setTempUrlPdf("/word/" + tempUrlPdf);
+            }
+            report.setIsPass(1);
+            insReportMapper.updateById(report);
+
             //鐢熸垚鍘熸潗鏂欒繘璐ч獙璇佸師濮嬭褰曞埌闄勪欢閲�
             if (order.getTypeSource() != null && order.getTypeSource().equals(1)) {
-                this.reportFactoryVerify(orderId, userId, report.getWriteUserId());
+                this.reportFactoryVerify(orderId, userId, writeUserId);
             }
 
             // 鏌ヨ妫�楠屼换鍔$殑妫�楠屼换鍔�
             // 鎶ュ憡鐩栦笂鎵瑰噯浜�
-            insReportService.writeReport(report.getId(), userId, report.getWriteUserId());
+            insReportService.writeReport(report.getId(), userId, writeUserId);
 
             // 妫�楠屼汉
-            String userName = insProductMapper.selectUserById(report.getWriteUserId()).get("name");
+            String userName = insProductMapper.selectUserById(writeUserId).get("name");
 
             // 澶嶆牳浜�
             Integer checkUserId = SecurityUtils.getUserId().intValue();
@@ -1210,7 +1691,7 @@
 
             // 鍙戦�佹秷鎭殑浜�
             // 鏌ヨ鍙戦�佷汉淇℃伅
-            String sendUserAccount = insProductMapper.selectUserById(report.getWriteUserId()).get("account");
+            String sendUserAccount = insProductMapper.selectUserById(writeUserId).get("account");
 
             // 鍙戦�佷紒涓氬井淇¢�氱煡(妫�楠屼换鍔¢��鍥�)
             threadPoolTaskExecutor.execute(() -> {
@@ -1242,26 +1723,80 @@
         return 1;
     }
 
+    private boolean isDirectTemplateOrder(Integer orderId) {
+        List<InsSample> samples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
+                .eq(InsSample::getInsOrderId, orderId));
+        if (samples.isEmpty()) {
+            return false;
+        }
+        Long snapshotCount = insOrderStandardTemplateService.count(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId));
+        InsOrder order = snapshotCount == 0 ? null : insOrderMapper.selectById(orderId);
+        if (order != null && samples.stream().anyMatch(sample -> isDirectTemplateSample(order, sample))) {
+            return true;
+        }
+        // 鍏煎宸茬粡鐢熸垚浜嗘ā鏉胯鍙枫�佷絾璁㈠崟鍩虹瀛楁涓嶅畬鏁寸殑鍘嗗彶鐩寸粦璁㈠崟銆�
+        return insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
+                .in(InsProduct::getInsSampleId, samples.stream().map(InsSample::getId).collect(Collectors.toList()))
+                .isNotNull(InsProduct::getTemplateRowIndex)) > 0;
+    }
+
+    /**
+     * 鍏煎淇涓婄嚎鍓嶅凡缁忎笅鍙戙�佷絾鍥犳病鏈� ins_product 鑰岀己灏戜换鍔$姸鎬佺殑鐩寸粦妯℃澘璁㈠崟銆�
+     */
+    private void ensureDirectTemplateOrderState(Integer orderId) {
+        if (!isDirectTemplateOrder(orderId)) {
+            return;
+        }
+        Long stateCount = insOrderStateMapper.selectCount(Wrappers.<InsOrderState>lambdaQuery()
+                .eq(InsOrderState::getInsOrderId, orderId)
+                .eq(InsOrderState::getLaboratory, DIRECT_TEMPLATE_LABORATORY));
+        if (stateCount > 0) {
+            return;
+        }
+        InsOrderState state = new InsOrderState();
+        state.setInsOrderId(orderId);
+        state.setLaboratory(DIRECT_TEMPLATE_LABORATORY);
+        state.setInsState(0);
+        insOrderStateMapper.insert(state);
+    }
+
+    private Integer resolveInspectionUserId(Integer orderId, String laboratory) {
+        InsSampleUser inspector = insSampleUserMapper.selectOne(Wrappers.<InsSampleUser>lambdaQuery()
+                .eq(InsSampleUser::getInsSampleId, orderId)
+                .eq(InsSampleUser::getState, 0)
+                .eq(StringUtils.isNotBlank(laboratory), InsSampleUser::getSonLaboratory, laboratory)
+                .orderByDesc(InsSampleUser::getId)
+                .last("limit 1"));
+        if (inspector == null || inspector.getUserId() == null) {
+            throw new ErrorException("鎵句笉鍒板綋鍓嶆楠屼换鍔$殑妫�楠屼汉锛屾棤娉曠敓鎴愭娴嬫姤鍛�");
+        }
+        return inspector.getUserId();
+    }
+
     /**
      * 鐢熸垚鎶ュ憡
      * @param orderId
      */
-    private void generateReport(Integer orderId) {
+    private void generateReport(Integer orderId, Integer reportType, Integer writeUserId) {
         /*鏍峰搧涓嬬殑椤圭洰鍙鏈変竴涓」鐩笉鍚堟牸鍒欐楠岀粨鏋滀负0,鍚﹀垯涓�1*/
         //杩欓噷鐨刬nsSamples鏄鍗曚笅鐨勬墍鏈夋牱鍝佸寘鎷�("/")
         List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery().eq(InsSample::getInsOrderId, orderId));
+        if (Objects.equals(reportType, INSPECTION_REPORT)) {
         for (InsSample insSample : insSamples) {
             List<InsProduct> insProducts = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery()
                     .eq(InsProduct::getInsSampleId, insSample.getId())
                     .eq(InsProduct::getState, 1)
                     .ne(InsProduct::getIsBinding, 1));
-            List<Integer> results = insProducts.stream().map(InsProduct::getInsResult).filter(str -> str != null).collect(Collectors.toList());
+            List<Integer> results = insProducts.stream().map(InsProduct::getInsResult).filter(Objects::nonNull).collect(Collectors.toList());
             if (results.contains(0)) {
                 insSample.setInsResult(0);
             } else {
                 insSample.setInsResult(1);
             }
             insSampleMapper.updateById(insSample);
+        }
         }
         InsOrder insOrder = insOrderMapper.selectById(orderId);
         // 鎶芥鍙樻垚濮旀墭妫�楠�
@@ -1272,10 +1807,10 @@
         // 鍒ゆ柇鏄ぇ鎶ュ憡杩樻槸灏忔姤鍛�  杩涘巶灏忔姤鍛�, 鍏朵粬閮芥槸澶ф姤鍛�
         if (insOrder.getOrderType().equals(InsOrderTypeConstants.ENTER_THE_FACTORY)) {
             // 鐢熸垚灏忔姤鍛�
-            addSmallReport(orderId, insOrder, insSamples);
+            addSmallReport(orderId, insOrder, insSamples, reportType, writeUserId);
         } else {
             //鐢熸垚澶ф姤鍛�
-            addBitReport(orderId, insOrder);
+            addBitReport(orderId, insOrder, reportType, writeUserId);
         }
 
     }
@@ -1315,36 +1850,13 @@
     }
 
     /**
-     * 鑾峰彇涓嶅悎鏍兼暟鎹�
-     * @return
-     */
-    @Override
-    public List<InsProduct> getInsProductUnqualified(InsOrderPlanProductDto dto) {
-        List<InsProduct> insProducts = new ArrayList<>();
-        switch (dto.getType()) {
-            case 0:
-                //鏍峰搧
-                insProducts = insSampleMapper.getInsProduct1(dto.getId(), dto.getLaboratory(), dto.getCableTag(), dto.getRepetitionTag(), "1");
-                break;
-            case 4:
-                //鐢电紗閰嶇疆
-                insProducts = insSampleMapper.getInsProduct1(dto.getId(), dto.getLaboratory(), dto.getCableTag(), dto.getRepetitionTag(), "1");
-                break;
-            case 5:
-                //鍘熸潗鏂欎笅鍗�
-                insProducts = insSampleMapper.getInsProduct6(dto.getId(), dto.getLaboratory(), dto.getRawMaterialTag(), "1");
-                break;
-        }
-        return insProducts;
-    }
-
-    /**
      * 鏂板涓嶅悎鏍煎娴嬪唴瀹�
-     * @param ids
      * @return
      */
     @Override
-    public boolean addDisqualificationRetest(List<Integer> ids) {
+    public boolean addDisqualificationRetest(List<InsProduct> insProductsList) {
+        List<Integer> ids = insProductsList.stream().map(InsProduct::getId).collect(Collectors.toList());
+
         // 鍒ゆ柇涔嬪墠鏄惁娣诲姞杩�
         Long count = insUnqualifiedRetestProductMapper.selectCount(Wrappers.<InsUnqualifiedRetestProduct>lambdaQuery()
                 .in(InsUnqualifiedRetestProduct::getInsProductId, ids));
@@ -1354,6 +1866,20 @@
 
         // 鏌ヨ涓嶅悎鏍煎唴瀹�
         List<InsUnqualifiedRetestProduct> list = insUnqualifiedRetestProductMapper.selectRetestProduct(ids);
+        // 寰幆鍒ゆ柇鏄惁鏄粦瀹氬��, 缁戝畾鍊间慨鏀规楠岃姹�
+        for (InsUnqualifiedRetestProduct insUnqualifiedRetestProduct : list) {
+            for (InsProduct insProduct : insProductsList) {
+                if (insProduct.getIsBinding().equals(1)) {
+                    insUnqualifiedRetestProduct.setIsBinding(1);
+                    insUnqualifiedRetestProduct.setAsk(null);
+                    insUnqualifiedRetestProduct.setTell(null);
+                    insUnqualifiedRetestProduct.setPrice(null);
+                    insUnqualifiedRetestProduct.setManHour(null);
+                    insUnqualifiedRetestProduct.setSection(null);
+                }
+            }
+        }
+
         // 鏂板涓嶅悎鏍煎唴瀹�
         insUnqualifiedRetestProductService.saveBatch(list);
         list.forEach(insUnqualifiedRetestProduct -> {
@@ -1365,38 +1891,29 @@
     }
 
     @Override
-    public List<InsProduct> getInsProductUnqualifiedRetest(Integer id, Integer type, String laboratory, String cableTag, String rawMaterialTag, String retestTag) {
+    public List<InsProduct> getInsProductUnqualifiedRetest(InsOrderPlanProductDto dto) {
 
         List<InsProduct> insProducts = new ArrayList<>();
-        switch (type) {
+        switch (dto.getType()) {
             case 0:
-                //鏍峰搧
-                insProducts = insUnqualifiedRetestProductMapper.getInsProductUnqualifiedRetest1(id, laboratory, retestTag);
-                break;
             case 4:
-                //鐢电紗閰嶇疆
-                insProducts = insUnqualifiedRetestProductMapper.getInsProductUnqualifiedRetest5(id, laboratory, cableTag, retestTag);
+                //濮旀墭
+                insProducts = insUnqualifiedRetestProductMapper.getInsProductUnqualifiedRetest1(dto.getId(), dto.getLaboratory(), dto.getCableTag(), dto.getRepetitionTag(), dto.getRetestTag());
                 break;
             case 5:
                 //鍘熸潗鏂欎笅鍗�
-                insProducts = insUnqualifiedRetestProductMapper.getInsProductUnqualifiedRetest6(id, laboratory, rawMaterialTag, retestTag);
+                insProducts = insUnqualifiedRetestProductMapper.getInsProductUnqualifiedRetest6(dto.getId(), dto.getLaboratory(), dto.getRawMaterialTag(), dto.getRetestTag());
                 break;
         }
         if (BeanUtil.isEmpty(insProducts)) {
             return null;
         }
-        InsOrder order = insOrderMapper.selectFirstSubmit(id);
-        getTemplateThing(order, Collections.unmodifiableList(insProducts));
+        InsOrder order = insOrderMapper.selectFirstSubmit(dto.getId());
+        getTemplateThing(order, Collections.unmodifiableList(insProducts), dto.getLaboratory());
         return insProducts;
     }
 
 
-    /**
-     * 淇濆瓨涓嶅悎鏍煎娴嬫楠屽唴瀹�
-     * @param currentTable
-     * @param orderId
-     * @param sonLaboratory
-     */
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void saveUnqualifiedContext(Map<String, Object> insContext, Integer currentTable, Integer currentSampleId, Integer orderId, String sonLaboratory) {
@@ -1414,13 +1931,12 @@
                     BeanUtil.copyProperties(oldResults.get(0), newResult);
                 }
                 newResult.setRetestProductId(Integer.parseInt(k));
-
+                /*鏍¢獙涓�涓媟esult琛�*/
                 if (oldResults.size() > 1) {
                     for (int i = 1; i < oldResults.size(); i++) {
                         insUnqualifiedRetestResultMapper.deleteById(oldResults.get(i));
                     }
                 }
-
                 //妫�楠屽��
                 if (jo.get("insValue") != null) {
                     JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(jo.get("insValue")));
@@ -1451,6 +1967,8 @@
                     for (Object o : jsonArray2) {
                         JSONObject comValue = JSON.parseObject(JSON.toJSONString(o));
                         Map<String, Object> map = new HashMap<>();
+                        map.put("r", JSON.toJSONString(comValue.get("r")));
+                        map.put("c", JSON.toJSONString(comValue.get("c")));
                         map.put("v", JSON.parseObject(JSON.toJSONString(comValue.get("v"))).get("v"));
                         cv.add(map);
                     }
@@ -1513,41 +2031,18 @@
                 insProductUserMapper.insert(new InsProductUser(null, userId, LocalDateTime.now(), insProduct.getId()));
 
 
-                InsSample insSample = insSampleMapper.selectById(insProductMapper.selectById(insProduct.getId()).getInsSampleId());
-                insSample.setInsState(1);
-                Long l = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
-                        .eq(InsProduct::getInsSampleId, insSample.getId()));
-                Long l1 = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
-                        .eq(InsProduct::getInsSampleId, insSample.getId())
-                        .and(wrapper -> wrapper
-                                .isNotNull(InsProduct::getInsResult)
-                                .or()
-                                .ne(InsProduct::getInsResult, 2)
-                        ));
-                if (Objects.equals(l, l1)) {
-                    insSample.setInsState(2);
-                }
-                insSampleMapper.updateById(insSample);
                 /*鏍¢獙涓�涓媟esult琛�*/
                 List<InsUnqualifiedRetestResult> insProductResults = insUnqualifiedRetestResultMapper.selectList(Wrappers.<InsUnqualifiedRetestResult>lambdaQuery()
-                        .eq(InsUnqualifiedRetestResult::getRetestProductId, insProduct.getId()));
+                        .eq(InsUnqualifiedRetestResult::getRetestProductId, product.getId()));
                 if (insProductResults.size() > 1) {
                     for (int i = 1; i < insProductResults.size(); i++) {
                         insUnqualifiedRetestResultMapper.deleteById(insProductResults.get(i));
                     }
                 }
+
             }
         });
-        String sampleIdStr = insContext.keySet().stream().findFirst().orElse(null);
-        if (sampleIdStr != null) {
-            int count = insProductMapper.selectInsProductCountByOrderId(orderId);
-            if (count == 0) {
-                insOrderStateMapper.update(new InsOrderState(), Wrappers.<InsOrderState>lambdaUpdate()
-                        .eq(InsOrderState::getInsOrderId, orderId)
-                        .eq(InsOrderState::getLaboratory, sonLaboratory)
-                        .set(InsOrderState::getInsState, 2));
-            }
-        }
+
     }
 
     /**
@@ -1657,16 +2152,117 @@
     /*****************************************************  灏忔姤鍛�    ***************************************************************************/
 
     /**
+     * 璁剧疆琛ㄦ牸鏍峰紡
+     * @param max 鏍囪瘑鏈�澶т釜鏁�
+     * @return
+     */
+    private TableStyle setTableStyle(int max, boolean showResult){
+        //璁剧疆鏍峰紡
+        TableStyle tableStyle = new TableStyle();
+        if (!showResult) {
+            switch (max) {
+                case 1: tableStyle.setColWidths(new int[]{650, 3000, 850, 2400, 3100}); break;
+                case 2: tableStyle.setColWidths(new int[]{650, 2800, 850, 2200, 1750, 1750}); break;
+                case 3: tableStyle.setColWidths(new int[]{650, 2600, 850, 1800, 1400, 1400, 1400}); break;
+                case 4: tableStyle.setColWidths(new int[]{650, 2400, 850, 1600, 1125, 1125, 1125, 1125}); break;
+                case 5: tableStyle.setColWidths(new int[]{650, 2200, 850, 1500, 960, 960, 960, 960, 960}); break;
+                default: break;
+            }
+        } else if(max<=5){
+            for (int i = 1; i <= max; i++) {
+                // 鏍规嵁妫�楠岀粨鏋滀釜鏁颁慨鏀归暱搴�
+                switch (i) {
+                    case 1:
+                        tableStyle.setColWidths(new int[]{650, 2900, 850, 2300, 2100, 1200});
+                        break;
+                    case 2:
+                        tableStyle.setColWidths(new int[]{650, 2700, 850, 2200, 1200, 1200, 1200});
+                        break;
+                    case 3:
+                        tableStyle.setColWidths(new int[]{650, 2700, 850, 1600, 1000, 1000, 1000, 1200});
+                        break;
+                    case 4:
+                        tableStyle.setColWidths(new int[]{650, 2400, 850, 1500, 850, 850, 850, 850, 1200});
+                        break;
+                    case 5:
+                        tableStyle.setColWidths(new int[]{650, 2200, 850, 1350, 770, 770, 770, 770, 770, 1100});
+                        break;
+                }
+            }
+        }
+
+        tableStyle.setWidth("10000");
+        tableStyle.setAlign(TableRowAlign.CENTER);
+        BorderStyle borderStyle = new BorderStyle();
+        borderStyle.setColor("000000");
+        borderStyle.setType(XWPFTable.XWPFBorderType.SINGLE);
+        borderStyle.setSize(4);
+        tableStyle.setLeftBorder(borderStyle);
+        tableStyle.setRightBorder(borderStyle);
+        tableStyle.setInsideHBorder(borderStyle); // 璁剧疆姘村钩鍐呰竟妗�
+        tableStyle.setInsideVBorder(borderStyle);
+        return tableStyle;
+    }
+
+
+    /**
+     * 澶勭悊鏈夌數缂嗛鑹叉爣璇嗙殑妫�娴嬮」
+     * @param cableTags 鐢电紗棰滆壊鏍囪瘑
+     * @param collect   妫�娴嬮」鍒楄〃
+     * @param startIndex 璧峰涓嬫爣
+     * @param endIndex   缁撴潫涓嬫爣
+     * @return
+     */
+    private List<SampleProductExportDto> transformSampleProduct(List<String> cableTags,Map<String, List<SampleProductExportDto>> collect,int startIndex,int endIndex){
+        List<SampleProductExportDto> sampleProductExportDtos = new ArrayList<>();
+        for (String s : collect.keySet()) {
+            List<String> lastValueList = new ArrayList<>();
+            SampleProductExportDto dto = new SampleProductExportDto();
+            BeanUtil.copyProperties(collect.get(s).get(0),dto);
+            Set<String> tellSet = new HashSet<>();
+            for (int i = startIndex; i < endIndex; i++) {
+                String cableTag = cableTags.get(i);
+                for (SampleProductExportDto sDto : collect.get(s)) {
+                    tellSet.add(sDto.getTell());
+                    if(sDto.getCableTag().equals(cableTag)){
+                        lastValueList.add(sDto.getLastValue());
+                    }
+                }
+            }
+            //鍒囧壊鐢电紗閰嶇疆椤�
+            dto.setTell(String.join("\n",tellSet));
+            dto.setLastValueList(lastValueList);
+            sampleProductExportDtos.add(dto);
+        }
+        return sampleProductExportDtos;
+    }
+
+    /**
+     * 妫�娴嬮」鎺掑簭
+     * @param sourceMap
+     * @param targetMap
+     */
+    private void sortSampleProduct(Map<String, List<SampleProductExportDto>> sourceMap,Map<String, List<SampleProductExportDto>> targetMap){
+        List<Map.Entry<String, List<SampleProductExportDto>>> entries = new ArrayList<>(sourceMap.entrySet());
+        entries.sort(Comparator.comparingInt(o -> (o.getValue().get(0).getSort() == null ? 0 : o.getValue().get(0).getSort())));
+        for (Map.Entry<String, List<SampleProductExportDto>> entry : entries) {
+            targetMap.put(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
      * 灏忔姤鍛婄敓鎴�
      * @param orderId
      * @param insOrder
      * @param insSamples
      */
-    private void addSmallReport(Integer orderId, InsOrder insOrder, List<InsSample> insSamples) {
+    private void addSmallReport(Integer orderId, InsOrder insOrder, List<InsSample> insSamples, Integer reportType, Integer writeUserId) {
         InsReport insReport = new InsReport();
         AtomicReference<String> resultCh = new AtomicReference<>("");
+        boolean showResult = Objects.equals(reportType, INSPECTION_REPORT);
         insReport.setCode(insOrder.getEntrustCode());
         insReport.setInsOrderId(orderId);
+        insReport.setReportType(reportType);
         InsSample insSample = insSamples.get(0);
         // 濉厖鍩虹鏁版嵁
         EnterFactoryReport enterFactoryReport = new EnterFactoryReport();
@@ -1674,11 +2270,17 @@
         enterFactoryReport.setSample(insOrder.getSample());
         // 鑾峰彇ifs鏁版嵁
         IfsInventoryQuantity ifsInventoryQuantity = ifsInventoryQuantityMapper.selectById(insOrder.getIfsInventoryId());
+        //鏌ヨ闆朵欢灞炴��
+        IfsPartPropsRecord ifsPartPropsRecord = ifsPartPropsRecordMapper.selectOne(Wrappers.<IfsPartPropsRecord>lambdaQuery()
+                .eq(IfsPartPropsRecord::getIfsInventoryId, ifsInventoryQuantity.getId()));
+        if(Objects.nonNull(ifsPartPropsRecord)){
+            enterFactoryReport.setOuterColor(ifsPartPropsRecord.getOuterColor());
+        }
         enterFactoryReport.setQtyArrived(ifsInventoryQuantity.getQtyArrived() == null ? "" :
                 ifsInventoryQuantity.getQtyArrived().stripTrailingZeros().toPlainString() + ifsInventoryQuantity.getBuyUnitMeas());
         enterFactoryReport.setQuantity(insOrder.getTestQuantity());
         enterFactoryReport.setPartDesc(insOrder.getPartDetail());
-        enterFactoryReport.setSupplierName("**********");
+        enterFactoryReport.setSupplierName(ifsInventoryQuantity.getSupplierName());
         enterFactoryReport.setLotBatchNo(ifsInventoryQuantity.getUpdateBatchNo());
 
         // 妫�娴嬩緷鎹�
@@ -1696,6 +2298,7 @@
         List<RowRenderData> rows = new ArrayList<>();
         List<TextRenderData> text = new ArrayList<>();
         RowRenderData rowRenderData = null;
+        List<Map<String,Object>> cableTagEnclosureTables = new ArrayList<>();
 
         // 鏌ヨ妫�楠屽唴瀹�
         List<SampleProductExportDto> sampleProductDto2s = insOrderMapper.selectSampleBySampleId(insSamples.stream()
@@ -1706,21 +2309,167 @@
 
         List<SampleProductExportDto> sampleList = new ArrayList<>();
         Integer max = insSamples.stream().mapToInt(InsSample::getQuantity).sum();
+        TableRenderData tableRenderData = new TableRenderData();
+        String templateName;
+        if(StringUtils.equals(OrderType.WG.getValue(),ifsInventoryQuantity.getOrderType())){
+            //杩囨护涓嶅垽瀹氱殑妫�娴嬮」
+            List<SampleProductExportDto> filterItems = sampleProductDto2s.stream()
+                    .filter(f -> !showResult || f.getInsResult() != 3)
+                    .collect(Collectors.toList());
+            int maxCableTag = 5;//鍗曚釜琛ㄦ牸锛岀數缂嗛鑹叉爣璇嗘渶澶т釜鏁�
+            templateName = showResult ? "/static/small-wg-report-template.docx" : "/static/small-wg-detection-template.docx";
+            //鏌ヨ妫�楠屽崟娑堟伅
+            InsSampleUserVO insSampleUser = insSampleUserMapper.selectUserNameByOrderId(orderId);
+            if(Objects.nonNull(insSampleUser)){
+                enterFactoryReport.setPartDesc(insSampleUser.getModel());
+                enterFactoryReport.setInspector(insSampleUser.getInspector());
+                enterFactoryReport.setInspectDate(insSampleUser.getInspectDate());
+            }
 
-        // 杞垚Mpa杩涜鎺掑簭
-        Map<String, List<SampleProductExportDto>> sortedMap = sampleProductDto2s.stream()
-                .filter(sampleProductDto2 -> StringUtils.isNotBlank(sampleProductDto2.getInspectionItem()))
-                .collect(Collectors.groupingBy(SampleProductExportDto::getInspectionItem));
-        List<Map.Entry<String, List<SampleProductExportDto>>> entries = new ArrayList<>(sortedMap.entrySet());
-        entries.sort((o1, o2) -> (o1.getValue().get(0).getSort() == null ? 0 : o1.getValue().get(0).getSort())
-                - (o2.getValue().get(0).getSort() == null ? 0 : o2.getValue().get(0).getSort()));
-        // 鍒涘缓涓�涓� LinkedHashMap 鏉ヤ繚鎸佹彃鍏ラ『搴�
-        Map<String, List<SampleProductExportDto>> item = new LinkedHashMap<>();
-        for (Map.Entry<String, List<SampleProductExportDto>> entry : entries) {
-            item.put(entry.getKey(), entry.getValue());
+            Map<String, List<SampleProductExportDto>> totalItem = new LinkedHashMap<>();//妫�娴嬮」鍒楄〃
+            Map<String, List<SampleProductExportDto>> cableTagItem = new LinkedHashMap<>();//鐢电紗閰嶇疆妫�娴嬮」
+            Map<String, List<SampleProductExportDto>> cableTagEnclosureItem = new LinkedHashMap<>();//鐢电紗閰嶇疆妫�娴嬮」闄勪欢
+
+            AtomicInteger finalIndex = new AtomicInteger(1);
+            List<String> cableTags = insOrderMapper.selectSampleCableTag(insSample.getId());
+            max = Math.max(cableTags.size(),1);
+            //澶勭悊鐢电紗閰嶇疆妫�娴嬮」
+            Map<String, List<SampleProductExportDto>> tempMap = new HashMap<>();
+            Map<String, List<SampleProductExportDto>> tempMap2 = new HashMap<>();
+            Map<String, List<SampleProductExportDto>> listMap2 = filterItems.stream()
+                    .filter(f -> StringUtils.isNotBlank(f.getCableTag()) && StringUtils.isNotBlank(f.getInspectionItem()))
+                    .collect(Collectors.groupingBy(SampleProductExportDto::getInspectionItem));
+            for (String key : listMap2.keySet()) {
+                List<SampleProductExportDto> sampleProductExportDtos;
+                List<SampleProductExportDto> sampleProductExportDtos2;
+                //澶勭悊鐢电紗閰嶇疆椤�
+                Map<String, List<SampleProductExportDto>> collect = listMap2.get(key).stream().collect(Collectors.groupingBy(SampleProductExportDto::getInspectionItemSubclass));
+                if(cableTags.size()>maxCableTag){
+                    sampleProductExportDtos = transformSampleProduct(cableTags,collect,0,maxCableTag);
+                    sampleProductExportDtos2 = transformSampleProduct(cableTags,collect,maxCableTag,cableTags.size());
+                    tempMap2.put(key,sampleProductExportDtos2);
+                }else{
+                    sampleProductExportDtos = transformSampleProduct(cableTags,collect,0,cableTags.size());
+                }
+                cableTagItem.put(key,sampleProductExportDtos);
+            }
+            //澶勭悊闈炵數缂嗛厤缃娴嬮」
+            Map<String, List<SampleProductExportDto>> listMap = filterItems.stream()
+                    .filter(f -> StringUtils.isBlank(f.getCableTag()) && StringUtils.isNotBlank(f.getInspectionItem()))
+                    .collect(Collectors.groupingBy(s->s.getInspectionItem()+"&"));
+            //鍚堝苟妫�娴嬮」鍒楄〃
+            tempMap.putAll(cableTagItem);
+            tempMap.putAll(listMap);
+            sortSampleProduct(tempMap,totalItem);
+            int tagNum = Math.min(max,maxCableTag);
+            List<String> tagList = cableTags.isEmpty()?new ArrayList<>():cableTags.subList(0,tagNum);
+            handlerSampleItems(OrderType.WG.getValue(), totalItem, finalIndex, sampleList, tagNum, text, rows, rowRenderData, resultCh, tagList, true, showResult);
+
+            if(CollectionUtil.isNotEmpty(tempMap2)){
+                sortSampleProduct(tempMap2,cableTagEnclosureItem);
+                //鐢熸垚闄勪欢鐢电紗琛ㄦ牸
+                TableRenderData tableRenderData2 = new TableRenderData();
+                List<String> newCableTags = cableTags.subList(maxCableTag,cableTags.size());
+                AtomicInteger finalIndex2 = new AtomicInteger(1);
+                List<TextRenderData> newText = new ArrayList<TextRenderData>();
+                List<RowRenderData> newRows = new ArrayList<>();
+                RowRenderData newRowRenderData = null;
+                handlerSampleItems(OrderType.WG.getValue(), cableTagEnclosureItem, finalIndex2, new ArrayList<>(), newCableTags.size(), newText, newRows, newRowRenderData, resultCh, newCableTags, true, showResult);
+                tableRenderData2.setRows(newRows);
+            tableRenderData2.setTableStyle(setTableStyle(newCableTags.size(), showResult));
+                HashMap<String, Object> tableMap = new HashMap<>();
+                tableMap.put("enclosureTable",tableRenderData2);
+                tableMap.put("resultCh", resultCh);
+                tableMap.put("writeUrl", null);
+                tableMap.put("examineUrl", null);
+                tableMap.put("ratifyUrl", null);
+                tableMap.put("writeDateUrl", null);
+                tableMap.put("examineDateUrl", null);
+                tableMap.put("ratifyDateUrl", null);
+                tableMap.put("seal1", null);
+                cableTagEnclosureTables.add(tableMap);
+            }
+
+            tableRenderData.setRows(rows);
+            tableRenderData.setTableStyle(setTableStyle(tagNum, showResult));
+            if (showResult && !resultCh.get().isEmpty()) {
+                resultCh.set("缁忔楠岋紝" + resultCh.get() + "鎵�妫�椤圭洰涓嶅悎鏍硷紝鍏朵綑鎵�妫�椤圭洰鍧囧悎鏍笺�傦紙鐩栫珷鏈夋晥锛�");
+            } else if (showResult) {
+                resultCh.set("鏈骇鍝佺鍚堢浉鍏虫爣鍑嗚姹傦紝缁忔楠屽悎鏍煎噯浜堝嚭鍘傦紙鐩栫珷鏈夋晥锛�");
+            }
+
+        }else{
+            templateName = showResult ? "/static/small-report-template.docx" : "/static/small-detection-template.docx";
+            // 杞垚Mpa杩涜鎺掑簭
+            Map<String, List<SampleProductExportDto>> sortedMap = sampleProductDto2s.stream()
+                    .filter(sampleProductDto2 -> StringUtils.isNotBlank(sampleProductDto2.getInspectionItem()))
+                    .collect(Collectors.groupingBy(SampleProductExportDto::getInspectionItem));
+//            // 鍒涘缓涓�涓� LinkedHashMap 鏉ヤ繚鎸佹彃鍏ラ『搴�
+            Map<String, List<SampleProductExportDto>> item = new LinkedHashMap<>();
+            sortSampleProduct(sortedMap,item);
+
+
+            AtomicInteger finalIndex = new AtomicInteger(1);
+            handlerSampleItems(OrderType.RAW.getValue(), item, finalIndex, sampleList, max, text, rows, rowRenderData, resultCh, null, true, showResult);
+            tableRenderData.setRows(rows);
+            tableRenderData.setTableStyle(setTableStyle(max, showResult));
+
+            if (showResult && !resultCh.get().equals("")) {
+                resultCh.set("缁忔楠岋紝" + resultCh.get() + "鎵�妫�椤圭洰涓嶅悎鏍硷紝鍏朵綑鎵�妫�椤圭洰鍧囧悎鏍笺��");
+            } else if (showResult) {
+                resultCh.set("缁忔楠屾鎵�" + enterFactoryReport.getSample() + "鍚勯」鐩潎绗﹀悎妫�楠岃鑼冭姹傘��");
+            }
         }
 
-        AtomicInteger finalIndex = new AtomicInteger(1);
+        ConfigureBuilder builder = Configure.builder();
+        builder.useSpringEL(true);
+
+        InputStream inputStream = this.getClass().getResourceAsStream(templateName);
+        XWPFTemplate template = XWPFTemplate.compile(inputStream, builder.build()).render(
+                new HashMap<String, Object>() {{
+                    put("report", enterFactoryReport);
+                    put("standardMethod", standardMethod2.toString().equals("null") ? "" : standardMethod2);
+                    put("orderType", orderType);
+                    put("table", tableRenderData);
+                    put("enclosureTables", cableTagEnclosureTables.isEmpty()?null:cableTagEnclosureTables);
+                    put("resultCh", resultCh);
+                    put("writeUrl", null);
+                    put("examineUrl", null);
+                    put("ratifyUrl", null);
+                    put("writeDateUrl", null);
+                    put("examineDateUrl", null);
+                    put("ratifyDateUrl", null);
+                    put("seal1", null);
+                }});
+        try {
+            // 淇敼鎹㈣鍜屽悎骞堕棶棰�
+            updaeMerge(template.getXWPFDocument(), true);
+            String name = insReport.getCode().replace("/", "") + (showResult ? "-J.docx" : "-C.docx");
+            Files.createDirectories(Paths.get(wordUrl));
+            template.writeAndClose(Files.newOutputStream(Paths.get(wordUrl, name)));
+            insReport.setUrl("/word/" + name);
+            insReport.setIsPass(0);
+            insReport.setWriteUserId(writeUserId);//缂栧埗浜猴紙妫�楠屼汉锛�
+            insReport.setWriteTime(LocalDateTime.now());//鎻愪氦鏃堕棿
+            saveGeneratedReport(insReport);
+            inputStream.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 澶勭悊甯歌妫�娴嬮」
+     * @param item
+     * @param finalIndex
+     * @param sampleList
+     * @param max
+     * @param text
+     * @param rows
+     * @param rowRenderData
+     * @param resultCh
+     */
+    private static void handlerSampleItems(String orderType, Map<String, List<SampleProductExportDto>> item, AtomicInteger finalIndex, List<SampleProductExportDto> sampleList, Integer max, List<TextRenderData> text, List<RowRenderData> rows, RowRenderData rowRenderData, AtomicReference<String> resultCh, List<String> cableTagList, Boolean hasAddHead, boolean showResult) {
         item.forEach((s, sampleProductDtoInside) -> {
             // 娣诲姞妫�楠岄」
             SampleProductExportDto dto2 = new SampleProductExportDto();
@@ -1733,19 +2482,23 @@
                 // 澶勭悊闆嗗悎
                 Map<String, SampleProductExportDto> map = new LinkedHashMap<>();
                 for (SampleProductExportDto productDto2 : sampleProductDtoInside) {
-                    String productName = productDto2.getInspectionItemClass() + productDto2.getInspectionItem();
+                    String productName = productDto2.getInspectionItemClass() + productDto2.getInspectionItem() + productDto2.getCableTag();
                     if (map.containsKey(productName)) {
                         // 濡傛灉鍚嶇О宸茬粡瀛樺湪锛屾坊鍔� lastValue 鍊煎埌 lastValueList 鍒楄〃
-                        map.get(productName)
-                                .getLastValueList()
-                                .add(productDto2.getLastValue());
+                        if(CollectionUtil.isEmpty(map.get(productName).getLastValueList()) || StringUtils.equals(OrderType.RAW.getValue(),orderType)){
+                            map.get(productName)
+                                    .getLastValueList()
+                                    .add(productDto2.getLastValue());
+                        }
                         map.get(productName)
                                 .getInsResultList()
                                 .add(productDto2.getInsResult());
                     } else {
                         // 濡傛灉鍚嶇О涓嶅瓨鍦紝鐩存帴鏀惧叆 map
-                        productDto2.setLastValueList(new ArrayList<>()); // 妫�楠屽唴瀹�
-                        productDto2.getLastValueList().add(productDto2.getLastValue());
+                        if(CollectionUtil.isEmpty(productDto2.getLastValueList()) || StringUtils.equals(OrderType.RAW.getValue(),orderType)){
+                            productDto2.setLastValueList(new ArrayList<>()); // 妫�楠屽唴瀹�
+                            productDto2.getLastValueList().add(productDto2.getLastValue());
+                        }
                         productDto2.setInsResultList(new ArrayList<>()); // 缁撴灉
                         productDto2.getInsResultList().add(productDto2.getInsResult());
 
@@ -1774,19 +2527,23 @@
                 // 澶勭悊闆嗗悎
                 Map<String, SampleProductExportDto> map = new LinkedHashMap<>();
                 for (SampleProductExportDto productDto2 : sampleProductDtoInside) {
-                    String productName = productDto2.getInspectionItemClass() + productDto2.getInspectionItem() + productDto2.getInspectionItemSubclass();
+                    String productName = productDto2.getInspectionItemClass() + productDto2.getInspectionItem() + productDto2.getInspectionItemSubclass() + productDto2.getCableTag();
                     if (map.containsKey(productName)) {
                         // 濡傛灉鍚嶇О宸茬粡瀛樺湪锛屾坊鍔� lastValue 鍊煎埌 lastValueList 鍒楄〃
-                        map.get(productName)
-                                .getLastValueList()
-                                .add(productDto2.getLastValue());
+                        if(CollectionUtil.isEmpty(map.get(productName).getLastValueList()) || StringUtils.equals(OrderType.RAW.getValue(),orderType)){
+                            map.get(productName)
+                                    .getLastValueList()
+                                    .add(productDto2.getLastValue());
+                        }
                         map.get(productName)
                                 .getInsResultList()
                                 .add(productDto2.getInsResult());
                     } else {
                         // 濡傛灉鍚嶇О涓嶅瓨鍦紝鐩存帴鏀惧叆 map
-                        productDto2.setLastValueList(new ArrayList<>()); // 妫�楠屽唴瀹�
-                        productDto2.getLastValueList().add(productDto2.getLastValue());
+                        if(CollectionUtil.isEmpty(productDto2.getLastValueList()) || StringUtils.equals(OrderType.RAW.getValue(),orderType)){
+                            productDto2.setLastValueList(new ArrayList<>()); // 妫�楠屽唴瀹�
+                            productDto2.getLastValueList().add(productDto2.getLastValue());
+                        }
                         productDto2.setInsResultList(new ArrayList<>()); // 缁撴灉
                         productDto2.getInsResultList().add(productDto2.getInsResult());
 
@@ -1804,8 +2561,9 @@
         });
 
         // 娣诲姞灏忔姤鍛婅〃澶�
-        text = addSmallHead(text, max, rows);
-
+        if(hasAddHead){
+            text = addSmallHead(text, max, rows, cableTagList, showResult);
+        }
 
         // 涓棿妫�娴嬪�兼坊鍔�
         for (int i = 0; i < sampleList.size(); i++) {
@@ -1822,7 +2580,9 @@
 
             // 妫�楠岄」鐩�
             TextRenderData middleRenderData2 = new TextRenderData();
-            middleRenderData2.setText(sample.getInspectionName());
+            String[] split = sample.getInspectionName().split("&");
+            String itemName = split.length>0?split[0]:sample.getInspectionName();
+            middleRenderData2.setText(itemName+"鈭�"+itemName+i+"_"+finalIndex);
             Style middleStyle2 = new Style();
             middleStyle2.setFontFamily("瀹嬩綋");
             middleStyle2.setColor("000000");
@@ -1852,21 +2612,21 @@
             if (CollectionUtils.isNotEmpty(sample.getLastValueList())
                     && sample.getLastValueList().size() == max) {
                 // 鍒ゆ柇鏄惁鏄瑙�, 澶栬鍏ㄩ儴鍚堟牸鐨勮瘽闇�瑕佸悎骞�
-                if (sample.getInspectionItem().contains("澶栬")) {
+                if (showResult && sample.getInspectionItem().contains("澶栬")) {
                     // 鍒ゅ畾缁撴灉
                     boolean falg = false;
                     if (CollectionUtils.isNotEmpty(sample.getLastValueList())) {
                         // 鍒ゆ柇鏄惁鏈変竴涓敊璇�
-                        if (sample.getInsResultList().stream().anyMatch(s -> s.equals(2))) {
+                        if (sample.getInsResultList().stream().anyMatch(s -> Objects.equals(s, 2))) {
                             falg = true;
                         } else {
-                            boolean error = sample.getInsResultList().stream().anyMatch(s -> s.equals(0));
+                            boolean error = sample.getInsResultList().stream().anyMatch(s -> Objects.equals(s, 0));
                             if (!error) {
                                 falg = true;
                             }
                         }
                     } else {
-                        if (!sample.getInsResult().equals(2)) {
+                        if (!Objects.equals(sample.getInsResult(), 2)) {
                             falg = true;
                         }
                     }
@@ -1909,7 +2669,7 @@
                     TextRenderData middleRenderData6 = new TextRenderData();
                     middleRenderData6.setText((StringUtils.isNotEmpty(sample.getLastValue()) ?
                             sample.getLastValue() : "")
-                            + "鈭�" + (7 + i));
+                            + "鈭�" + (finalIndex.get() +"_"+ i));
                     Style middleStyle6 = new Style();
                     middleStyle6.setFontFamily("瀹嬩綋");
                     middleStyle6.setColor("000000");
@@ -1921,7 +2681,7 @@
 
             // 鍒ゅ畾缁撴灉
             String result = "";
-            if (sample.getInsResult() != null) {
+            if (showResult && sample.getInsResult() != null) {
                 switch (sample.getInsResult()) {
                     case 1:
                         result = "鈭�";
@@ -1934,20 +2694,20 @@
                         break;
                 }
             }
-            if (CollectionUtils.isNotEmpty(sample.getLastValueList())) {
+            if (showResult && CollectionUtils.isNotEmpty(sample.getLastValueList())) {
                 // 鍒ゆ柇鏄惁鏈変竴涓敊璇�
-                if (sample.getInsResultList().stream().anyMatch(s -> s.equals(3))) {
+                if (sample.getInsResultList().stream().anyMatch(s -> Objects.equals(s, 3))) {
                     result = "-";
                 } else {
-                    boolean error = sample.getInsResultList().stream().anyMatch(s -> s.equals(0));
+                    boolean error = sample.getInsResultList().stream().anyMatch(s -> Objects.equals(s, 0));
                     if (error) {
                         List<String> collect = new ArrayList<>();
                         int index = 1;
                         for (Integer count : sample.getInsResultList()) {
                             String type;
-                            if (count.equals(0)) {
+                            if (Objects.equals(count, 0)) {
                                 // 娣诲姞涓嶅悎鏍兼弿杩�
-                                String item1 = (max == 1 ? "" : "绗�" + Integer.toString(index) + "娆�")
+                                String item1 = (max == 1 ? "" : "绗�" + index + "娆�")
                                         + sample.getInspectionItem()
                                         + (StringUtils.isBlank(sample.getInspectionItemSubclass()) ? "" : "" + sample.getInspectionItemSubclass());
                                 if (resultCh.get().equals("")) {
@@ -1969,6 +2729,7 @@
                 }
             }
 
+            if (showResult) {
             TextRenderData middleRenderData7 = new TextRenderData();
             middleRenderData7.setText(result);
             Style middleStyle7 = new Style();
@@ -1976,6 +2737,7 @@
             middleStyle7.setColor("000000");
             middleRenderData7.setStyle(middleStyle7);
             text.add(middleRenderData7);
+            }
 
             TextRenderData[] text2 = text.toArray(new TextRenderData[0]);
             rowRenderData = Rows.of(text2).center().rowAtleastHeight(1).create();
@@ -1987,95 +2749,16 @@
             text = new ArrayList<>();
         }
 
-        TableRenderData tableRenderData = new TableRenderData();
-        tableRenderData.setRows(rows);
-
-        //璁剧疆鏍峰紡
-        TableStyle tableStyle = new TableStyle();
-        for (int i = 1; i <= max; i++) {
-            // 鏍规嵁鍑忓帇閭g粨鏋滀釜鏁颁慨鏀归暱搴�
-            switch (i) {
-                case 1:
-                    tableStyle.setColWidths(new int[]{650, 2900, 850, 2300, 2100, 1200});
-                    break;
-                case 2:
-                    tableStyle.setColWidths(new int[]{650, 2700, 850, 2200, 1200, 1200, 1200});
-                    break;
-                case 3:
-                    tableStyle.setColWidths(new int[]{650, 2700, 850, 1600, 1000, 1000, 1000, 1200});
-                    break;
-                case 4:
-                    tableStyle.setColWidths(new int[]{650, 2400, 850, 1500, 850, 850, 850, 850, 1200});
-                    break;
-                case 5:
-                    tableStyle.setColWidths(new int[]{650, 2200, 850, 1350, 750, 750, 750, 750, 750, 1200});
-                    break;
-            }
-        }
-        tableStyle.setWidth("10000");
-        tableStyle.setAlign(TableRowAlign.CENTER);
-        BorderStyle borderStyle = new BorderStyle();
-        borderStyle.setColor("000000");
-        borderStyle.setType(XWPFTable.XWPFBorderType.SINGLE);
-        borderStyle.setSize(4);
-        tableStyle.setLeftBorder(borderStyle);
-        tableStyle.setRightBorder(borderStyle);
-        tableStyle.setInsideHBorder(borderStyle); // 璁剧疆姘村钩鍐呰竟妗�
-        tableStyle.setInsideVBorder(borderStyle);
-        tableRenderData.setTableStyle(tableStyle);
-
-        if (!resultCh.get().equals("")) {
-            resultCh.set("缁忔楠岋紝" + resultCh.get() + "鎵�妫�椤圭洰涓嶅悎鏍硷紝鍏朵綑鎵�妫�椤圭洰鍧囧悎鏍笺��");
-        } else {
-            resultCh.set("缁忔楠屾鎵�" + enterFactoryReport.getSample() + "鍚勯」鐩潎绗﹀悎妫�楠岃鑼冭姹傘��");
-        }
-
-        ConfigureBuilder builder = Configure.builder();
-        builder.useSpringEL(true);
-
-        InputStream inputStream = this.getClass().getResourceAsStream("/static/small-report-template.docx");
-        XWPFTemplate template = XWPFTemplate.compile(inputStream, builder.build()).render(
-                new HashMap<String, Object>() {{
-                    put("report", enterFactoryReport);
-                    put("standardMethod", standardMethod2.toString().equals("null") ? "" : standardMethod2);
-                    put("orderType", orderType);
-                    put("table", tableRenderData);
-                    put("resultCh", resultCh);
-                    put("writeUrl", null);
-                    put("examineUrl", null);
-                    put("ratifyUrl", null);
-                    put("writeDateUrl", null);
-                    put("examineDateUrl", null);
-                    put("ratifyDateUrl", null);
-                    put("seal1", null);
-                }});
-        try {
-            // 淇敼鎹㈣鍜屽悎骞堕棶棰�
-            updaeMerge(template.getXWPFDocument(), true);
-            String name = insReport.getCode().replace("/", "") + "-J.docx";
-            template.writeAndClose(Files.newOutputStream(Paths.get(wordUrl + "/" + name)));
-            insReport.setUrl("/word/" + name);
-            insReport.setIsPass(0);
-            insReport.setWriteUserId(SecurityUtils.getUserId().intValue());//鎻愪氦浜�
-            insReport.setWriteTime(LocalDateTime.now());//鎻愪氦鏃堕棿
-            // 鏌ヨ鎶ュ憡, 鍒ゆ柇涔嬪墠鏄惁娣诲姞杩�, 娣诲姞杩囧垹闄�
-            insReportMapper.delete(Wrappers.<InsReport>lambdaQuery()
-                    .eq(InsReport::getInsOrderId, insOrder.getId()));
-            insReportMapper.insert(insReport);
-
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
     }
 
     /**
-     * 娣诲姞灏忓疂琛ㄥご
+     * 娣诲姞灏忔姤鍛婅〃澶�
      * @param text
      * @param max
      * @param rows
      * @return
      */
-    private static List<TextRenderData> addSmallHead(List<TextRenderData> text, Integer max, List<RowRenderData> rows) {
+    private static List<TextRenderData> addSmallHead(List<TextRenderData> text, Integer max, List<RowRenderData> rows, List<String> cableTagList, boolean showResult) {
         RowRenderData rowRenderData;
 //        // 澶�
         TextRenderData headRenderData1 = new TextRenderData();
@@ -2112,13 +2795,14 @@
 
         for (int i = 0; i < max; i++) {
             TextRenderData headRenderData6 = new TextRenderData();
-            headRenderData6.setText("妫�楠岀粨鏋溾垜6");
+            headRenderData6.setText(showResult ? "妫�楠岀粨鏋溾垜6" : "妫�娴嬫暟鎹垜6");
             Style headStyle6 = new Style();
             headStyle6.setFontFamily("瀹嬩綋");
             headStyle6.setColor("000000");
             headRenderData6.setStyle(headStyle6);
             text.add(headRenderData6);
         }
+        if (showResult) {
         TextRenderData headRenderData7 = new TextRenderData();
         headRenderData7.setText("鍗曢」鍒ゆ柇");
         Style headStyle7 = new Style();
@@ -2126,6 +2810,7 @@
         headStyle7.setColor("000000");
         headRenderData7.setStyle(headStyle7);
         text.add(headRenderData7);
+        }
 
         TextRenderData[] text3 = text.toArray(new TextRenderData[0]);
         rowRenderData = Rows.of(text3).center().rowAtleastHeight(1).create();
@@ -2133,7 +2818,7 @@
         text = new ArrayList<>();
 
         // 绗簩琛�(鍙兘娌℃湁)
-        if (max > 1) {
+        if (max > 1 && CollectionUtil.isEmpty(cableTagList)) {
             TextRenderData tagRenderData1 = new TextRenderData();
             tagRenderData1.setText("");
             Style tagStyle1 = new Style();
@@ -2175,6 +2860,7 @@
                 tagRenderData6.setStyle(tagStyle6);
                 text.add(tagRenderData6);
             }
+            if (showResult) {
             TextRenderData tagRenderData7 = new TextRenderData();
             tagRenderData7.setText("");
             Style tagStyle7 = new Style();
@@ -2182,6 +2868,7 @@
             tagStyle7.setColor("000000");
             tagRenderData7.setStyle(tagStyle7);
             text.add(tagRenderData7);
+            }
 
             TextRenderData[] text4 = text.toArray(new TextRenderData[0]);
             rowRenderData = Rows.of(text4).center().rowAtleastHeight(1).create();
@@ -2190,7 +2877,64 @@
 
 
         }
+        //濡傛灉鏈夌數缂嗛鑹诧紝鐢熸垚棰滆壊鏍囪瘑琛�
+        if(CollectionUtil.isNotEmpty(cableTagList)){
+            TextRenderData tagRenderData1 = new TextRenderData();
+            tagRenderData1.setText("");
+            Style tagStyle1 = new Style();
+            tagStyle1.setFontFamily("瀹嬩綋");
+            tagStyle1.setColor("000000");
+            tagRenderData1.setStyle(tagStyle1);
+            text.add(tagRenderData1);
 
+            TextRenderData tagRenderData2 = new TextRenderData();
+            tagRenderData2.setText("缁濈紭绾胯姱棰滆壊鍜屾爣蹇�");
+            Style tagStyle2 = new Style();
+            tagStyle2.setFontFamily("瀹嬩綋");
+            tagStyle2.setColor("000000");
+            tagRenderData2.setStyle(tagStyle2);
+            text.add(tagRenderData2);
+
+            TextRenderData tagRenderData4 = new TextRenderData();
+            tagRenderData4.setText("/");
+            Style tagStyle4 = new Style();
+            tagStyle4.setFontFamily("瀹嬩綋");
+            tagStyle4.setColor("000000");
+            tagRenderData4.setStyle(tagStyle4);
+            text.add(tagRenderData4);
+
+            TextRenderData tagRenderData5 = new TextRenderData();
+            tagRenderData5.setText("/");
+            Style tagStyle5 = new Style();
+            tagStyle5.setFontFamily("瀹嬩綋");
+            tagStyle5.setColor("000000");
+            tagRenderData5.setStyle(tagStyle5);
+            text.add(tagRenderData5);
+
+            for (String cableTag : cableTagList) {
+                TextRenderData tagRenderData6 = new TextRenderData();
+                tagRenderData6.setText(cableTag);
+                Style tagStyle6 = new Style();
+                tagStyle6.setFontFamily("瀹嬩綋");
+                tagStyle6.setColor("000000");
+                tagRenderData6.setStyle(tagStyle6);
+                text.add(tagRenderData6);
+            }
+            if (showResult) {
+            TextRenderData tagRenderData7 = new TextRenderData();
+            tagRenderData7.setText("/");
+            Style tagStyle7 = new Style();
+            tagStyle7.setFontFamily("瀹嬩綋");
+            tagStyle7.setColor("000000");
+            tagRenderData7.setStyle(tagStyle7);
+            text.add(tagRenderData7);
+            }
+
+            TextRenderData[] text4 = text.toArray(new TextRenderData[0]);
+            rowRenderData = Rows.of(text4).center().rowAtleastHeight(1).create();
+            rows.add(rowRenderData);
+            text = new ArrayList<>();
+        }
         return text;
     }
 
@@ -2202,13 +2946,14 @@
      * @param insOrder
      * @param
      */
-    private void addBitReport(Integer orderId, InsOrder insOrder) {
-        Map<String, String> user = insProductMapper.selectUserById(insOrder.getUserId());
+    private void addBitReport(Integer orderId, InsOrder insOrder, Integer reportType, Integer writeUserId) {
         //samples鏄笉鍖呮嫭甯︽湁"/"鐨勬牱鍝�
         List<SampleProductDto> samples = insSampleMapper.selectSampleProductListByOrderId(orderId);
         InsReport insReport = new InsReport();
         insReport.setCode(insOrder.getEntrustCode());
         insReport.setInsOrderId(orderId);
+        insReport.setReportType(reportType);
+        boolean showResult = Objects.equals(reportType, INSPECTION_REPORT);
         List<Map<String, Object>> tables = new ArrayList<>();
         Set<String> standardMethod = new HashSet<>();
         Set<String> deviceSet = new HashSet<>();
@@ -2219,10 +2964,9 @@
         List<String> resultChList = new ArrayList<>();
         List<String> resultEnList = new ArrayList<>();
         // 鍒ゆ柇鏄惁鏄彧鏈変竴涓牱鍝�
-        boolean isOneSample = samples.size() == 1 ? true : false;
+        boolean isOneSample = samples.size() == 1;
         /*鍩虹鎶ュ憡(鏍规嵁缁樺埗鐨勫師濮嬭褰曟ā鐗堝舰鎴�)*/
         samples.forEach(a -> {
-            Map<Integer, String> map2 = new HashMap<>();
             models.add(a.getModel());
             String standardMethodCode = baseMapper.getStandardMethodCode(a.getStandardMethodListId());
             if (StrUtil.isNotBlank(a.getSpecialStandardMethod())) {
@@ -2239,6 +2983,11 @@
                         }
                     }
                 }
+            }
+            // 鏂扮増妫�娴嬫姤鍛婄洿鎺ヤ娇鐢ㄥ浐瀹氬洓鍒楃粨鏋滆锛屼笉鍐嶆瀯閫犳棫鐗堝彲鍙樺垪 TableRenderData銆�
+            // 妫�楠屾姤鍛婁粛娌跨敤涓嬫柟鍘熸湁鐨勫ぇ琛ㄦ牸閫昏緫銆�
+            if (!showResult) {
+                return;
             }
             // 鏀舵牱鏃ユ湡
             List<RowRenderData> rows = new ArrayList<>();
@@ -2286,12 +3035,16 @@
                         }
                     }
                 }
-                insOrder.setSampleView(insOrder.getSample());
-                String sampleViewEn = insSampleMapper.getSampleEn(insOrder.getSample());
-                if (StringUtils.isBlank(sampleViewEn)) {
-                    sampleViewEn = insSampleMapper.getSampleEnByObject(insOrder.getSample());
+                if (StringUtils.isBlank(insOrder.getSampleView())) {
+                    insOrder.setSampleView(insOrder.getSample());
                 }
-                insOrder.setSampleViewEn(sampleViewEn);
+                if (StringUtils.isBlank(insOrder.getSampleViewEn())) {
+                    String sampleViewEn = insSampleMapper.getSampleEn(insOrder.getSample());
+                    if (StringUtils.isBlank(sampleViewEn)) {
+                        sampleViewEn = insSampleMapper.getSampleEnByObject(insOrder.getSample());
+                    }
+                    insOrder.setSampleViewEn(sampleViewEn);
+                }
             } else {
                 // 鑾峰緱鎵归噺妫�楠岀殑鎬绘暟
                 max = insOrderMapper.selectSampleMax(a.getId());
@@ -2299,15 +3052,15 @@
             }
 
             // 琛ㄥご娣诲姞
-            addHead(a, text, rowRenderData, rows, max, cableTags);
+            addHead(a, text, rowRenderData, rows, max, cableTags, showResult);
             text = new ArrayList<>();
 
             // 娣诲姞妫�娴嬪��
-            productSize.set(addTestValue(a, text, rowRenderData, rows, max, resultChList, resultEnList, insSamples, cableTags, isOneSample));
+            productSize.set(addTestValue(a, text, rowRenderData, rows, max, resultChList, resultEnList, insSamples, cableTags, isOneSample, showResult));
             text = new ArrayList<>();
 
             // 缁撳熬娣诲姞
-            addEnding(text, rowRenderData, rows, max);
+            addEnding(text, rowRenderData, rows, max, showResult);
             text = new ArrayList<>();
 
             List<TableRenderData> tables1 = new ArrayList<>();
@@ -2338,26 +3091,27 @@
                     newTableRenderData.setRows(new ArrayList<>(firstTwoRows));
                     //璁剧疆鏍峰紡
                     TableStyle tableStyle = new TableStyle();
-                    for (int i = 1; i <= max; i++) {
-                        // 鏍规嵁鍑忓帇閭g粨鏋滀釜鏁颁慨鏀归暱搴�
-                        switch (i) {
-                            case 1:
-                                tableStyle.setColWidths(new int[]{650, 2000, 2000, 850, 2200, 2100, 1200});
-                                break;
-                            case 2:
-                                tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 2100, 1200, 1200, 1200});
-                                break;
-                            case 3:
-                                tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 1500, 1000, 1000, 1000, 1200});
-                                break;
-                            case 4:
-                                tableStyle.setColWidths(new int[]{650, 1200, 1200, 850, 1400, 850, 850, 850, 850, 1200});
-                                break;
-                            case 5:
-                                tableStyle.setColWidths(new int[]{650, 1100, 1100, 850, 1350, 750, 750, 750, 750, 750, 1200});
-                                break;
-                        }
-                    }
+//                    for (int i = 1; i <= max; i++) {
+//                    }
+                    // 鏍规嵁妫�楠岀粨鏋滀釜鏁颁慨鏀归暱搴�
+                    tableStyle.setColWidths(calcTableColWidths(max, showResult));
+//                    switch (max) {
+//                        case 1:
+//                            tableStyle.setColWidths(new int[]{650, 2000, 2000, 850, 2200, 2100, 1200});
+//                            break;
+//                        case 2:
+//                            tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 2100, 1200, 1200, 1200});
+//                            break;
+//                        case 3:
+//                            tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 1500, 1000, 1000, 1000, 1200});
+//                            break;
+//                        case 4:
+//                            tableStyle.setColWidths(new int[]{650, 1200, 1200, 850, 1400, 850, 850, 850, 850, 1200});
+//                            break;
+//                        case 5:
+//                            tableStyle.setColWidths(new int[]{650, 1100, 1100, 850, 1350, 750, 750, 750, 750, 750, 1200});
+//                            break;
+//                    }
                     tableStyle.setWidth("10000");
                     tableStyle.setAlign(TableRowAlign.CENTER);
                     BorderStyle borderStyle = new BorderStyle();
@@ -2380,42 +3134,43 @@
                 }
                 tableRenderData.getRows().add(row);
             }
-            if (!tableRenderData.getRows().isEmpty() && tableRenderData.getRows().size() != 3) {
+            TableStyle tableStyle = new TableStyle();
+            if (tableRenderData.getRows().size() != 3) {
                 //璁剧疆鏍峰紡
-                TableStyle tableStyle = new TableStyle();
-                for (int i = 1; i <= max; i++) {
-                    // 鏍规嵁鍑忓帇閭g粨鏋滀釜鏁颁慨鏀归暱搴�
-                    switch (i) {
-                        case 1:
-                            tableStyle.setColWidths(new int[]{650, 2000, 2000, 850, 2200, 2100, 1200});
-                            break;
-                        case 2:
-                            tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 2100, 1200, 1200, 1200});
-                            break;
-                        case 3:
-                            tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 1500, 1000, 1000, 1000, 1200});
-                            break;
-                        case 4:
-                            tableStyle.setColWidths(new int[]{650, 1200, 1200, 850, 1400, 850, 850, 850, 850, 1200});
-                            break;
-                        case 5:
-                            tableStyle.setColWidths(new int[]{650, 1100, 1100, 850, 1350, 750, 750, 750, 750, 750, 1200});
-                            break;
-                    }
-                }
-                tableStyle.setWidth("10000");
-                tableStyle.setAlign(TableRowAlign.CENTER);
-                BorderStyle borderStyle = new BorderStyle();
-                borderStyle.setColor("000000");
-                borderStyle.setType(XWPFTable.XWPFBorderType.THICK);
-                borderStyle.setSize(14);
-                tableStyle.setLeftBorder(borderStyle);
-                tableStyle.setTopBorder(borderStyle);
-                tableStyle.setRightBorder(borderStyle);
-                tableStyle.setBottomBorder(borderStyle);
-                tableRenderData.setTableStyle(tableStyle);
-                tables1.add(tableRenderData);
+//                for (int i = 1; i <= max; i++) {
+//                }
+                // 鏍规嵁妫�楠岀粨鏋滀釜鏁颁慨鏀归暱搴�
+                tableStyle.setColWidths(calcTableColWidths(max, showResult));
+//                switch (max) {
+//                    case 1:
+//                        tableStyle.setColWidths(new int[]{650, 2000, 2000, 850, 2200, 2100, 1200});
+//                        break;
+//                    case 2:
+//                        tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 2100, 1200, 1200, 1200});
+//                        break;
+//                    case 3:
+//                        tableStyle.setColWidths(new int[]{650, 1400, 1400, 850, 1500, 1000, 1000, 1000, 1200});
+//                        break;
+//                    case 4:
+//                        tableStyle.setColWidths(new int[]{650, 1200, 1200, 850, 1400, 850, 850, 850, 850, 1200});
+//                        break;
+//                    case 5:
+//                        tableStyle.setColWidths(new int[]{650, 1100, 1100, 850, 1350, 750, 750, 750, 750, 750, 1200});
+//                        break;
+//                }
             }
+            tableStyle.setWidth("10000");
+            tableStyle.setAlign(TableRowAlign.CENTER);
+            BorderStyle borderStyle = new BorderStyle();
+            borderStyle.setColor("000000");
+            borderStyle.setType(XWPFTable.XWPFBorderType.THICK);
+            borderStyle.setSize(14);
+            tableStyle.setLeftBorder(borderStyle);
+            tableStyle.setTopBorder(borderStyle);
+            tableStyle.setRightBorder(borderStyle);
+            tableStyle.setBottomBorder(borderStyle);
+            tableRenderData.setTableStyle(tableStyle);
+            tables1.add(tableRenderData);
             tables1.forEach(table -> {
                 Map<String, Object> tableMap = new HashMap<>();
                 tableMap.put("table", table);
@@ -2429,15 +3184,26 @@
         for (String s : standardMethod) {
             standardMethod2.append("銆�").append(s);
         }
-        standardMethod2.replace(0, 1, "");
+        if (standardMethod2.length() > 0) {
+            standardMethod2.deleteCharAt(0);
+        }
         tables.forEach(table -> {
             table.put("tableSize", tables.size() + 1);
         });
-        // 璁惧淇℃伅
-        List<Map<String, String>> deviceList = null;
-        if (CollectionUtils.isNotEmpty(deviceSet)) {
-            deviceList = insOrderMapper.selectDeviceList(deviceSet);
+        // 鏂拌鍗曟寜妯℃澘閫夋嫨璁惧锛涙棫璁㈠崟娌℃湁妯℃澘璁惧鍏崇郴鏃跺洖閫�鍒拌鍗曠骇璁惧璁板綍銆�
+        Set<String> reportDeviceNumbers = insOrderTemplateDeviceMapper
+                .selectManagementNumbersByOrderId(orderId).stream()
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+        if (reportDeviceNumbers.isEmpty()) {
+            reportDeviceNumbers.addAll(insOrderDeviceRecordMapper.selectDeviceNumber(orderId).stream()
+                    .map(InsOrderDeviceRecordDto::getManagementNumber)
+                    .filter(StringUtils::isNotBlank)
+                    .collect(Collectors.toList()));
         }
+        reportDeviceNumbers.addAll(deviceSet);
+        List<Map<String, String>> deviceList = reportDeviceNumbers.isEmpty()
+                ? new ArrayList<>() : insOrderMapper.selectDeviceList(reportDeviceNumbers);
         if (CollectionUtils.isNotEmpty(deviceList)) {
             int count = 1;
             for (Map<String, String> stringMap : deviceList) {
@@ -2448,7 +3214,7 @@
 
         Map<String, String> codeStr = new HashMap<>();
         codeStr.put("鎶ュ憡缂栧彿", insReport.getCode());
-        codeStr.put("鏍峰搧鍚嶇О", insOrder.getSample());
+        codeStr.put("鏍峰搧鍚嶇О", defaultReportText(insOrder.getSampleView(), insOrder.getSample()));
         codeStr.put("瑙勬牸鍨嬪彿", samples.get(0).getModel());
         codeStr.put("鍙戞斁鏃ユ湡", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
 
@@ -2473,7 +3239,7 @@
         Custom custom = customMapper.selectById(insOrder.getCompanyId());
 
         // 鏌ヨ鍒ゆ柇鏄惁鏈変笉鍒ゅ畾椤圭洰,鍜屽叏閮芥槸鍒ゅ畾椤�
-        int judgeType = insProductMapper.selectNoJudge(insOrder.getId());
+        int judgeType = showResult ? insProductMapper.selectNoJudge(insOrder.getId()) : 0;
         String resultCh = "";
         String resultEn = "";
         for (String reference : resultChList) {
@@ -2533,13 +3299,16 @@
         // 鎶芥牱鏃ユ湡
         // 鎴愬搧鏄娊鏍锋椂闂�
         LocalDateTime sendTime = insOrder.getSendTime();
-        if (insOrder.getTypeSource() != null && insOrder.getTypeSource().equals(1)) {
+        IfsInventoryQuantity reportInventory = null;
+        if (insOrder.getIfsInventoryId() != null) {
+            reportInventory = ifsInventoryQuantityMapper.selectById(insOrder.getIfsInventoryId());
+        }
+        if (insOrder.getTypeSource() != null && insOrder.getTypeSource().equals(1) && reportInventory != null) {
             // 鍘熸潗鏂欐敹鏍锋棩鏈熸槸鎶ユ鏃ユ湡
-            IfsInventoryQuantity ifsInventoryQuantity = ifsInventoryQuantityMapper.selectById(insOrder.getIfsInventoryId());
-            sendTime = ifsInventoryQuantity.getDeclareDate();
+            sendTime = reportInventory.getDeclareDate();
         }
 
-        // 妫�楠屾椂闂�  鎶芥牱鏃堕棿-鎻愪氦鏃堕棿
+        // 妫�娴嬫棩鏈燂細棣栨淇濆瓨妯℃澘鍊兼椂闂�-棣栨鎻愪氦鏃堕棿
         LocalDateTime now = LocalDateTime.now();
         // 鎻愪氦鏃堕棿
         LocalDateTime submitTime = LocalDateTime.now();
@@ -2548,15 +3317,20 @@
             submitTime = insOrder.getFirstSubmitDate();
         }
 
-        String insTime = insOrder.getSendTime().format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")) + "-"
+        LocalDateTime firstInspectDate = insOrder.getFirstInspectDate();
+        // 瀛楁涓婄嚎鍓嶇殑鍘嗗彶璁㈠崟娌跨敤鍘熸潵鐨勪笅鍙戞椂闂达紝閬垮厤鏀瑰彉鏃㈡湁鎶ュ憡鍙e緞銆�
+        if (firstInspectDate == null) {
+            firstInspectDate = insOrder.getSendTime();
+        }
+
+        String insTime = firstInspectDate.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")) + "-"
                 + submitTime.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�"));
 
-        String insTimeEn = monthNames[insOrder.getSendTime().getMonthValue() - 1] + " " + insOrder.getSendTime().format(DateTimeFormatter.ofPattern("dd, yyyy")) + "-"
+        String insTimeEn = monthNames[firstInspectDate.getMonthValue() - 1] + " " + firstInspectDate.format(DateTimeFormatter.ofPattern("dd, yyyy")) + "-"
                 + monthNames[submitTime.getMonthValue() - 1] + " " + submitTime.format(DateTimeFormatter.ofPattern("dd, yyyy"));
 
-        //妫�楠岄」鐩殑鐜
-        String environment = "";
-        environment = (ObjectUtils.isNotEmpty(insOrder.getTemperature()) ? insOrder.getTemperature() + "鈩� " : "") + (ObjectUtils.isNotEmpty(insOrder.getHumidity()) ? insOrder.getHumidity() + "%" : "");
+        // 妫�楠岀幆澧冿細浼樺厛姹囨�诲悇妯℃澘濉啓鐨勬俯婀垮害锛屾姤鍛婂睍绀哄叏閮ㄦā鏉跨殑鏈�灏忓�煎埌鏈�澶у�笺��
+        String environment = buildReportEnvironment(orderId, insOrder);
         String finalEnvironment = environment;
         LocalDateTime finalSendTime = sendTime;
         String finalResultCh = resultCh;
@@ -2565,12 +3339,85 @@
         List<Map<String, String>> finalDeviceList = deviceList;
         String finalModelStr = modelStr;
 
-        InputStream inputStream = this.getClass().getResourceAsStream("/static/report-template.docx");
+        List<Map<String, String>> detectionResultRows = buildDetectionResultRows(orderId, samples);
+        String productName = defaultReportText(insOrder.getSampleView(), insOrder.getSample());
+        String customerName = defaultReportText(custom == null ? null : custom.getCompany(), insOrder.getCompany());
+        String detectionCategory = defaultReportText(finalOrderType, "濮旀墭妫�娴�");
+        String sampleCode = samples.stream()
+                .map(SampleProductDto::getSampleCode)
+                .filter(StringUtils::isNotBlank)
+                .distinct()
+                .collect(Collectors.joining("銆�"));
+        String productAndModel = productName;
+        if (StringUtils.isNotBlank(finalModelStr) && !Objects.equals(productName, finalModelStr)) {
+            productAndModel = productName + " " + finalModelStr;
+        }
+        String standardMethodText = "null".equals(standardMethod2.toString()) ? "" : standardMethod2.toString();
+        String productionDate = "/";
+        String batchNo = "/";
+        if (reportInventory != null) {
+            if (reportInventory.getProductDate() != null) {
+                productionDate = reportInventory.getProductDate().format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�"));
+            }
+            batchNo = defaultReportText(reportInventory.getUpdateBatchNo(), reportInventory.getLotBatchNo());
+        }
+        // 鏂拌仛鐩寸粦妯℃澘璁㈠崟锛氭姤鍛婁俊鎭彇濮旀墭淇℃伅鍜岃鍗曟ā鏉垮揩鐓э紝涓嶅啀鍙栬兘鍔涜寖鍥存爣鍑嗘柟娉曘��
+        List<InsOrderStandardTemplate> templateSnapshots = insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                        .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId));
+        boolean newJuTemplateOrder = !templateSnapshots.isEmpty() && isDirectTemplateOrder(orderId);
+        if (newJuTemplateOrder) {
+            productName = defaultReportText(insOrder.getSampleView(), insOrder.getSample());
+            finalModelStr = "/";
+            productAndModel = productName;
+            if (insOrder.getSampleDate() != null) {
+                finalSendTime = insOrder.getSampleDate().atStartOfDay();
+            }
+            if (insOrder.getProductionDate() != null) {
+                productionDate = insOrder.getProductionDate().format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�"));
+            }
+            batchNo = defaultReportText(insOrder.getProductionBatch(), "/");
+            standardMethodText = templateSnapshots.stream()
+                    .map(InsOrderStandardTemplate::getRemark)
+                    .filter(StringUtils::isNotBlank)
+                    .distinct()
+                    .collect(Collectors.joining("锛�"));
+        }
+        boolean containsOrganicChlorine = detectionResultRows.stream()
+                .map(row -> row.get("itemName"))
+                .filter(Objects::nonNull)
+                .anyMatch(name -> name.contains("鏈夋満姘�"));
+        String resultRemark = containsOrganicChlorine
+                ? "寰簱浠戞硶锛屾湁鏈烘隘鍚噺灏忎簬0.005%鏃讹紝浠ユ湭妫�鍑烘姤鍑恒��"
+                : defaultReportText(insOrder.getRemark(), "/");
+
+        // 妫�娴嬫姤鍛婂拰妫�楠屾姤鍛婄粺涓�浣跨敤鏂扮増鎶ュ憡妯℃澘
+        String templateName = "/static/detection-report-template-v2.docx";
+        InputStream inputStream = this.getClass().getResourceAsStream(templateName);
+        if (inputStream == null) {
+            throw new RuntimeException("鎵句笉鍒版姤鍛婃ā鏉�: " + templateName);
+        }
         Configure configure = Configure.builder()
                 .bind("deviceList", new HackLoopTableRenderPolicy())
+                .bind("r", new HackLoopTableRenderPolicy(true))
+                .setValidErrorHandler(new PreserveReportPicturePlaceholderHandler())
                 .useSpringEL(true)
                 .build();
 
+        String finalProductAndModel = productAndModel;
+        String finalProductName = productName;
+        String finalCustomerName = customerName;
+        String finalDetectionCategory = detectionCategory;
+        String finalSampleCode = defaultReportText(sampleCode, "/");
+        String finalStandardMethodText = defaultReportText(standardMethodText, "/");
+        String finalProductionDate = productionDate;
+        String finalBatchNo = batchNo;
+        String finalResultRemark = resultRemark;
+        String equipmentText = buildEquipmentText(finalDeviceList);
+        String issueDate = now.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�"));
+        String finalReportModelStr = finalModelStr;
+        LocalDateTime finalReportSendTime = finalSendTime;
         XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(
                 new HashMap<String, Object>() {{
                     put("order", insOrder);
@@ -2580,10 +3427,10 @@
                     put("sampleSize", insOrder.getTestQuantity());
                     put("tables", tables);
                     put("tableSize", tables.size() + 1);
-                    put("standardMethod", (standardMethod2.toString().equals("null") ? "" : standardMethod2));
+                    put("standardMethod", finalStandardMethodText);
                     put("deviceList", finalDeviceList);
                     put("twoCode", null);
-                    put("models", finalModelStr);
+                    put("models", finalReportModelStr);
                     put("productSize", productSize.get());
                     put("createTime", now.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")));
                     put("createTimeEn", monthNames[now.getMonthValue() - 1] + " " + now.format(DateTimeFormatter.ofPattern("dd, yyyy")));
@@ -2595,8 +3442,8 @@
                     put("examineUrl", null);
                     put("ratifyUrl", null);
                     put("orderType", finalOrderType);
-                    put("getTime", finalSendTime.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")));
-                    put("getTimeEn", monthNames[finalSendTime.getMonthValue() - 1] + " " + finalSendTime.format(DateTimeFormatter.ofPattern("dd, yyyy")));
+                    put("getTime", finalReportSendTime.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")));
+                    put("getTimeEn", monthNames[finalReportSendTime.getMonthValue() - 1] + " " + finalReportSendTime.format(DateTimeFormatter.ofPattern("dd, yyyy")));
                     put("seal1", null);
                     put("seal2", null);
                     put("formTypeCh", formType);
@@ -2604,22 +3451,355 @@
                     put("resultCh", finalResultCh);
                     put("resultEn", finalResultEn);
                     put("sampleStatus", sampleStatus);
+                    // 鏂扮増妫�娴嬫姤鍛婃ā鏉匡紙鍙傜収銆婃湁鏈烘隘妫�娴嬫姤鍛娿�嬶級浣跨敤鐨勬墎骞冲瓧娈点��
+                    put("no", insReport.getCode());
+                    put("cover", finalProductAndModel);
+                    put("product", finalProductName);
+                    put("model", defaultReportText(finalReportModelStr, "/"));
+                    put("customer", finalCustomerName);
+                    put("category", finalDetectionCategory);
+                    put("date", issueDate);
+                    put("maker", defaultReportText(insOrder.getProduction(), "/"));
+                    put("env", finalEnvironment);
+                    put("qty", defaultReportText(insOrder.getTestQuantity(), "/"));
+                    put("receive", finalReportSendTime.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")));
+                    put("sampleNo", finalSampleCode);
+                    put("appearance", defaultReportText(sampleStatus, "/"));
+                    put("sender", defaultReportText(insOrder.getPrepareUser(), "/"));
+                    put("produced", finalProductionDate);
+                    put("batch", finalBatchNo);
+                    put("phone", defaultReportText(insOrder.getPhone(), "/"));
+                    put("testDate", insTime);
+                    put("entrustNo", defaultReportText(insOrder.getEntrustCode(), "/"));
+                    put("sampling", "/");
+                    put("standard", finalStandardMethodText);
+                    put("equipment", equipmentText);
+                    put("conclusion", "鏍峰搧鎸夊鎵樻柟瑕佹眰杩涜妫�娴嬶紝鏁版嵁瑙佹娴嬬粨鏋溿��");
+                    put("remark", "鏈姤鍛婃娴嬬粨鏋滀粎瀵瑰綋鏃ユ墍鎺ユ敹鏍峰搧璐熻矗銆�");
+                    put("r", detectionResultRows);
+                    put("resultNote", finalResultRemark);
                 }});
         try {
-            // 淇敼鎹㈣鍜屽悎骞堕棶棰�
-            updaeMerge(template.getXWPFDocument(), false);
-            String name = insReport.getCode().replace("/", "") + ".docx";
-            template.writeAndClose(Files.newOutputStream(Paths.get(wordUrl + "/" + name)));
+            String name = insReport.getCode().replace("/", "") + (showResult ? ".docx" : "-C.docx");
+            Files.createDirectories(Paths.get(wordUrl));
+            template.writeAndClose(Files.newOutputStream(Paths.get(wordUrl, name)));
             insReport.setUrl("/word/" + name);
-            insReport.setWriteUserId(SecurityUtils.getUserId().intValue());//鎻愪氦浜�
+            insReport.setWriteUserId(writeUserId);//缂栧埗浜猴紙妫�楠屼汉锛�
             insReport.setWriteTime(LocalDateTime.now());//鎻愪氦鏃堕棿
-            // 鏌ヨ鎶ュ憡, 鍒ゆ柇涔嬪墠鏄惁娣诲姞杩�, 娣诲姞杩囧垹闄�
-            insReportMapper.delete(Wrappers.<InsReport>lambdaQuery()
-                    .eq(InsReport::getInsOrderId, insOrder.getId()));
-            insReportMapper.insert(insReport);
+            saveGeneratedReport(insReport);
+            inputStream.close();
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
+    }
+
+    private void saveGeneratedReport(InsReport report) {
+        InsReport existing = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
+                .eq(InsReport::getInsOrderId, report.getInsOrderId())
+                .last("limit 1"));
+        if (existing == null) {
+            insReportMapper.insert(report);
+            return;
+        }
+        report.setId(existing.getId());
+        insReportMapper.updateById(report);
+    }
+
+    /**
+     * 鏂扮増妫�娴嬫姤鍛婄殑缁撴灉琛ㄥ浐瀹氫负鍥涘垪锛氬簭鍙枫�佹娴嬮」鐩�佸崟浣嶃�佹娴嬬粨鏋溿��
+     */
+    private List<Map<String, String>> buildDetectionResultRows(Integer orderId, List<SampleProductDto> samples) {
+        if (isDirectTemplateOrder(orderId)) {
+            return buildTemplateDetectionResultRows(orderId);
+        }
+        List<Map<String, String>> rows = new ArrayList<>();
+        if (CollectionUtils.isEmpty(samples)) {
+            return rows;
+        }
+
+        boolean multipleSamples = samples.size() > 1;
+        int sequence = 1;
+        for (SampleProductDto sample : samples) {
+            if (CollectionUtils.isEmpty(sample.getInsProduct())) {
+                continue;
+            }
+            for (InsProduct product : sample.getInsProduct()) {
+                // 缁戝畾椤圭洰浠呭弬涓庤绠楋紝涓嶅簲鍑虹幇鍦ㄦ姤鍛婁腑銆�
+                if (product == null || Objects.equals(product.getIsBinding(), 1)) {
+                    continue;
+                }
+
+                String itemName = defaultReportText(
+                        product.getInspectionItemSubclass(),
+                        defaultReportText(product.getInspectionItem(), product.getInspectionItemClass()));
+                if (multipleSamples && StringUtils.isNotBlank(sample.getSampleCode())) {
+                    itemName = sample.getSampleCode() + " - " + itemName;
+                }
+
+                Map<String, String> row = new LinkedHashMap<>();
+                row.put("seq", String.valueOf(sequence++));
+                row.put("itemName", itemName);
+                row.put("unit", defaultReportText(product.getUnit(), "/"));
+                row.put("result", defaultReportText(product.getLastValue(), "/"));
+                rows.add(row);
+            }
+        }
+        return rows;
+    }
+
+    /**
+     * 鏂拌仛鐩寸粦妯℃澘璁㈠崟锛氫竴涓ā鏉块〉绛惧湪鎶ュ憡涓彧瀵瑰簲涓�鏉℃娴嬮」鐩��
+     */
+    private List<Map<String, String>> buildTemplateDetectionResultRows(Integer orderId) {
+        List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                        .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId));
+        List<Map<String, String>> rows = new ArrayList<>();
+        int sequence = 1;
+        for (InsOrderStandardTemplate snapshot : snapshots) {
+            TemplateExportCell exportCell = getFirstTemplateExportCell(snapshot.getThing());
+            JSONObject recordValues = StrUtil.isBlank(snapshot.getRecordValues())
+                    ? new JSONObject() : JSON.parseObject(snapshot.getRecordValues());
+            String result = readTemplateCellText(recordValues, exportCell.resultCoordinate, exportCell.templateValues);
+            if (StringUtils.isBlank(result)) {
+                throw new ErrorException("妯℃澘鈥�" + defaultReportText(snapshot.getName(), "妯℃澘ID " + snapshot.getTemplateId())
+                        + "鈥濈殑瀵煎嚭鍊间笉鑳戒负绌�");
+            }
+            String unit = exportCell.unitCoordinate == null ? null
+                    : readTemplateCellText(recordValues, exportCell.unitCoordinate, exportCell.templateValues);
+            String itemName = exportCell.itemCoordinate == null ? null
+                    : readTemplateCellText(recordValues, exportCell.itemCoordinate, exportCell.templateValues);
+
+            Map<String, String> row = new LinkedHashMap<>();
+            row.put("seq", String.valueOf(sequence++));
+            row.put("itemName", defaultReportText(itemName,
+                    defaultReportText(snapshot.getName(), "妯℃澘ID " + snapshot.getTemplateId())));
+            row.put("unit", defaultReportText(unit, "/"));
+            row.put("result", result);
+            rows.add(row);
+        }
+        if (rows.isEmpty()) {
+            throw new ErrorException("褰撳墠璁㈠崟鏈壘鍒板彲鐢熸垚鎶ュ憡鐨勫師濮嬭褰曟ā鏉�");
+        }
+        return rows;
+    }
+
+    private TemplateExportCell getFirstTemplateExportCell(String compressedThing) {
+        if (StrUtil.isBlank(compressedThing)) {
+            throw new ErrorException("鍘熷璁板綍妯℃澘涓虹┖");
+        }
+        String thing;
+        try {
+            thing = GZipUtil.uncompress(compressedThing);
+        } catch (Exception ignored) {
+            thing = compressedThing;
+        }
+        JSONArray cellData = JSON.parseObject(thing).getJSONArray("data").getJSONObject(0).getJSONArray("celldata");
+        Integer resultColumn = null;
+        Integer itemColumn = null;
+        Integer unitColumn = null;
+        List<int[]> exportCells = new ArrayList<>();
+        Map<String, String> templateValues = new HashMap<>();
+        for (Object item : cellData) {
+            JSONObject cell = JSON.parseObject(JSON.toJSONString(item));
+            Integer row = cell.getInteger("r");
+            Integer column = cell.getInteger("c");
+            JSONObject value = cell.getJSONObject("v");
+            if (row == null || column == null || value == null) {
+                continue;
+            }
+            String displayValue = value.get("v") == null ? null : String.valueOf(value.get("v"));
+            templateValues.put(row + "-" + column, displayValue);
+            if (resultColumn == null && "妫�楠岀粨鏋�".equals(StringUtils.trim(displayValue))) {
+                resultColumn = column;
+            }
+            if (itemColumn == null && ("妫�娴嬮」鐩�".equals(StringUtils.trim(displayValue))
+                    || "妫�楠岄」鐩�".equals(StringUtils.trim(displayValue)))) {
+                itemColumn = column;
+            }
+            if (unitColumn == null && "鍗曚綅".equals(StringUtils.trim(displayValue))) {
+                unitColumn = column;
+            }
+            JSONObject ps = value.getJSONObject("ps");
+            if (ps != null && "瀵煎嚭鍊�".equals(ps.getString("value"))) {
+                exportCells.add(new int[]{row, column});
+            }
+        }
+        if (exportCells.isEmpty()) {
+            throw new ErrorException("妯℃澘蹇呴』鑷冲皯閰嶇疆涓�涓鍑哄�兼壒娉�");
+        }
+        exportCells.sort(Comparator.comparingInt((int[] cell) -> cell[0]).thenComparingInt(cell -> cell[1]));
+        int[] firstExport = exportCells.get(0);
+        int resultColumnForRow = resultColumn == null ? firstExport[1] : resultColumn;
+        // 閫氬父鈥滃鍑哄�尖�濇壒娉ㄩ厤缃湪椤圭洰鍚嶇О鍗曞厓鏍硷紱鑻ラ厤缃湪缁撴灉鍗曞厓鏍硷紝鍒欏洖鍒扳�滄娴嬮」鐩�濆垪鍙栧悕绉般��
+        Integer itemColumnForRow = !Objects.equals(firstExport[1], resultColumnForRow)
+                ? firstExport[1] : itemColumn;
+        TemplateExportCell result = new TemplateExportCell();
+        result.resultCoordinate = firstExport[0] + "-" + resultColumnForRow;
+        result.itemCoordinate = itemColumnForRow == null ? null : firstExport[0] + "-" + itemColumnForRow;
+        result.unitCoordinate = unitColumn == null ? null : firstExport[0] + "-" + unitColumn;
+        result.templateValues = templateValues;
+        return result;
+    }
+
+    private String readTemplateCellText(JSONObject recordValues, String coordinate, Map<String, String> templateValues) {
+        JSONObject recordCell = recordValues == null ? null : recordValues.getJSONObject(coordinate);
+        if (recordCell != null && recordCell.get("v") != null) {
+            String value = String.valueOf(recordCell.get("v"));
+            if (StringUtils.isNotBlank(value)) {
+                return value;
+            }
+        }
+        return templateValues.get(coordinate);
+    }
+
+    private static class TemplateExportCell {
+        private String itemCoordinate;
+        private String resultCoordinate;
+        private String unitCoordinate;
+        private Map<String, String> templateValues;
+    }
+
+    private static String buildEquipmentText(List<Map<String, String>> deviceList) {
+        if (CollectionUtils.isEmpty(deviceList)) {
+            return "/";
+        }
+        Set<String> lines = new LinkedHashSet<>();
+        int sequence = 1;
+        for (Map<String, String> device : deviceList) {
+            String name = getMapText(device, "deviceName", "device_name");
+            String managementNumber = getMapText(device, "managementNumber", "management_number");
+            String line = sequence++ + ". " + defaultReportText(name, "/");
+            if (StringUtils.isNotBlank(managementNumber)) {
+                line += "锛�" + managementNumber;
+            }
+            lines.add(line);
+        }
+        return String.join("\n", lines);
+    }
+
+    private String buildReportEnvironment(Integer orderId, InsOrder order) {
+        List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                        .select(InsOrderStandardTemplate::getTemperature,
+                                InsOrderStandardTemplate::getHumidity));
+        List<String> temperatures = snapshots.stream()
+                .map(InsOrderStandardTemplate::getTemperature)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toList());
+        List<String> humidities = snapshots.stream()
+                .map(InsOrderStandardTemplate::getHumidity)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toList());
+
+        String temperature = formatConditionRange(temperatures, order.getTemperature(), "鈩�");
+        String humidity = formatConditionRange(humidities, order.getHumidity(), "%");
+        return Stream.of(temperature, humidity)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.joining(" "));
+    }
+
+    private static String formatConditionRange(List<String> values, String fallback, String unit) {
+        List<BigDecimal> numbers = new ArrayList<>();
+        List<String> candidates = CollectionUtils.isEmpty(values)
+                ? Collections.singletonList(fallback) : values;
+        Pattern numberPattern = Pattern.compile("-?\\d+(?:\\.\\d+)?");
+        for (String value : candidates) {
+            if (StringUtils.isBlank(value)) {
+                continue;
+            }
+            java.util.regex.Matcher matcher = numberPattern.matcher(value);
+            while (matcher.find()) {
+                numbers.add(new BigDecimal(matcher.group()));
+            }
+        }
+        if (numbers.isEmpty()) {
+            return StringUtils.isBlank(fallback) ? "" : fallback + unit;
+        }
+        BigDecimal minimum = Collections.min(numbers);
+        BigDecimal maximum = Collections.max(numbers);
+        String minimumText = minimum.stripTrailingZeros().toPlainString();
+        if (minimum.compareTo(maximum) == 0) {
+            return minimumText + unit;
+        }
+        return minimumText + "~" + maximum.stripTrailingZeros().toPlainString() + unit;
+    }
+
+    private static String getMapText(Map<String, String> map, String... keys) {
+        if (map == null) {
+            return null;
+        }
+        for (String key : keys) {
+            String value = map.get(key);
+            if (StringUtils.isNotBlank(value)) {
+                return value;
+            }
+            for (Map.Entry<String, String> entry : map.entrySet()) {
+                if (entry.getKey() != null && entry.getKey().equalsIgnoreCase(key)
+                        && StringUtils.isNotBlank(entry.getValue())) {
+                    return entry.getValue();
+                }
+            }
+        }
+        return null;
+    }
+
+    private static String defaultReportText(String value, String fallback) {
+        if (StringUtils.isNotBlank(value)) {
+            return value;
+        }
+        return StringUtils.isNotBlank(fallback) ? fallback : "/";
+    }
+
+    /**
+     * 璁$畻琛ㄦ牸鍒楀搴�
+     * @param max 鏈�澶ф楠屼釜鏁�
+     * @return
+     */
+    private static int[] calcTableColWidths(int max, boolean showResult){
+        if (!showResult) {
+            switch (max) {
+                case 1: return new int[]{650, 2200, 2200, 850, 2300, 1800};
+                case 2: return new int[]{650, 1600, 1600, 850, 1900, 1700, 1700};
+                case 3: return new int[]{650, 1400, 1400, 850, 1600, 1375, 1375, 1375};
+                case 4: return new int[]{650, 1250, 1250, 850, 1450, 1140, 1140, 1140, 1140};
+                case 5: return new int[]{650, 1150, 1150, 850, 1300, 980, 980, 980, 980, 980};
+                default: return new int[0];
+            }
+        }
+        int[] colWidths = null;
+        switch (max) {
+            case 1:
+                colWidths = new int[]{650, 2000, 2000, 850, 2200, 2100, 1200};
+                break;
+            case 2:
+                colWidths = new int[]{650, 1400, 1400, 850, 2100, 1200, 1200, 1200};
+                break;
+            case 3:
+                colWidths = new int[]{650, 1400, 1400, 850, 1500, 1000, 1000, 1000, 1200};
+                break;
+            case 4:
+                colWidths = new int[]{650, 1200, 1200, 850, 1400, 850, 850, 850, 850, 1200};
+                break;
+            case 5:
+                colWidths = new int[]{650, 1100, 1100, 850, 1350, 750, 750, 750, 750, 750, 1200};
+                break;
+        }
+        if(ObjectUtils.isNull(colWidths)){
+            List<Integer> defaultColWidths = new ArrayList<>(Arrays.asList(650, 1100, 1100, 850, 1350));
+            int totalWidth = 3000;//鎬诲搴�
+            int byOneWidth = totalWidth/max;//姣忎竴涓殑瀹藉害
+            int realWidth = 0;//瀹為檯瀹藉害
+            for (int i = 0; i < max; i++) {
+                realWidth+=byOneWidth;
+                defaultColWidths.add(byOneWidth);
+            }
+            defaultColWidths.add(1200+(totalWidth-realWidth));
+            return defaultColWidths.stream().mapToInt(Integer::intValue).toArray();
+        }
+        return colWidths;
     }
 
     /**
@@ -2637,9 +3817,9 @@
         // 鑾峰彇妫�娴嬪唴瀹瑰垽鏂槸鍚﹁秴鍑�
         if (StringUtils.isNotBlank(dataText) && dataText.contains("@")) {
             double number = 1;
-            double chinaLength = 0;
-            double englishLength = 0;
-            double valueLength = 0;
+            double chinaLength = 14;
+            double englishLength = 28;
+            double valueLength = 6;
             // 鏍规嵁绾胯姱涓暟鍒ゆ柇璺濈
             switch (max) {
                 case 1:
@@ -2862,7 +4042,7 @@
      * @param max
      * @param cableTags 绾胯姱棰滆壊
      */
-    private static void addHead(SampleProductDto sample, List<TextRenderData> text, RowRenderData rowRenderData, List<RowRenderData> rows, int max, List<String> cableTags) {
+    private static void addHead(SampleProductDto sample, List<TextRenderData> text, RowRenderData rowRenderData, List<RowRenderData> rows, int max, List<String> cableTags, boolean showResult) {
         // 绗竴琛�
         TextRenderData firstRenderData1 = new TextRenderData();
         firstRenderData1.setText("鏍峰搧缂栧彿@Sample No.鈭�1");
@@ -2939,6 +4119,11 @@
             }
 
         }
+        // 妫�娴嬫姤鍛婁笉灞曠ず鈥滅粨璁衡�濆垪锛岄琛屼篃瑕佸悓姝ュ噺灏戜竴涓崟鍏冩牸锛�
+        // 鍚﹀垯棣栬涓� max + 6 鍒椼�佸叾浣欒涓� max + 5 鍒楋紝poi-tl 鏃犳硶娓叉煋琛ㄦ牸銆�
+        if (!showResult && !text.isEmpty()) {
+            text.remove(text.size() - 1);
+        }
         TextRenderData[] text2 = text.toArray(new TextRenderData[0]);
         rowRenderData = Rows.of(text2).center().rowAtleastHeight(1).create();
         rows.add(rowRenderData);
@@ -2987,13 +4172,14 @@
 
         for (int i = 0; i < max; i++) {
             TextRenderData headRenderData6 = new TextRenderData();
-            headRenderData6.setText("妫�楠岀粨鏋淍Test result鈭�6");
+            headRenderData6.setText(showResult ? "妫�楠岀粨鏋淍Test result鈭�6" : "妫�娴嬫暟鎹瓳Test data鈭�6");
             Style headStyle6 = new Style();
             headStyle6.setFontFamily("瀹嬩綋");
             headStyle6.setColor("000000");
             headRenderData6.setStyle(headStyle6);
             text.add(headRenderData6);
         }
+        if (showResult) {
         TextRenderData headRenderData7 = new TextRenderData();
         headRenderData7.setText("缁撹@Conclusion");
         Style headStyle7 = new Style();
@@ -3001,6 +4187,7 @@
         headStyle7.setColor("000000");
         headRenderData7.setStyle(headStyle7);
         text.add(headRenderData7);
+        }
 
         TextRenderData[] text3 = text.toArray(new TextRenderData[0]);
         rowRenderData = Rows.of(text3).center().rowAtleastHeight(1).create();
@@ -3058,6 +4245,7 @@
                 cableRenderData6.setStyle(cableStyle6);
                 text.add(cableRenderData6);
             }
+            if (showResult) {
             TextRenderData cableRenderData7 = new TextRenderData();
             cableRenderData7.setText("-");
             Style cableStyle7 = new Style();
@@ -3065,6 +4253,7 @@
             cableStyle7.setColor("000000");
             cableRenderData7.setStyle(cableStyle7);
             text.add(cableRenderData7);
+            }
 
             TextRenderData[] text4 = text.toArray(new TextRenderData[0]);
             rowRenderData = Rows.of(text4).center().rowAtleastHeight(1).create();
@@ -3097,7 +4286,7 @@
                              List<String> resultChList,
                              List<String> resultEhList,
                              InsSample insSamples, List<String> cableTags,
-                             boolean isOneSample) {
+                             boolean isOneSample, boolean showResult) {
         // 妫�楠岄」鎬绘暟
         AtomicInteger productSize = new AtomicInteger(1);
         // 涓嶅悎鏍间俊鎭�
@@ -3505,7 +4694,6 @@
         // 妫�楠岄」鍒嗙被      妫�楠岄」  妫�楠屽瓙椤�
         Map<String, LinkedHashMap<String, List<String>>> errorClassItemMapCn = new LinkedHashMap<>();
         Map<String, LinkedHashMap<String, List<String>>> errorClassItemMapEn = new LinkedHashMap<>();
-
         // 涓棿妫�娴嬪�兼坊鍔�
         for (int i = 0; i < sampleList.size(); i++) {
             SampleProductExportDto sample = sampleList.get(i);
@@ -3586,7 +4774,9 @@
 
             // 鍒ゆ柇鏄惁鏈夌數缂嗘爣璇唌ap
             if (CollectionUtils.isNotEmpty(sample.getCableTagValueMap())) {
-                sample.setLastValueList(new ArrayList<>(sample.getCableTagValueMap().values()));
+                TreeMap<String, String> cableTagValues = new TreeMap<>(Comparator.comparingInt(cableTags::indexOf));
+                cableTagValues.putAll(sample.getCableTagValueMap());
+                sample.setLastValueList(new ArrayList<>(cableTagValues.values()));
             }
             if (CollectionUtils.isNotEmpty(sample.getCableTagResultMap())) {
                 sample.setInsResultList(new ArrayList<>(sample.getCableTagResultMap().values()));
@@ -3620,6 +4810,7 @@
                 }
             }
             // 鍒ゅ畾缁撴灉
+            if (showResult) {
             String result = "";
             if (sample.getInsResult() != null) {
                 switch (sample.getInsResult()) {
@@ -3636,16 +4827,16 @@
             }
             if (CollectionUtils.isNotEmpty(sample.getLastValueList())) {
                 // 鍒ゆ柇鏄惁鏈変竴涓敊璇�
-                if (sample.getInsResultList().stream().anyMatch(s -> s.equals(3))) {
+                if (sample.getInsResultList().stream().anyMatch(s -> Objects.equals(s, 3))) {
                     result = "-";
                 } else {
-                    boolean error = sample.getInsResultList().stream().anyMatch(s -> s.equals(0));
+                    boolean error = sample.getInsResultList().stream().anyMatch(s -> Objects.equals(s, 0));
                     if (error) {
                         List<String> collect = new ArrayList<>();
                         int index = 0;
                         for (Integer count : sample.getInsResultList()) {
                             String type;
-                            if (count.equals(0)) {
+                            if (Objects.equals(count, 0)) {
                                 String itemCh = "";
                                 String itemEn = "";
                                 // 娣诲姞涓嶅悎鏍兼弿杩�
@@ -3679,6 +4870,7 @@
                 }
             }
 
+            if (showResult) {
             TextRenderData headRenderData7 = new TextRenderData();
             headRenderData7.setText(result);
             Style headStyle7 = new Style();
@@ -3686,6 +4878,8 @@
             headStyle7.setColor("000000");
             headRenderData7.setStyle(headStyle7);
             text.add(headRenderData7);
+            }
+            }
 
             TextRenderData[] text2 = text.toArray(new TextRenderData[0]);
             rowRenderData = Rows.of(text2).center().rowAtleastHeight(1).create();
@@ -3765,6 +4959,18 @@
     }
 
     /**
+     * NBSP锛堥潪闂存柇绌烘牸锛� 杞垚 鏅�氱┖鏍�
+     * @param oldStr
+     * @return
+     */
+    private String normalizedSpaces(String oldStr){
+        if(StringUtils.isBlank(oldStr)){
+            return oldStr;
+        }
+        return oldStr.replaceAll("\u00A0", " ").trim();
+    }
+
+    /**
      * 娣诲姞鎶ュ憡缁撹涓嫳鏂�
      * @param sample
      * @param itemCh
@@ -3776,9 +4982,9 @@
                                        String itemCh,
                                        String itemEn) {
         // 鍒ゆ柇鏄惁鏈夋楠岄」鍒嗙被map
-        String classTiemName = itemCh + (StringUtils.isBlank(sample.getInspectionItemClass()) ? "" : sample.getInspectionItemClass());
-        String classTiemNameEn = itemEn + (StringUtils.isBlank(sample.getInspectionItemClassEN()) ? "" : sample.getInspectionItemClassEN());
-        String classTiemNameItemEN = StringUtils.isBlank(sample.getInspectionItemEn()) ? "" : sample.getInspectionItemEn();
+        String classTiemName = itemCh + (StringUtils.isBlank(sample.getInspectionItemClass()) ? "" : normalizedSpaces(sample.getInspectionItemClass()));
+        String classTiemNameEn = itemEn + (StringUtils.isBlank(sample.getInspectionItemClassEN()) ? "" : normalizedSpaces(sample.getInspectionItemClassEN()));
+        String classTiemNameItemEN = StringUtils.isBlank(sample.getInspectionItemEn()) ? "" : normalizedSpaces(sample.getInspectionItemEn());
 
         if (errorClassItemMapCn.containsKey(classTiemName)) {
             // 鍒ゆ柇鏄惁鏈夋楠岄」map
@@ -3834,7 +5040,7 @@
                 sampleProductDto2.setLastValue(sampleProductDto2.getLastValue().trim());
             }
 
-            if (sampleProductDto2.getInsResult().equals(0)) {
+            if (Objects.equals(sampleProductDto2.getInsResult(), 0)) {
                 // 鏌ヨ涓嶅悎鏍煎娴�
                 Long count = insUnqualifiedRetestProductMapper.selectCount(Wrappers.<InsUnqualifiedRetestProduct>lambdaQuery()
                         .eq(InsUnqualifiedRetestProduct::getInsProductId, sampleProductDto2.getInsProductId())
@@ -3898,7 +5104,7 @@
      * @param rowRenderData
      * @param rows
      */
-    private static void addEnding(List<TextRenderData> text, RowRenderData rowRenderData, List<RowRenderData> rows, int max) {
+    private static void addEnding(List<TextRenderData> text, RowRenderData rowRenderData, List<RowRenderData> rows, int max, boolean showResult) {
         for (int i = 0; i < 2; i++) {
             TextRenderData endingRenderData = new TextRenderData();
             endingRenderData.setText("澶囨敞鈭�1999");
@@ -3909,9 +5115,9 @@
             text.add(endingRenderData);
         }
 
-        for (int i = 0; i < 5 + max - 1; i++) {
+        for (int i = 0; i < (showResult ? 5 : 4) + max - 1; i++) {
             TextRenderData endingRenderData = new TextRenderData();
-            endingRenderData.setText("鈥溾垰鈥濊〃绀洪」鐩悎鏍�,鈥溍椻�濊〃绀洪」鐩笉鍚堟牸,鈥�-鈥濊〃绀轰笉瑕佸垽瀹氾紝鈥�/鈥濊〃绀烘病鏈夋爣鍑嗚姹傘�侤鈥溾垰鈥� indicates test ltem is qualified,鈥溍椻�� indicates test ltem is unqualified,鈥�-鈥� indicates test ltem judgment is not required,鈥�/鈥� indicates test ltem is no test requirement.鈭�2000");
+            endingRenderData.setText(showResult ? "鈥溾垰鈥濊〃绀洪」鐩悎鏍�,鈥溍椻�濊〃绀洪」鐩笉鍚堟牸,鈥�-鈥濊〃绀轰笉瑕佸垽瀹氾紝鈥�/鈥濊〃绀烘病鏈夋爣鍑嗚姹傘�侤鈥溾垰鈥� indicates test ltem is qualified,鈥溍椻�� indicates test ltem is unqualified,鈥�-鈥� indicates test ltem judgment is not required,鈥�/鈥� indicates test ltem is no test requirement.鈭�2000" : "");
             Style endingStyle = new Style();
             endingStyle.setFontFamily("瀹嬩綋");
             endingStyle.setColor("000000");
@@ -4291,6 +5497,11 @@
 
         // 淇濆瓨鍒伴檮浠堕噷闈�
         uploadFile(insOrderId, multipartFile);
+        try {
+            inputStream.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
 
     }
 
@@ -4445,42 +5656,43 @@
             return;
         }
 
-        //棣栧厛鍒ゆ柇褰撳墠浜虹殑褰撳墠鏃堕棿鏄惁鏄帓鐝椂闂村唴,濡傛灉涓嶆槸灏辨槸鍔犵彮
-        LocalDateTime today = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT);
-
         //鏍¢獙濡傛灉杩欎釜浜鸿繖涓娴嬮」鐩凡缁忔坊鍔犺繃浜�
         List<AuxiliaryOutputWorkingHours> count2s = auxiliaryOutputWorkingHoursMapper.selectList(Wrappers.<AuxiliaryOutputWorkingHours>lambdaQuery()
                 .eq(AuxiliaryOutputWorkingHours::getCheck, userId)
                 .eq(AuxiliaryOutputWorkingHours::getInsProductId, insProduct.getId()));
         if (CollectionUtils.isNotEmpty(count2s)) {
-            auxiliaryOutputWorkingHoursMapper.deleteBatchIds(count2s.stream().map(auxiliaryOutputWorkingHours -> auxiliaryOutputWorkingHours.getId()).collect(Collectors.toList()));
-        }
-        if (ObjectUtils.isNotEmpty(insProduct.getManHour()) && StringUtils.isNotBlank(insProduct.getLastValue())) {
-            AuxiliaryOutputWorkingHours auxiliaryOutputWorkingHours = new AuxiliaryOutputWorkingHours();
-            auxiliaryOutputWorkingHours.setInspectionItemClass(insProduct.getInspectionItemClass());//妫�娴嬮」鍒嗙被
-            auxiliaryOutputWorkingHours.setInspectionItem(insProduct.getInspectionItem());//妫�娴嬬埗椤�
-            auxiliaryOutputWorkingHours.setInspectionItemSubclass(insProduct.getInspectionItemSubclass());//妫�娴嬪瓙椤�
-            auxiliaryOutputWorkingHours.setSample(insSampleMapper.selectById(insProduct.getInsSampleId()).getSampleCode());//鏍峰搧缂栧彿
-            auxiliaryOutputWorkingHours.setOrderId(insOrder.getId());//璁㈠崟id
-            auxiliaryOutputWorkingHours.setOrderNo(insOrder.getEntrustCode());//闈炲姞鐝鎵樺崟鍙�
-            auxiliaryOutputWorkingHours.setWorkTime(insProduct.getManHour());//闈炲姞鐝伐鏃�
-            auxiliaryOutputWorkingHours.setAmount(1);//闈炲姞鐝暟閲�
-            auxiliaryOutputWorkingHours.setOutputWorkTime((ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHours.getOvertimeWorkTime()) ? auxiliaryOutputWorkingHours.getOvertimeWorkTime() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHours.getWorkTime()) ? auxiliaryOutputWorkingHours.getWorkTime() : BigDecimal.ZERO));//浜ч噺宸ユ椂
-            auxiliaryOutputWorkingHours.setManHourGroup(insProduct.getManHourGroup());//宸ユ椂鍒嗙粍
-            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-            DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-            auxiliaryOutputWorkingHours.setDateTime(LocalDateTime.now().toLocalDate().atStartOfDay().format(formatters));//鏃ユ湡
-            LocalDateTime localDateTime = LocalDateTime.now();
-            DateTime parse = DateUtil.parse(localDateTime.format(formatter));
-            auxiliaryOutputWorkingHours.setWeekDay(getWeek(localDateTime.format(formatters)));//鏄熸湡
-            auxiliaryOutputWorkingHours.setWeek(String.valueOf(DateUtil.weekOfYear(DateUtil.offsetDay(parse, 1))));//鍛ㄦ
-            auxiliaryOutputWorkingHours.setCheck(userId);//妫�娴嬩汉
-            auxiliaryOutputWorkingHours.setPrice(insProduct.getPrice());//鍗曚环
-            auxiliaryOutputWorkingHours.setSampleId(insProduct.getInsSampleId());//鏍峰搧id
-            auxiliaryOutputWorkingHours.setInsProductId(insProduct.getId());//妫�楠岄」id
+            for (AuxiliaryOutputWorkingHours auxiliaryOutputWorkingHours : count2s) {
+                auxiliaryOutputWorkingHours.setCheck(userId);//妫�娴嬩汉
+            }
+            auxiliaryOutputWorkingHoursService.updateBatchById(count2s);
+        } else {
+            if (ObjectUtils.isNotEmpty(insProduct.getManHour()) && StringUtils.isNotBlank(insProduct.getLastValue())) {
+                AuxiliaryOutputWorkingHours auxiliaryOutputWorkingHours = new AuxiliaryOutputWorkingHours();
+                auxiliaryOutputWorkingHours.setInspectionItemClass(insProduct.getInspectionItemClass());//妫�娴嬮」鍒嗙被
+                auxiliaryOutputWorkingHours.setInspectionItem(insProduct.getInspectionItem());//妫�娴嬬埗椤�
+                auxiliaryOutputWorkingHours.setInspectionItemSubclass(insProduct.getInspectionItemSubclass());//妫�娴嬪瓙椤�
+                auxiliaryOutputWorkingHours.setSample(insSampleMapper.selectById(insProduct.getInsSampleId()).getSampleCode());//鏍峰搧缂栧彿
+                auxiliaryOutputWorkingHours.setOrderId(insOrder.getId());//璁㈠崟id
+                auxiliaryOutputWorkingHours.setOrderNo(insOrder.getEntrustCode());//闈炲姞鐝鎵樺崟鍙�
+                auxiliaryOutputWorkingHours.setWorkTime(insProduct.getManHour());//闈炲姞鐝伐鏃�
+                auxiliaryOutputWorkingHours.setAmount(1);//闈炲姞鐝暟閲�
+                auxiliaryOutputWorkingHours.setOutputWorkTime((ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHours.getOvertimeWorkTime()) ? auxiliaryOutputWorkingHours.getOvertimeWorkTime() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHours.getWorkTime()) ? auxiliaryOutputWorkingHours.getWorkTime() : BigDecimal.ZERO));//浜ч噺宸ユ椂
+                auxiliaryOutputWorkingHours.setManHourGroup(insProduct.getManHourGroup());//宸ユ椂鍒嗙粍
+                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                auxiliaryOutputWorkingHours.setDateTime(LocalDateTime.now().toLocalDate().atStartOfDay().format(formatters));//鏃ユ湡
+                LocalDateTime localDateTime = LocalDateTime.now();
+                DateTime parse = DateUtil.parse(localDateTime.format(formatter));
+                auxiliaryOutputWorkingHours.setWeekDay(getWeek(localDateTime.format(formatters)));//鏄熸湡
+                auxiliaryOutputWorkingHours.setWeek(String.valueOf(DateUtil.weekOfYear(DateUtil.offsetDay(parse, 1))));//鍛ㄦ
+                auxiliaryOutputWorkingHours.setCheck(userId);//妫�娴嬩汉
+                auxiliaryOutputWorkingHours.setPrice(insProduct.getPrice());//鍗曚环
+                auxiliaryOutputWorkingHours.setSampleId(insProduct.getInsSampleId());//鏍峰搧id
+                auxiliaryOutputWorkingHours.setInsProductId(insProduct.getId());//妫�楠岄」id
 
-            auxiliaryOutputWorkingHoursMapper.insert(auxiliaryOutputWorkingHours);
+                auxiliaryOutputWorkingHoursMapper.insert(auxiliaryOutputWorkingHours);
 
+            }
         }
     }
 

--
Gitblit v1.9.3