From fbd4ecb70baf2e671876ca809a81f6e6fe7342ee Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期日, 20 九月 2026 19:52:50 +0800
Subject: [PATCH] feat(inspect): 新增检测标准方法报告文本功能并优化报告生成 - 委托编号生成逻辑调整为下单时生成并校验唯一性,避免审核时重复 - 新增标准模板价格字段及对应的数据模型和数据库映射 - 订单费用详情查询逻辑重构为基于模板价格计算方式 - 新增标准模板与设备绑定关系的数据结构和管理功能 - 委托编号唯一性校验逻辑增强

---
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderRatesServiceImpl.java |    6 
 inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderRatesMapper.java            |    7 
 basic-server/src/main/java/com/ruoyi/basic/dto/StandardTreeTemplateBindingVo.java         |   11 +
 inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderMapper.java                 |    4 
 basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeTemplateDeviceMapper.java   |   13 +
 inspect-server/src/main/resources/static/inspection-report-template-v2.docx               |    0 
 inspect-server/src/main/java/com/ruoyi/inspect/util/ReportSignaturePictureUtils.java      |   41 +++++
 basic-server/src/main/resources/mapper/StandardTreeTemplateDeviceMapper.xml               |   10 +
 inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderRatesController.java    |    5 
 inspect-server/src/main/resources/mapper/InsOrderRatesMapper.xml                          |   27 +-
 inspect-server/src/main/java/com/ruoyi/inspect/dto/TemplateRateDto.java                   |   16 ++
 inspect-server/src/main/resources/mapper/InsOrderMapper.xml                               |   17 ++
 basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java                     |    7 
 basic-server/src/main/resources/mapper/StandardTemplateMapper.xml                         |    2 
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java     |    9 
 basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java  |    9 +
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java      |   90 ++++++++--
 basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTreeTemplateDevice.java           |   39 ++++
 basic-server/src/main/java/com/ruoyi/basic/dto/TemplateBindingItemDto.java                |    8 +
 basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java      |   46 +++++
 inspect-server/src/main/resources/static/detection-report-template-v2.docx                |    0 
 inspect-server/src/main/java/com/ruoyi/inspect/service/InsOrderRatesService.java          |    9 +
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java  |   51 +++--
 23 files changed, 361 insertions(+), 66 deletions(-)

diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/StandardTreeTemplateBindingVo.java b/basic-server/src/main/java/com/ruoyi/basic/dto/StandardTreeTemplateBindingVo.java
index 31b0672..2e8ed7c 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/dto/StandardTreeTemplateBindingVo.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/StandardTreeTemplateBindingVo.java
@@ -1,12 +1,23 @@
 package com.ruoyi.basic.dto;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
 
 @Data
 public class StandardTreeTemplateBindingVo {
+    @ApiModelProperty("妯℃澘ID")
     private Integer templateId;
+    @ApiModelProperty("妯℃澘鍚嶇О")
     private String name;
+    @ApiModelProperty("妫�楠岄」鐩�")
     private String number;
+    @ApiModelProperty("澶囨敞")
     private String remark;
+    @ApiModelProperty("鎺掑簭")
     private Integer sort;
+    @ApiModelProperty("璁惧ID闆嗗悎")
+    private List<Integer> deviceIds = new ArrayList<>();
 }
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/TemplateBindingItemDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/TemplateBindingItemDto.java
index 3c4381f..64a07e9 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/dto/TemplateBindingItemDto.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/TemplateBindingItemDto.java
@@ -1,9 +1,17 @@
 package com.ruoyi.basic.dto;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
 
 @Data
 public class TemplateBindingItemDto {
+    @ApiModelProperty("妯℃澘ID")
     private Integer templateId;
+    @ApiModelProperty("鎺掑簭")
     private Integer sort;
+    @ApiModelProperty("璁惧ID闆嗗悎")
+    private List<Integer> deviceIds = new ArrayList<>();
 }
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeTemplateDeviceMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeTemplateDeviceMapper.java
new file mode 100644
index 0000000..030f40d
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeTemplateDeviceMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.basic.pojo.StandardTreeTemplateDevice;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/** 鏍囧噯妯℃澘榛樿璁惧 Mapper銆� */
+public interface StandardTreeTemplateDeviceMapper extends BaseMapper<StandardTreeTemplateDevice> {
+
+    List<Integer> selectExistingDeviceIds(@Param("deviceIds") List<Integer> deviceIds);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java
index e26971f..87bf387 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java
@@ -6,6 +6,7 @@
 import lombok.Data;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 /**
@@ -73,4 +74,10 @@
      */
     @ApiModelProperty("妯℃澘缂栧彿")
     private String number;
+
+    /**
+     * 浠锋牸(鍏�)
+     */
+    @ApiModelProperty("浠锋牸(鍏�)")
+    private BigDecimal price;
 }
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTreeTemplateDevice.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTreeTemplateDevice.java
new file mode 100644
index 0000000..d734955
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTreeTemplateDevice.java
@@ -0,0 +1,39 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/** 鏍囧噯涓嬪師濮嬭褰曟ā鏉夸笌榛樿璁惧鐨勭粦瀹氬叧绯汇�� */
+@Data
+@TableName("standard_tree_template_device")
+public class StandardTreeTemplateDevice {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    private Integer standardTreeId;
+
+    private Integer templateId;
+
+    private Integer deviceId;
+
+    private Integer sort;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java
index 5e7530a..fcf020a 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java
@@ -50,6 +50,9 @@
                     StandardTemplate::getNumber);
             standardTemplate.setNumber(giveCode);
         }
+        if (standardTemplate.getPrice() == null) {
+            standardTemplate.setPrice(java.math.BigDecimal.ZERO);
+        }
         if (StringUtils.isNotBlank(standardTemplate.getThing())) {
             standardTemplate.setThing(GZipUtil.compress(standardTemplate.getThing()));
         } else {
@@ -60,6 +63,9 @@
 
     @Override
     public int upStandardTemplate(StandardTemplate standardTemplate) {
+        if (standardTemplate.getPrice() == null) {
+            standardTemplate.setPrice(java.math.BigDecimal.ZERO);
+        }
         if (StringUtils.isNotBlank(standardTemplate.getThing())) {
             standardTemplate.setThing(GZipUtil.compress(standardTemplate.getThing()));
         } else {
@@ -128,6 +134,9 @@
         // 鏌ヨ鏃фā鏉�
         StandardTemplate standardTemplate = baseMapper.selectById(newTemplate.getId());
         newTemplate.setThing(standardTemplate.getThing());
+        if (newTemplate.getPrice() == null) {
+            newTemplate.setPrice(java.math.BigDecimal.ZERO);
+        }
 
         if (StringUtils.isBlank(newTemplate.getNumber())) {
             String giveCode = numberGenerator.generateNumberWithPrefix(5,
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
index 280d3c5..8b5ae45 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
@@ -18,6 +18,7 @@
 import com.ruoyi.basic.mapper.StandardProductListMapper;
 import com.ruoyi.basic.mapper.StandardTreeMapper;
 import com.ruoyi.basic.mapper.StandardTreeTemplateBindingMapper;
+import com.ruoyi.basic.mapper.StandardTreeTemplateDeviceMapper;
 import com.ruoyi.basic.mapper.StructureItemParameterMapper;
 import com.ruoyi.basic.mapper.StructureTestObjectMapper;
 import com.ruoyi.basic.pojo.Laboratory;
@@ -25,6 +26,7 @@
 import com.ruoyi.basic.pojo.StandardTree;
 import com.ruoyi.basic.pojo.StandardTemplate;
 import com.ruoyi.basic.pojo.StandardTreeTemplateBinding;
+import com.ruoyi.basic.pojo.StandardTreeTemplateDevice;
 import com.ruoyi.basic.pojo.StructureItemParameter;
 import com.ruoyi.basic.pojo.StructureTestObject;
 import com.ruoyi.basic.service.StandardTreeService;
@@ -45,6 +47,7 @@
 import java.util.HashSet;
 import java.util.Comparator;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author Administrator
@@ -68,6 +71,8 @@
     private LaboratoryMapper laboratoryMapper;
 
     private StandardTreeTemplateBindingMapper standardTreeTemplateBindingMapper;
+
+    private StandardTreeTemplateDeviceMapper standardTreeTemplateDeviceMapper;
 
     private StandardTemplateService standardTemplateService;
 
@@ -204,6 +209,8 @@
         }
         standardTreeTemplateBindingMapper.delete(Wrappers.<StandardTreeTemplateBinding>lambdaQuery()
                 .eq(StandardTreeTemplateBinding::getStandardTreeId, standardTree.getId()));
+        standardTreeTemplateDeviceMapper.delete(Wrappers.<StandardTreeTemplateDevice>lambdaQuery()
+                .eq(StandardTreeTemplateDevice::getStandardTreeId, standardTree.getId()));
         standardTreeMapper.deleteById(standardTree.getId());
         standardProductListMapper.delete(Wrappers.<StandardProductList>lambdaQuery()
                 .eq(StandardProductList::getLaboratory, industry)
@@ -384,6 +391,15 @@
                 Wrappers.<StandardTreeTemplateBinding>lambdaQuery()
                         .eq(StandardTreeTemplateBinding::getStandardTreeId, standardTreeId)
                         .orderByAsc(StandardTreeTemplateBinding::getSort, StandardTreeTemplateBinding::getId));
+        Map<Integer, List<Integer>> deviceIdsByTemplate = standardTreeTemplateDeviceMapper.selectList(
+                        Wrappers.<StandardTreeTemplateDevice>lambdaQuery()
+                                .eq(StandardTreeTemplateDevice::getStandardTreeId, standardTreeId)
+                                .orderByAsc(StandardTreeTemplateDevice::getSort,
+                                        StandardTreeTemplateDevice::getId))
+                .stream().collect(Collectors.groupingBy(
+                        StandardTreeTemplateDevice::getTemplateId,
+                        LinkedHashMap::new,
+                        Collectors.mapping(StandardTreeTemplateDevice::getDeviceId, Collectors.toList())));
         List<StandardTreeTemplateBindingVo> result = new ArrayList<>();
         for (StandardTreeTemplateBinding binding : bindings) {
             StandardTemplate template = standardTemplateService.getById(binding.getTemplateId());
@@ -396,6 +412,7 @@
             vo.setNumber(template.getNumber());
             vo.setRemark(template.getRemark());
             vo.setSort(binding.getSort());
+            vo.setDeviceIds(deviceIdsByTemplate.getOrDefault(template.getId(), new ArrayList<>()));
             result.add(vo);
         }
         return result;
@@ -410,6 +427,7 @@
         ensureTwoLevelStandard(dto.getStandardTreeId());
         List<TemplateBindingItemDto> templates = dto.getTemplates() == null ? new ArrayList<>() : dto.getTemplates();
         Set<Integer> templateIds = new HashSet<>();
+        Set<Integer> allDeviceIds = new HashSet<>();
         List<StandardTreeTemplateBinding> bindings = new ArrayList<>();
         int index = 0;
         for (TemplateBindingItemDto item : templates) {
@@ -425,12 +443,38 @@
             binding.setTemplateId(item.getTemplateId());
             binding.setSort(item.getSort() == null ? index : item.getSort());
             bindings.add(binding);
+            if (item.getDeviceIds() != null) {
+                allDeviceIds.addAll(item.getDeviceIds().stream()
+                        .filter(Objects::nonNull).collect(Collectors.toSet()));
+            }
             index++;
         }
+        if (!allDeviceIds.isEmpty()) {
+            List<Integer> requestedDeviceIds = new ArrayList<>(allDeviceIds);
+            if (standardTreeTemplateDeviceMapper.selectExistingDeviceIds(requestedDeviceIds).size()
+                    != requestedDeviceIds.size()) {
+                throw new BaseException("鎵�閫夎澶囦笉瀛樺湪锛岃鍒锋柊璁惧鍒楄〃鍚庨噸璇�");
+            }
+        }
+        standardTreeTemplateDeviceMapper.delete(Wrappers.<StandardTreeTemplateDevice>lambdaQuery()
+                .eq(StandardTreeTemplateDevice::getStandardTreeId, dto.getStandardTreeId()));
         standardTreeTemplateBindingMapper.delete(Wrappers.<StandardTreeTemplateBinding>lambdaQuery()
                 .eq(StandardTreeTemplateBinding::getStandardTreeId, dto.getStandardTreeId()));
-        for (StandardTreeTemplateBinding binding : bindings) {
+        for (int bindingIndex = 0; bindingIndex < bindings.size(); bindingIndex++) {
+            StandardTreeTemplateBinding binding = bindings.get(bindingIndex);
             standardTreeTemplateBindingMapper.insert(binding);
+            TemplateBindingItemDto item = templates.get(bindingIndex);
+            List<Integer> deviceIds = item.getDeviceIds() == null ? new ArrayList<>()
+                    : item.getDeviceIds().stream().filter(Objects::nonNull).distinct()
+                            .collect(Collectors.toList());
+            for (int deviceIndex = 0; deviceIndex < deviceIds.size(); deviceIndex++) {
+                StandardTreeTemplateDevice relation = new StandardTreeTemplateDevice();
+                relation.setStandardTreeId(dto.getStandardTreeId());
+                relation.setTemplateId(item.getTemplateId());
+                relation.setDeviceId(deviceIds.get(deviceIndex));
+                relation.setSort(deviceIndex);
+                standardTreeTemplateDeviceMapper.insert(relation);
+            }
         }
         return true;
     }
diff --git a/basic-server/src/main/resources/mapper/StandardTemplateMapper.xml b/basic-server/src/main/resources/mapper/StandardTemplateMapper.xml
index dbf9d94..a3d74b0 100644
--- a/basic-server/src/main/resources/mapper/StandardTemplateMapper.xml
+++ b/basic-server/src/main/resources/mapper/StandardTemplateMapper.xml
@@ -17,7 +17,7 @@
 
     <select id="selectStandardTemplatePageList" resultType="com.ruoyi.basic.pojo.StandardTemplate">
         select * from (
-        select st.id, st.name,st.number, st.remark, u2.name create_user_name, u3.name update_user_name, st.create_time, st.update_time
+        select st.id, st.name,st.number, st.price, st.remark, u2.name create_user_name, u3.name update_user_name, st.create_time, st.update_time
         from standard_template st
         left join user u2 on u2.id = st.create_user
         left join user u3 on u3.id = st.update_user
diff --git a/basic-server/src/main/resources/mapper/StandardTreeTemplateDeviceMapper.xml b/basic-server/src/main/resources/mapper/StandardTreeTemplateDeviceMapper.xml
new file mode 100644
index 0000000..894e3f0
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StandardTreeTemplateDeviceMapper.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.basic.mapper.StandardTreeTemplateDeviceMapper">
+    <select id="selectExistingDeviceIds" resultType="java.lang.Integer">
+        select id from device where id in
+        <foreach collection='deviceIds' item='deviceId' open='(' separator=',' close=')'>
+            #{deviceId}
+        </foreach>
+    </select>
+</mapper>
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderRatesController.java b/inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderRatesController.java
index 1d3a486..f83e310 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderRatesController.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/controller/InsOrderRatesController.java
@@ -2,11 +2,9 @@
 
 
 
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.core.domain.Result;
 import com.ruoyi.inspect.dto.SampleOrderDto;
-import com.ruoyi.inspect.pojo.InsOrderRates;
 import com.ruoyi.inspect.service.InsOrderRatesService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -51,8 +49,7 @@
     @ApiOperation(value = "鏌ヨ璁㈠崟璐圭敤璇︽儏")
     @GetMapping("/selectRatesDetail")
     public Result selectRatesDetail(Page page, Integer insOrderId) {
-        return Result.success(insOrderRatesService.page(page, Wrappers.<InsOrderRates>lambdaQuery()
-                .eq(InsOrderRates::getInsOrderId, insOrderId)));
+        return Result.success(insOrderRatesService.selectTemplateRatesDetail(page, insOrderId));
     }
 
 }
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/dto/TemplateRateDto.java b/inspect-server/src/main/java/com/ruoyi/inspect/dto/TemplateRateDto.java
new file mode 100644
index 0000000..8227fdb
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/dto/TemplateRateDto.java
@@ -0,0 +1,16 @@
+package com.ruoyi.inspect.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class TemplateRateDto {
+    @ApiModelProperty("妫�楠岄」鐩�")
+    private String number;
+    @ApiModelProperty("妯℃澘鍚嶇О")
+    private String name;
+    @ApiModelProperty("浠锋牸(鍏�)")
+    private BigDecimal price;
+}
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderMapper.java b/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderMapper.java
index 41421a5..d418b17 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderMapper.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderMapper.java
@@ -42,6 +42,10 @@
 
     String getStandardMethodCode(@Param("id") Integer id);
 
+    String getStandardMethodReportText(@Param("id") Integer id);
+
+    String getStandardMethodReportTextByCode(@Param("code") String code);
+
     int updateStatus(@Param("id") Integer id);
 
     String selLaboratoryCode(@Param("laboratory") String laboratory);
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderRatesMapper.java b/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderRatesMapper.java
index 8464b1c..b139164 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderRatesMapper.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderRatesMapper.java
@@ -5,6 +5,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.inspect.dto.SampleOrderDto;
+import com.ruoyi.inspect.dto.TemplateRateDto;
 import com.ruoyi.inspect.pojo.InsOrderRates;
 import org.apache.ibatis.annotations.Param;
 
@@ -21,5 +22,11 @@
      * @return
      */
     IPage<SampleOrderDto> selectInsOrderRates(Page page, @Param("ew") QueryWrapper<SampleOrderDto> ew);
+
+    /**
+     * 鏌ヨ璁㈠崟璐圭敤璇︽儏锛堟ā鏉夸环鏍硷級
+     * @return
+     */
+    IPage<TemplateRateDto> selectTemplateRatesDetail(Page page, @Param("insOrderId") Integer insOrderId);
 }
 
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/InsOrderRatesService.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/InsOrderRatesService.java
index 8aa80fa..1e3726f 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/InsOrderRatesService.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/InsOrderRatesService.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.inspect.dto.SampleOrderDto;
+import com.ruoyi.inspect.dto.TemplateRateDto;
 import com.ruoyi.inspect.pojo.InsOrderRates;
 
 /**
@@ -21,5 +22,13 @@
      * @return
      */
     IPage<SampleOrderDto> selectInsOrderRates(Page page, SampleOrderDto sampleOrderDto);
+
+    /**
+     * 鏌ヨ璁㈠崟璐圭敤璇︽儏锛堟ā鏉夸环鏍硷級
+     * @param page
+     * @param insOrderId
+     * @return
+     */
+    IPage<TemplateRateDto> selectTemplateRatesDetail(Page page, Integer insOrderId);
 }
 
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 1b0aee8..dff3ad5 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
@@ -46,6 +46,7 @@
 import com.ruoyi.inspect.service.*;
 import com.ruoyi.inspect.util.HackLoopTableRenderPolicy;
 import com.ruoyi.inspect.util.PreserveReportPicturePlaceholderHandler;
+import com.ruoyi.inspect.util.ReportSignaturePictureUtils;
 import com.ruoyi.inspect.vo.InsOrderPlanTaskSwitchVo;
 import com.ruoyi.inspect.vo.InsOrderPlanVO;
 import com.ruoyi.inspect.vo.InsSampleUserVO;
@@ -1217,13 +1218,12 @@
                 .last("FOR UPDATE"));
         boolean isInspectionReport = Objects.equals(INSPECTION_REPORT, reportType);
         registerInsResults = isInspectionReport && Boolean.TRUE.equals(registerInsResults);
-        // 1. 鍒ゆ柇鏄惁鏈夐噸澶嶇紪鍙�, 鏈夐噸澶嶇紪鍙峰仛鎻愰啋
+        // 1. 濮旀墭缂栧彿鍏ㄥ眬鍞竴锛屾彁浜ゅ鏍告椂鍐嶆鏍¢獙锛岄槻姝㈠苟鍙戞垨鍘嗗彶鏁版嵁缁曡繃鐢熸垚鏍¢獙銆�
         Long codeCount = insOrderMapper.selectCount(Wrappers.<InsOrder>lambdaQuery()
-                .ne(InsOrder::getState, -1)
-                .ne(InsOrder::getIfsInventoryId, order.getIfsInventoryId())
+                .ne(InsOrder::getId, orderId)
                 .eq(InsOrder::getEntrustCode, order.getEntrustCode()));
         if (codeCount > 0) {
-            throw new ErrorException("褰撳墠缂栧彿鏈夐噸澶�, 璇峰厛鍘讳慨鏀归噸澶嶇紪鍙�");
+            throw new ErrorException("鏍峰搧/濮旀墭鍗曞凡瀛樺湪锛岃纭鏍峰搧缂栧彿");
         }
 
         // 2. 鍒ゆ柇璇ヨ鍗曟槸鍚︽槸绗竴娆$敓浜�(鍚庣画鎶ュ憡鐢熸垚鍙彇绗竴娆℃彁浜ゆ椂闂�)
@@ -1985,13 +1985,13 @@
                 || report.getExamineTime() != null;
         if (submitted) {
             User writer = getReportSigner(report.getWriteUserId(), "缂栧埗浜�");
-            marks.put("writeUrl", Pictures.ofLocal(imgUrl + "/" + writer.getSignatureUrl()).create());
+            marks.put("writeUrl", ReportSignaturePictureUtils.create(imgUrl, writer.getSignatureUrl()));
             marks.put("writeDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(report.getWriteTime())).create());
-            marks.put("insUrl", Pictures.ofLocal(imgUrl + "/" + writer.getSignatureUrl()).create());
+            marks.put("insUrl", ReportSignaturePictureUtils.create(imgUrl, writer.getSignatureUrl()));
         }
         if (Objects.equals(report.getIsExamine(), 1)) {
             User examiner = getReportSigner(report.getExamineUserId(), "瀹℃牳浜�");
-            marks.put("examineUrl", Pictures.ofLocal(imgUrl + "/" + examiner.getSignatureUrl()).create());
+            marks.put("examineUrl", ReportSignaturePictureUtils.create(imgUrl, examiner.getSignatureUrl()));
             marks.put("examineDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(report.getExamineTime())).create());
         }
         return marks;
@@ -2536,13 +2536,18 @@
         enterFactoryReport.setLotBatchNo(ifsInventoryQuantity.getUpdateBatchNo());
 
         // 妫�娴嬩緷鎹�
-        Set<String> standardMethod = new HashSet<>();
+        Set<String> standardMethod = new LinkedHashSet<>();
         StringBuilder standardMethod2 = new StringBuilder();
-        standardMethod.add(baseMapper.getStandardMethodCode(insSample.getStandardMethodListId()));
+        String reportStandardMethod = baseMapper.getStandardMethodReportText(insSample.getStandardMethodListId());
+        if (StringUtils.isNotBlank(reportStandardMethod)) {
+            standardMethod.add(reportStandardMethod);
+        }
         for (String s : standardMethod) {
             standardMethod2.append("銆�").append(s);
         }
-        standardMethod2.replace(0, 1, "");
+        if (standardMethod2.length() > 0) {
+            standardMethod2.deleteCharAt(0);
+        }
 
         // 鏍峰搧绫诲瀷
         String orderType = iSysDictTypeService.selectLabelByDict(DictDataConstants.CHECK_TYPE, insOrder.getOrderType());
@@ -3214,7 +3219,7 @@
         insReport.setReportType(reportType);
         boolean showResult = Objects.equals(reportType, INSPECTION_REPORT);
         List<Map<String, Object>> tables = new ArrayList<>();
-        Set<String> standardMethod = new HashSet<>();
+        Set<String> standardMethod = new LinkedHashSet<>();
         Set<String> deviceSet = new HashSet<>();
         Set<String> models = new HashSet<>();
         // 鏌ヨ妫�楠岄」鏁伴噺
@@ -3227,11 +3232,13 @@
         /*鍩虹鎶ュ憡(鏍规嵁缁樺埗鐨勫師濮嬭褰曟ā鐗堝舰鎴�)*/
         samples.forEach(a -> {
             models.add(a.getModel());
-            String standardMethodCode = baseMapper.getStandardMethodCode(a.getStandardMethodListId());
-            if (StrUtil.isNotBlank(a.getSpecialStandardMethod())) {
-                standardMethodCode = standardMethodCode + "+" + a.getSpecialStandardMethod();
+            String standardMethodCode = baseMapper.getStandardMethodReportText(a.getStandardMethodListId());
+            if (StrUtil.isNotBlank(standardMethodCode)) {
+                if (StrUtil.isNotBlank(a.getSpecialStandardMethod())) {
+                    standardMethodCode = standardMethodCode + "+" + a.getSpecialStandardMethod();
+                }
+                standardMethod.add(standardMethodCode);
             }
-            standardMethod.add(standardMethodCode);
             for (InsProduct b : a.getInsProduct()) {
                 if (b.getInsProductResult() != null) {
                     List<JSONObject> jsonObjects = JSON.parseArray(b.getInsProductResult().getEquipValue(), JSONObject.class);
@@ -3577,9 +3584,14 @@
         if (firstInspectDate == null) {
             firstInspectDate = insOrder.getSendTime();
         }
+        if (firstInspectDate == null) {
+            firstInspectDate = submitTime;
+        }
 
         String insTime = firstInspectDate.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�")) + "-"
                 + submitTime.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�"));
+        String testStartDate = firstInspectDate.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�"));
+        String testEndDate = submitTime.format(DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�"));
 
         String insTimeEn = monthNames[firstInspectDate.getMonthValue() - 1] + " " + firstInspectDate.format(DateTimeFormatter.ofPattern("dd, yyyy")) + "-"
                 + monthNames[submitTime.getMonthValue() - 1] + " " + submitTime.format(DateTimeFormatter.ofPattern("dd, yyyy"));
@@ -3636,11 +3648,8 @@
                 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("锛�"));
+            standardMethodText = defaultReportText(
+                    baseMapper.getStandardMethodReportTextByCode(insOrder.getSample()), insOrder.getSample());
         }
         boolean containsOrganicChlorine = detectionResultRows.stream()
                 .map(row -> row.get("itemName"))
@@ -3729,6 +3738,8 @@
                     put("batch", finalBatchNo);
                     put("phone", defaultReportText(insOrder.getPhone(), "/"));
                     put("testDate", insTime);
+                    put("testStartDate", testStartDate);
+                    put("testEndDate", testEndDate);
                     put("entrustNo", defaultReportText(insOrder.getEntrustCode(), "/"));
                     put("sampling", "/");
                     put("standard", finalStandardMethodText);
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderRatesServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderRatesServiceImpl.java
index 43178e5..9b3066f 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderRatesServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderRatesServiceImpl.java
@@ -5,6 +5,7 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.QueryWrappers;
 import com.ruoyi.inspect.dto.SampleOrderDto;
+import com.ruoyi.inspect.dto.TemplateRateDto;
 import com.ruoyi.inspect.mapper.InsOrderRatesMapper;
 import com.ruoyi.inspect.pojo.InsOrderRates;
 import com.ruoyi.inspect.service.InsOrderRatesService;
@@ -29,5 +30,10 @@
     public IPage<SampleOrderDto> selectInsOrderRates(Page page, SampleOrderDto sampleOrderDto) {
         return baseMapper.selectInsOrderRates(page, QueryWrappers.queryWrappers(sampleOrderDto));
     }
+
+    @Override
+    public IPage<TemplateRateDto> selectTemplateRatesDetail(Page page, Integer insOrderId) {
+        return baseMapper.selectTemplateRatesDetail(page, insOrderId);
+    }
 }
 
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
index d7c0021..5be630d 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderServiceImpl.java
@@ -364,6 +364,15 @@
                 }
             }
         });
+        // 涓嬪崟鏃剁敓鎴愬鎵樼紪鍙峰苟鏍¢獙鍞竴鎬э紱瀛e害妫�楠屽鐢ㄨ繘鍘傛楠岀紪鍙凤紝鐣欏緟瀹℃牳澶勭悊銆�
+        if (!InsOrderTypeConstants.QUARTERLY_TEST.equals(insOrder.getOrderType())) {
+            String entrustCode = buildEntrustCode(insOrder, Collections.emptyList());
+            assertEntrustCodeUnique(entrustCode, insOrder.getId());
+            insOrder.setEntrustCode(entrustCode);
+            insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
+                    .eq(InsOrder::getId, insOrder.getId())
+                    .set(InsOrder::getEntrustCode, entrustCode));
+        }
         //鍘熸潗鏂欎笅鍗曟垨澶栬喘鎴愬搧涓嬪崟
         if (Objects.nonNull(insOrder.getTypeSource())&&Objects.nonNull(insOrder.getIfsInventoryId())) {
             // 濮旀墭浜哄氨鏄姤妫�浜�, 鐢熶骇鍗曚綅灏辨槸渚涘簲鍟嗗崟浣�
@@ -573,11 +582,19 @@
             product.setSort(productSort++);
             insProductMapper.insert(product);
         }
-        saveTemplateSnapshots(order.getId(), selections);
+        saveTemplateSnapshots(order.getId(), selections, bindingMap);
+
+        // 涓嬪崟鏃剁敓鎴愬鎵樼紪鍙峰苟鏍¢獙鍞竴鎬э紝閲嶅鍒欐彁绀猴紝閬垮厤鐣欏埌瀹℃牳鎵嶆姤閿欍��
+        String entrustCode = buildEntrustCode(order, Collections.singletonList(sample));
+        assertEntrustCodeUnique(entrustCode, order.getId());
+        insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
+                .eq(InsOrder::getId, order.getId())
+                .set(InsOrder::getEntrustCode, entrustCode));
         return order.getId();
     }
 
-    private void saveTemplateSnapshots(Integer orderId, List<OrderTemplateSelectionDto> selections) {
+    private void saveTemplateSnapshots(Integer orderId, List<OrderTemplateSelectionDto> selections,
+                                       Map<Integer, StandardTreeTemplateBindingVo> bindingMap) {
         for (OrderTemplateSelectionDto selection : selections) {
             StandardTemplate template = standardTemplateService.getById(selection.getTemplateId());
             if (template == null) {
@@ -592,6 +609,18 @@
             snapshot.setThing(template.getThing());
             snapshot.setSort(selection.getSort());
             insOrderStandardTemplateMapper.insert(snapshot);
+
+            StandardTreeTemplateBindingVo binding = bindingMap.get(selection.getTemplateId());
+            List<Integer> deviceIds = binding == null || binding.getDeviceIds() == null
+                    ? Collections.emptyList() : binding.getDeviceIds();
+            for (int index = 0; index < deviceIds.size(); index++) {
+                InsOrderTemplateDevice relation = new InsOrderTemplateDevice();
+                relation.setInsOrderId(orderId);
+                relation.setTemplateId(selection.getTemplateId());
+                relation.setDeviceId(deviceIds.get(index));
+                relation.setSort(index);
+                insOrderTemplateDeviceMapper.insert(relation);
+            }
         }
     }
 
@@ -675,30 +704,12 @@
     public int upInsOrderOfState(InsOrder insOrder) {
         insOrder.setExamineTime(LocalDateTime.now());
         if (insOrder.getState() == 1) {
-            //瀹℃牳閫氳繃鎵嶄細鐢熸垚濮旀墭缂栧彿
+            //濮旀墭缂栧彿宸插湪涓嬪崟鏃剁敓鎴愬苟鏍¢獙鍞竴鎬э紝瀹℃牳鏃跺鐢紱鍘嗗彶/瀛e害妫�楠岃鍗曞厹搴曠敓鎴愩��
             InsOrder order = this.getById(insOrder.getId());
             List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
                     .eq(InsSample::getInsOrderId, insOrder.getId())
                     .orderByAsc(InsSample::getId));
-            // 濮旀墭缂栧彿鎸夐�佹牱鏃ユ湡鐢熸垚锛涙柊鑱氬崟鏍峰搧璁㈠崟鐨勬湯涓や綅鍙栨牱鍝佺紪鍙锋湯涓や綅銆�
-            // 鍘嗗彶/澶栭儴璁㈠崟鏈~鍐欓�佹牱鏃ユ湡鏃跺洖閫�鍒板綋澶╋紝閬垮厤褰卞搷鍘熸湁娴佺▼銆�
-            LocalDate entrustDate = order.getSampleDate() == null ? LocalDate.now() : order.getSampleDate();
-            String entrustCodePrefix = "LMSY-"
-                    + entrustDate.format(DateTimeFormatter.BASIC_ISO_DATE)
-                    + "-";
-            String no;
-            if (isDirectTemplateOrder(order, insSamples)) {
-                String sampleCode = insSamples.get(0).getSampleCode();
-                if (StringUtils.isBlank(sampleCode) || sampleCode.trim().length() < 2) {
-                    throw new ErrorException("鏍峰搧缂栧彿涓嶈兘涓虹┖涓斾笉鑳藉皯浜�2浣�");
-                }
-                sampleCode = sampleCode.trim();
-                no = entrustCodePrefix + sampleCode.substring(sampleCode.length() - 2);
-            } else {
-                no = numberGenerator.generateNumberWithPrefix(2,
-                        entrustCodePrefix,
-                        InsOrder::getEntrustCode);
-            }
+            String no = order.getEntrustCode();
             // 鍒ゆ柇鏄惁鏄搴︽楠�, 鏄搴︽楠屽彇娑堝師鏉愭枡瀛e害妫�楠屼笅鍗�
             if (InsOrderTypeConstants.QUARTERLY_TEST.equals(order.getOrderType())) {
                 ifsInventoryQuantityMapper.update(null,  Wrappers.<IfsInventoryQuantity>lambdaUpdate()
@@ -714,6 +725,10 @@
                   no = order1.getEntrustCode();
                 }
             }
+            if (StringUtils.isBlank(no)) {
+                no = buildEntrustCode(order, insSamples);
+            }
+            assertEntrustCodeUnique(no, order.getId());
 
             int count = 1;
             for (InsSample insSample : insSamples) {
@@ -734,6 +749,37 @@
         return insOrderMapper.updateById(insOrder);
     }
 
+    /**
+     * 濮旀墭缂栧彿鍏ㄥ眬鍞竴锛岀敓鎴愮紪鍙峰拰鍚庣画鎻愪氦鍓嶅潎闇�鎺掗櫎褰撳墠璁㈠崟鍚庢牎楠屻��
+     */
+    private void assertEntrustCodeUnique(String entrustCode, Integer currentOrderId) {
+        Long count = insOrderMapper.selectCount(Wrappers.<InsOrder>lambdaQuery()
+                .eq(InsOrder::getEntrustCode, entrustCode)
+                .ne(currentOrderId != null, InsOrder::getId, currentOrderId));
+        if (count > 0) {
+            throw new ErrorException("鏍峰搧/濮旀墭鍗曞凡瀛樺湪锛岃纭鏍峰搧缂栧彿");
+        }
+    }
+
+    /**
+     * 鐢熸垚濮旀墭缂栧彿锛氭柊鑱氱洿缁戞ā鏉胯鍗曟湯涓や綅鍙栨牱鍝佺紪鍙锋湯涓や綅锛屽叾浣欐寜閫佹牱鏃ユ湡鐢熸垚搴忓彿銆�
+     */
+    private String buildEntrustCode(InsOrder order, List<InsSample> insSamples) {
+        LocalDate entrustDate = order.getSampleDate() == null ? LocalDate.now() : order.getSampleDate();
+        String entrustCodePrefix = "LMSY-"
+                + entrustDate.format(DateTimeFormatter.BASIC_ISO_DATE)
+                + "-";
+        if (isDirectTemplateOrder(order, insSamples)) {
+            String sampleCode = insSamples.get(0).getSampleCode();
+            if (StringUtils.isBlank(sampleCode) || sampleCode.trim().length() < 2) {
+                throw new ErrorException("鏍峰搧缂栧彿涓嶈兘涓虹┖涓斾笉鑳藉皯浜�2浣�");
+            }
+            sampleCode = sampleCode.trim();
+            return entrustCodePrefix + sampleCode.substring(sampleCode.length() - 2);
+        }
+        return numberGenerator.generateNumberWithPrefix(2, entrustCodePrefix, InsOrder::getEntrustCode);
+    }
+
     @Override
     public Map<String, Object> getInsOrderAndSample(Integer id, String laboratory) {
         Map<String, Object> map = new HashMap<>();
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
index 48d4063..bfb7516 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
@@ -46,6 +46,7 @@
 import com.ruoyi.inspect.service.InsReportService;
 import com.ruoyi.inspect.service.RawMaterialOrderService;
 import com.ruoyi.inspect.util.PreserveReportPicturePlaceholderHandler;
+import com.ruoyi.inspect.util.ReportSignaturePictureUtils;
 import com.ruoyi.system.mapper.UserMapper;
 import com.ruoyi.system.service.InformationNotificationService;
 import lombok.extern.slf4j.Slf4j;
@@ -228,9 +229,9 @@
         }
 
         Map<String, Object> writeMarks = new HashMap<String, Object>() {{
-            put("writeUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
+            put("writeUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
             put("writeDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
-            put("insUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
+            put("insUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
         }};
         writeMarksToReportFiles(insReport, writeMarks);
 
@@ -335,7 +336,7 @@
         informationNotificationService.addInformationNotification(info);
         String primaryReportUrl = getPrimaryReportUrl(insReport);
         Map<String, Object> examineMarks = new HashMap<String, Object>() {{
-            put("examineUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
+            put("examineUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
             put("examineDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
         }};
         writeMarksToReportFiles(insReport, examineMarks);
@@ -478,7 +479,7 @@
         String finalUrl = primaryReportUrl.replace("/word", wordUrl);
 
         Map<String, Object> ratifyMarks = new HashMap<String, Object>() {{
-            put("ratifyUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
+            put("ratifyUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
             put("ratifyDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
             put("seal1", Pictures.ofLocal(imgUrl + "/" + sealUrl).create());
             put("seal2", Pictures.ofLocal(imgUrl + "/" + sealUrl).create());
diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/util/ReportSignaturePictureUtils.java b/inspect-server/src/main/java/com/ruoyi/inspect/util/ReportSignaturePictureUtils.java
new file mode 100644
index 0000000..e33f010
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/util/ReportSignaturePictureUtils.java
@@ -0,0 +1,41 @@
+package com.ruoyi.inspect.util;
+
+import com.deepoove.poi.data.PictureRenderData;
+import com.deepoove.poi.data.Pictures;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 鎶ュ憡绛惧悕鍥剧墖宸ュ叿銆�
+ */
+public final class ReportSignaturePictureUtils {
+
+    private static final int MAX_WIDTH = 90;
+    private static final int MAX_HEIGHT = 45;
+
+    private ReportSignaturePictureUtils() {
+    }
+
+    /**
+     * 鎸夊師濮嬫瘮渚嬪皢绛惧悕閫傞厤鍒版姤鍛婄鍚嶅崟鍏冩牸锛岄伩鍏嶅浘鐗囪秺杩囧崟鍏冩牸杈圭晫鑰岃瑁佸壀銆�
+     */
+    public static PictureRenderData create(String imageDirectory, String signatureUrl) {
+        String signaturePath = imageDirectory + "/" + signatureUrl;
+        try {
+            BufferedImage image = ImageIO.read(new File(signaturePath));
+            if (image != null && image.getWidth() > 0 && image.getHeight() > 0) {
+                double scale = Math.min((double) MAX_WIDTH / image.getWidth(),
+                        (double) MAX_HEIGHT / image.getHeight());
+                int width = Math.max(1, (int) Math.round(image.getWidth() * scale));
+                int height = Math.max(1, (int) Math.round(image.getHeight() * scale));
+                return Pictures.ofLocal(signaturePath).size(width, height).create();
+            }
+        } catch (IOException ignored) {
+            // 鍥剧墖鍏冩暟鎹鍙栧け璐ユ椂浠嶅彲灏濊瘯浠ラ粯璁ゅ昂瀵稿啓鍏ユ姤鍛娿��
+        }
+        return Pictures.ofLocal(signaturePath).size(MAX_WIDTH, MAX_HEIGHT).create();
+    }
+}
diff --git a/inspect-server/src/main/resources/mapper/InsOrderMapper.xml b/inspect-server/src/main/resources/mapper/InsOrderMapper.xml
index e5af839..8589361 100644
--- a/inspect-server/src/main/resources/mapper/InsOrderMapper.xml
+++ b/inspect-server/src/main/resources/mapper/InsOrderMapper.xml
@@ -281,6 +281,23 @@
         from standard_method
         where id = #{id}
     </select>
+    <select id="getStandardMethodReportText" resultType="java.lang.String">
+        select case
+                   when name is null or trim(name) = '' then code
+                   else concat(code, '銆�', name, '銆�')
+               end
+        from standard_method
+        where id = #{id}
+    </select>
+    <select id="getStandardMethodReportTextByCode" resultType="java.lang.String">
+        select case
+                   when name is null or trim(name) = '' then code
+                   else concat(code, '銆�', name, '銆�')
+               end
+        from standard_method
+        where code = #{code}
+        limit 1
+    </select>
     <select id="selLaboratoryCode" resultType="java.lang.String">
         select laboratory_code
         from laboratory
diff --git a/inspect-server/src/main/resources/mapper/InsOrderRatesMapper.xml b/inspect-server/src/main/resources/mapper/InsOrderRatesMapper.xml
index 402a50a..4791cf3 100644
--- a/inspect-server/src/main/resources/mapper/InsOrderRatesMapper.xml
+++ b/inspect-server/src/main/resources/mapper/InsOrderRatesMapper.xml
@@ -11,26 +11,25 @@
         then io.sample_view
         else io.sample end                            sampleStr,
         GROUP_CONCAT(DISTINCT isa.model SEPARATOR ' ') AS sample_model,
-        sum(tempior.rates) + 200 total_price
+        COALESCE(sum(st.price), 0) total_price
         from ins_order io
         LEFT JOIN ins_sample isa ON isa.ins_order_id = io.id
-        left join (
-        select ior.id, ior.ins_order_id, ior.rates from
-        ins_order_rates ior
-        left join ins_product ip on ip.id = ior.ins_product_id
-        left join ins_order io2 on ior.ins_order_id = io2.id
-        GROUP BY CASE
-        WHEN ior.man_hour_group IS NOT NULL AND ior.man_hour_group != '' THEN ior.man_hour_group
-        ELSE ior.id END,
-        CASE WHEN ior.man_hour_group IS NOT NULL AND ior.man_hour_group != '' THEN ior.ins_sample_id ELSE ior.id END,
-        CASE WHEN ior.man_hour_group IS NOT NULL AND ior.man_hour_group != '' THEN ip.radius ELSE ior.id END,
-        CASE WHEN ior.man_hour_group IS NOT NULL AND ior.man_hour_group != '' THEN ip.cable_tag ELSE ior.id END,
-        CASE WHEN ior.man_hour_group IS NOT NULL AND ior.man_hour_group != '' THEN ior.ins_order_id ELSE ior.id END) tempior on tempior.ins_order_id = io.id
-        where tempior.id is not null
+        left join ins_order_standard_template iost on iost.ins_order_id = io.id
+        left join standard_template st on st.id = iost.template_id
+        where iost.id is not null
         group by io.id) a
         <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
             ${ew.customSqlSegment}
         </if>
     </select>
 
+    <!-- 鏌ヨ璁㈠崟璐圭敤璇︽儏锛堟ā鏉夸环鏍硷級 -->
+    <select id="selectTemplateRatesDetail" resultType="com.ruoyi.inspect.dto.TemplateRateDto">
+        select iost.number, iost.name, COALESCE(st.price, 0) as price
+        from ins_order_standard_template iost
+        left join standard_template st on st.id = iost.template_id
+        where iost.ins_order_id = #{insOrderId}
+        order by iost.sort, iost.id
+    </select>
+
 </mapper>
diff --git a/inspect-server/src/main/resources/static/detection-report-template-v2.docx b/inspect-server/src/main/resources/static/detection-report-template-v2.docx
index f385f8a..54d6b84 100644
--- a/inspect-server/src/main/resources/static/detection-report-template-v2.docx
+++ b/inspect-server/src/main/resources/static/detection-report-template-v2.docx
Binary files differ
diff --git a/inspect-server/src/main/resources/static/inspection-report-template-v2.docx b/inspect-server/src/main/resources/static/inspection-report-template-v2.docx
index b769824..4bb0c32 100644
--- a/inspect-server/src/main/resources/static/inspection-report-template-v2.docx
+++ b/inspect-server/src/main/resources/static/inspection-report-template-v2.docx
Binary files differ

--
Gitblit v1.9.3