From 8bf9254ba43e744517d4de2516121da2979fd057 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期二, 01 四月 2025 11:29:51 +0800
Subject: [PATCH] 1.检验项目参数导入 2.对象导入

---
 basic-server/src/main/java/com/ruoyi/basic/excel/ExcelMultiSheetImporter.java          |   31 +
 basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java            |  132 ++++++
 basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java  |  321 ++++++++++------
 cnas-device/src/main/java/com/ruoyi/device/mapper/DeviceMapper.java                    |    4 
 pom.xml                                                                                |    2 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonnelHeaderApi.java         |    2 
 basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java |  108 +++-
 cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceServiceImpl.java         |    6 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonDto.java                  |    2 
 basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java     |  247 ------------
 basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java                   |    4 
 basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java       |    6 
 basic-server/src/main/java/com/ruoyi/basic/excel/MultiSheetImportListener.java         |  224 +++++++++++
 13 files changed, 687 insertions(+), 402 deletions(-)

diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java
index 7923abd..97ac1cf 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java
@@ -1,22 +1,18 @@
 package com.ruoyi.basic.controller;
 
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.poi.excel.ExcelUtil;
+
 import com.alibaba.excel.EasyExcel;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.basic.dto.ProductDto;
 import com.ruoyi.basic.dto.StructureTestObjectDto;
+import com.ruoyi.basic.excel.ExcelMultiSheetImporter;
 import com.ruoyi.common.core.domain.Result;
-import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.system.service.ISysDictTypeService;
 import com.ruoyi.basic.dto.PageTestObjectDto;
 import com.ruoyi.basic.dto.ProductDTO1;
 import com.ruoyi.basic.excel.StructureTestObjectData;
 import com.ruoyi.basic.excel.StructureTestObjectListener;
 import com.ruoyi.basic.pojo.Product;
-import com.ruoyi.basic.pojo.StandardTemplate;
 import com.ruoyi.basic.pojo.StructureItemParameter;
 import com.ruoyi.basic.pojo.StructureTestObject;
 import com.ruoyi.basic.service.CapacityScopeService;
@@ -27,18 +23,13 @@
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.lang3.ObjectUtils;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
 
 /**
  * 妫�楠岄」鐩弬鏁�(StructureItemParameter)琛ㄦ帶鍒跺眰
@@ -152,240 +143,16 @@
         return Result.success(capacityScopeService.getItemTree());
     }
 
-
-    @ApiOperation(value = "瑁呭瀵煎叆妫�楠岄」鐩�")
     @PostMapping("/importEquipData")
-    @Transactional
-    public Result importEquipData(@RequestParam("file") MultipartFile file) throws Exception {
-        InputStream inputStream = file.getInputStream();
-        List<StructureItemParameter> lists = new ArrayList<>();
-        AtomicReference<String> sample = new AtomicReference<>();
-        ExcelUtil.readBySax(inputStream, -1, (i, l, list1) -> {
-            if (l == 1) {
-                sample.set(list1.get(1) + "");
-            }
-            if (l >= 1) {
-                StructureItemParameter str = new StructureItemParameter();
-                // 娴嬭瘯瀵硅薄
-                if (list1.get(1) == null) {
-                    str.setSample(null);
-                } else {
-                    String brand = (String) list1.get(1);
-                    StringBuilder builder = new StringBuilder();
-                    builder.append("[");
-                    // 浜у搧
-                    if (ObjectUtil.isNotEmpty(list1.get(2))) {
-                        String production = (String) list1.get(2);
-                        if (!production.contains("锛�")) {
-                            builder.append(String.format("[\"%s\",\"%s\"]", brand, production));
-                        } else {
-                            Arrays.stream(production.split("锛�")).forEach(item -> {
-                                builder.append(String.format("[\"%s\",\"%s\"],", brand, item));
-                            });
-                            builder.deleteCharAt(builder.length() - 1);
-                        }
-                    } else {
-                        builder.append("[");
-                        builder.append(String.format("\"%s\"", brand));
-                        builder.append("]");
-                    }
-                    builder.append("]");
-                    str.setSample(builder.toString());
-                }
-                // 妫�楠岄」
-                str.setInspectionItem(list1.get(4).toString().trim());
-                // 妫�楠岄」鑻辨枃
-                if (list1.get(5) != null) {
-                    str.setInspectionItemEn(list1.get(5).toString());
-                }
-                // 妫�楠屽瓙椤�
-                if (list1.get(6) == null) {
-                    str.setInspectionItemSubclass(null);
-                } else {
-                    str.setInspectionItemSubclass(list1.get(6).toString().trim());
-                }
-                // 妫�楠屽瓙椤硅嫳鏂�
-                if (list1.get(7) == null) {
-                    str.setInspectionItemSubclassEn(null);
-                } else {
-                    str.setInspectionItemSubclassEn(String.valueOf(list1.get(7).toString()));
-                }
-                // 妫�楠岄」鍒嗙被
-                if (list1.get(22) != null && list1.get(22) != "") {
-                    str.setInspectionItemClass(list1.get(22).toString().trim());
-                } else {
-                    str.setInspectionItemClass(null);
-                }
-                // 妫�楠岄」鍒嗙被鑻辨枃
-                if (list1.get(23) != null && list1.get(23) != "") {
-                    str.setInspectionItemClassEn(list1.get(23) + "");
-                } else {
-                    str.setInspectionItemClassEn(null);
-                }
-
-                LambdaQueryWrapper<StructureItemParameter> wrapper = Wrappers.lambdaQuery(StructureItemParameter.class)
-                        .eq(StructureItemParameter::getInspectionItem, str.getInspectionItem())
-                        .eq(StructureItemParameter::getSample, str.getSample())
-
-                        .last("limit 1");
-                // 鍒ゆ柇鏄惁鏈夋楠岄」绫诲瀷
-                if (ObjectUtils.isNotEmpty(str.getInspectionItemClass())) {
-                    wrapper.eq(StructureItemParameter::getInspectionItemClass, str.getInspectionItemClass());
-                }
-
-                // 鍒ゆ柇鏄惁鏈夋楠屽瓙椤�
-                if (ObjectUtils.isNotEmpty(str.getInspectionItemSubclass())) {
-                    wrapper.eq(StructureItemParameter::getInspectionItemSubclass, str.getInspectionItemSubclass());
-                }
-                StructureItemParameter db_str = structureItemParameterService.getOne(wrapper);
-                if (ObjectUtils.isNotEmpty(db_str)) {
-                    str.setId(db_str.getId());
-                }
-                // 鏂规硶鍚嶇О
-                if (list1.get(8) == null) {
-                    str.setMethod(null);
-                } else {
-                    StringBuffer buffer = new StringBuffer();
-                    String input = list1.get(8).toString();
-                    buffer.append("[");
-                    String[] values = input.split("锛�");
-                    for (String value : values) {
-                        buffer.append("\"").append(value.trim()).append("\",");
-                    }
-                    buffer.deleteCharAt(buffer.length() - 1);
-                    buffer.append("]");
-                    str.setMethod(buffer.toString());
-                }
-                // 璇曢獙瀹�
-                if (list1.get(9) == null) {
-                    str.setSonLaboratory(null);
-                } else {
-                    str.setSonLaboratory(list1.get(9).toString());
-                }
-                // 璁¢噺鍗曚綅
-                if (list1.get(10) == null) {
-                    str.setUnit(null);
-                } else {
-                    str.setUnit(list1.get(10).toString());
-                }
-                // 瑕佹眰鍊�
-                if (list1.get(11) == null) {
-                    str.setAskTell(null);
-                } else {
-                    str.setAskTell(list1.get(11).toString());
-                }
-                // 瑕佹眰鎻忚堪
-                if (list1.get(12) == null) {
-                    str.setAsk(null);
-                } else {
-                    str.setAsk(list1.get(12).toString());
-                }
-                // 鍗曚环
-                if (list1.get(13) == null) {
-                    str.setPrice(null);
-                } else {
-                    str.setPrice(list1.get(13) + "");
-                }
-                // 宸ユ椂绯绘暟
-                if (list1.get(14) == null) {
-                    str.setManHour(null);
-                } else {
-                    str.setManHour(Double.valueOf(list1.get(14).toString()));
-                }
-                // 宸ユ椂鍒嗙粍
-                if (list1.get(15) == null) {
-                    str.setManHourGroup(null);
-                } else {
-                    str.setManHourGroup(list1.get(15).toString());
-                }
-                // 棰勮瀹屾垚鏃堕棿
-                if (list1.get(16) == null) {
-                    str.setManDay(null);
-                } else {
-                    str.setManDay(Integer.valueOf(list1.get(16).toString()));
-                }
-                // 鏁版嵁绫诲瀷
-                String jy;
-                if (list1.get(17).toString().equals("闈為噰闆嗙被鍨�")) {
-                    jy = "0";
-                } else {
-                    jy = "1";
-                }
-                str.setInspectionItemType(jy);
-                // 妫�楠岄」绫诲瀷
-                String validateValueType = list1.get(18).toString();
-                if (ObjectUtils.isNotEmpty(validateValueType)) {
-                    List<SysDictData> enums = dictTypeService.selectDictDataByName("妫�楠屽�肩被鍨�")
-                            .stream().filter(sysDictData -> sysDictData.getDictLabel().equals(validateValueType)).collect(Collectors.toList());
-                    str.setInspectionValueType(enums.get(0).getDictValue());
-                }
-                int bsm;
-                //鐗规畩鏍囪瘑
-                if (list1.get(19).toString().equals("鍚�")) {
-                    bsm = 0;
-                } else {
-                    bsm = 1;
-                }
-                str.setBsm(bsm + "");
-                // 鏁板瓧瀛楀吀
-                if (list1.get(20) != null) {
-                    str.setDic(list1.get(20) + "");
-                } else {
-                    str.setDic(null);
-                }
-                // 鍘熷璁板綍妯℃澘
-                StandardTemplate standTempIdByName = standardTemplateService.getStandTempIdByName(String.valueOf(list1.get(21)));
-                if (standTempIdByName != null) {
-                    str.setTemplateId(standTempIdByName.getId());
-                } else {
-                    str.setTemplateId(null);
-                }
-                try {
-                    if (list1.get(24) != null) {
-                        str.setLaboratory(list1.get(24) + "");
-                    }
-                } catch (Exception e) {
-                }
-
-                // 鏉′欢
-                if (list1.get(25) == null) {
-                    str.setRadiusList(null);
-                } else {
-                    StringBuffer buffer = new StringBuffer();
-                    String input = list1.get(25).toString();
-                    buffer.append("[");
-                    String[] values = input.split("锛�");
-                    for (String value : values) {
-                        buffer.append("\"").append(value.trim()).append("\",");
-                    }
-                    buffer.deleteCharAt(buffer.length() - 1);
-                    buffer.append("]");
-                    str.setRadiusList(buffer.toString());
-                }
-                //鏀惰垂鏍囧噯
-                if (list1.get(26) == null) {
-                    str.setRates(null);
-                } else {
-                    str.setRates(list1.get(26) + "");
-                }
-
-                lists.add(str);
-            }
-        });
-//        structureItemParameterService.removeNoSample(sample.get());
-        // 濡傛灉鏁版嵁搴撻噷闈㈢殑鏁版嵁瀛樺湪閭d箞灏辨墽琛屾洿鏂版嫹璐濇搷浣�
-        try {
-            structureItemParameterService.saveOrUpdateBatch(lists);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new RuntimeException("鏈嶅姟绔姤閿�");
-        }
-        return Result.success();
+    public Result importData(@RequestParam("file") MultipartFile file) {
+        // 璋冪敤瀵煎叆宸ュ叿
+        String result = ExcelMultiSheetImporter.importExcel(file, structureItemParameterService, standardTemplateService, dictTypeService);
+        return Result.success(result);
     }
 
     @ApiOperation(value = "瀵煎叆妫�楠屽璞�")
     @PostMapping("/importExcel")
-    public Result importExcel(@RequestParam("file") MultipartFile file){
+    public Result importExcel(@RequestParam("file") MultipartFile file) {
         List<String> processedFiles = new ArrayList<>();
         try (InputStream inputStream = file.getInputStream()) {
             String fileHash = DigestUtils.md5Hex(inputStream);
diff --git a/basic-server/src/main/java/com/ruoyi/basic/excel/ExcelMultiSheetImporter.java b/basic-server/src/main/java/com/ruoyi/basic/excel/ExcelMultiSheetImporter.java
new file mode 100644
index 0000000..56159cb
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/excel/ExcelMultiSheetImporter.java
@@ -0,0 +1,31 @@
+package com.ruoyi.basic.excel;
+
+import com.alibaba.excel.EasyExcel;
+import com.ruoyi.basic.pojo.StructureItemParameter;
+import com.ruoyi.basic.service.StandardTemplateService;
+import com.ruoyi.basic.service.StructureItemParameterService;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysDictTypeService;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
+public class ExcelMultiSheetImporter {
+
+    public static String importExcel(MultipartFile file, StructureItemParameterService service, StandardTemplateService standardTemplateService,
+                                     ISysDictTypeService dictTypeService) {
+        try {
+            // 璇诲彇鎵�鏈塖heet锛堥�氳繃鐩戝惉鍣ㄥ鐞嗘瘡涓猄heet锛�
+            EasyExcel.read(file.getInputStream())
+                    .head(StructureItemParameter.class)
+                    // 娉ㄥ唽鐩戝惉鍣紙姣忎釜Sheet鍏辩敤鍚屼竴涓洃鍚櫒锛�
+                    .registerReadListener(new MultiSheetImportListener(service, standardTemplateService, dictTypeService))
+                    // 鑷姩璇嗗埆鎵�鏈塖heet骞堕亶鍘嗚鍙�
+                    .doReadAll();
+            return "瀵煎叆鎴愬姛";
+        } catch (IOException e) {
+            System.out.println(e.getMessage());
+            return "瀵煎叆澶辫触锛�" + StringUtils.substring(e.getMessage(), 0, 100);
+        }
+    }
+}
\ No newline at end of file
diff --git a/basic-server/src/main/java/com/ruoyi/basic/excel/MultiSheetImportListener.java b/basic-server/src/main/java/com/ruoyi/basic/excel/MultiSheetImportListener.java
new file mode 100644
index 0000000..281061c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/excel/MultiSheetImportListener.java
@@ -0,0 +1,224 @@
+package com.ruoyi.basic.excel;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.exception.ExcelDataConvertException;
+import com.alibaba.excel.metadata.data.ReadCellData;
+import com.alibaba.excel.read.listener.ReadListener;
+import com.alibaba.excel.util.ListUtils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.basic.pojo.StandardTemplate;
+import com.ruoyi.basic.pojo.StructureItemParameter;
+import com.ruoyi.basic.service.StandardTemplateService;
+import com.ruoyi.basic.service.StructureItemParameterService;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.system.service.ISysDictTypeService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@AllArgsConstructor
+public class MultiSheetImportListener implements ReadListener<StructureItemParameter> {
+
+    // 姣忔壒澶勭悊1000鏉℃暟鎹�
+    private static final int BATCH_COUNT = 1000;
+    private List<StructureItemParameter> cachedList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
+    private final StructureItemParameterService parameterService;
+    private String currentSheetName;
+
+    private final ISysDictTypeService dictTypeService;
+
+    private final StandardTemplateService standardTemplateService;
+
+    public MultiSheetImportListener(StructureItemParameterService parameterService, StandardTemplateService standardTemplateService,
+                                    ISysDictTypeService dictTypeService) {
+        this.parameterService = parameterService;
+        this.standardTemplateService = standardTemplateService;
+        this.dictTypeService = dictTypeService;
+    }
+
+
+    @Override
+    public void invoke(StructureItemParameter data, AnalysisContext context) {
+        data.setId(null);
+        // 娴嬭瘯瀵硅薄
+        if (data.getSample() == null) {
+            data.setSample(null);
+        } else {
+            String brand = data.getSample();
+            StringBuilder builder = new StringBuilder();
+            builder.append("[");
+            // 浜у搧
+            if (ObjectUtil.isNotEmpty(data.getProduct())) {
+                String production = data.getProduct();
+                if (!production.contains("锛�")) {
+                    builder.append(String.format("[\"%s\",\"%s\"]", brand, production));
+                } else {
+                    Arrays.stream(production.split("锛�")).forEach(item -> {
+                        builder.append(String.format("[\"%s\",\"%s\"],", brand, item));
+                    });
+                    builder.deleteCharAt(builder.length() - 1);
+                }
+            } else {
+                builder.append("[");
+                builder.append(String.format("\"%s\"", brand));
+                builder.append("]");
+            }
+            builder.append("]");
+            data.setSample(builder.toString());
+        }
+
+        // 鏌ヨ鏁版嵁搴撲腑鏄惁瀛樺湪鐩稿悓璁板綍
+        LambdaQueryWrapper<StructureItemParameter> wrapper = Wrappers.lambdaQuery(StructureItemParameter.class)
+                .eq(StructureItemParameter::getInspectionItem, data.getInspectionItem())
+                .eq(StructureItemParameter::getSample, data.getSample())
+                .last("limit 1");
+
+        // 鍒ゆ柇鏄惁鏈夋楠岄」绫诲瀷
+        if (ObjectUtils.isNotEmpty(data.getInspectionItemClass())) {
+            wrapper.eq(StructureItemParameter::getInspectionItemClass, data.getInspectionItemClass());
+        }
+
+        // 鍒ゆ柇鏄惁鏈夋楠屽瓙椤�
+        if (ObjectUtils.isNotEmpty(data.getInspectionItemSubclass())) {
+            wrapper.eq(StructureItemParameter::getInspectionItemSubclass, data.getInspectionItemSubclass());
+        }
+
+        StructureItemParameter db_str = parameterService.getOne(wrapper);
+        if (db_str != null) {
+            // 鑻ラ渶鏇存柊锛岃缃� id
+            data.setId(db_str.getId());
+        }
+
+        // 鍘熷璁板綍妯℃澘
+        StandardTemplate standTempIdByName = standardTemplateService.getStandTempIdByName(String.valueOf(data.getTemplateName()));
+        if (standTempIdByName != null) {
+            data.setTemplateId(standTempIdByName.getId());
+        } else {
+            data.setTemplateId(null);
+        }
+
+        // 鏁版嵁绫诲瀷
+        String jy;
+        String inspectionType = data.getInspectionItemType() != null ?
+                data.getInspectionItemType().toString() : "";
+        if ("闈為噰闆嗙被鍨�".equals(inspectionType)) {
+            jy = "0";
+        } else {
+            jy = "1";
+        }
+        data.setInspectionItemType(jy);
+
+        // 鏂规硶鍚嶇О
+        if (data.getMethod() == null) {
+            data.setMethod(null);
+        } else {
+            StringBuffer buffer = new StringBuffer();
+            String input = data.getMethod().toString();
+            buffer.append("[");
+            String[] values = input.split("锛�");
+            for (String value : values) {
+                buffer.append("\"").append(value.trim()).append("\",");
+            }
+            buffer.deleteCharAt(buffer.length() - 1);
+            buffer.append("]");
+            data.setMethod(buffer.toString());
+        }
+
+        // 鐗规畩鏍囪瘑
+        String bs;
+        String bsmValue = data.getBsm() == null ? "" : data.getBsm().trim();
+        if ("鍚�".equals(bsmValue)) {
+            bs = "0";
+        } else {
+            bs = "1";
+        }
+        data.setBsm(bs);
+
+        //妫�楠岄」绫诲瀷
+        String validateValueType = data.getInspectionValueType().toString();
+        if (ObjectUtils.isNotEmpty(validateValueType)) {
+            List<SysDictData> enums = dictTypeService.selectDictDataByName("妫�楠屽�肩被鍨�")
+                    .stream().filter(sysDictData -> sysDictData.getDictLabel().equals(validateValueType)).collect(Collectors.toList());
+            data.setInspectionValueType(enums.get(0).getDictValue());
+        }
+
+        // 鏉′欢
+        if (data.getRadiusList() == null) {
+            data.setRadiusList(null);
+        } else {
+            StringBuffer buffer = new StringBuffer();
+            String input = data.getRadiusList();
+            buffer.append("[");
+            String[] values = input.split("锛�");
+            for (String value : values) {
+                buffer.append("\"").append(value.trim()).append("\",");
+            }
+            buffer.deleteCharAt(buffer.length() - 1);
+            buffer.append("]");
+            data.setRadiusList(buffer.toString());
+        }
+
+        if (data.getManDay() == null) {
+            data.setManDay(null);
+        }
+
+        // 璁剧疆褰撳墠Sheet鍚嶄负鍒嗙被鏍囪瘑
+        data.setInspectionItemClass(currentSheetName);
+
+        // 娣诲姞鍒扮紦瀛樺垪琛�
+        cachedList.add(data);
+
+        // 杈惧埌鎵规澶勭悊闃堝�兼椂鍏ュ簱
+        if (cachedList.size() >= BATCH_COUNT) {
+            saveData();
+            cachedList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        // 鏈�鍚庝竴鎵规暟鎹鐞�
+        if (!cachedList.isEmpty()) {
+            saveData();
+        }
+        log.info("Sheet [{}] 瀵煎叆瀹屾垚", currentSheetName);
+    }
+
+    @Override
+    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
+        this.currentSheetName = context.readSheetHolder().getSheetName();
+    }
+
+    private void saveData() {
+        // 鎵归噺鎻掑叆锛堜娇鐢ㄨ嫢渚漇ervice灞傛柟娉曪級
+        parameterService.saveOrUpdateBatch(cachedList);
+    }
+
+    @Override
+    public void onException(Exception exception, AnalysisContext context) {
+        String sheetName = context.readSheetHolder().getSheetName();
+        int rowIndex = context.readRowHolder().getRowIndex() + 1;
+        int columnIndex = -1;
+        String errorMsg = exception.getMessage();
+
+        // 閽堝 ExcelDataConvertException 鎻愬彇鍒楀彿
+        if (exception instanceof ExcelDataConvertException) {
+            ExcelDataConvertException ex = (ExcelDataConvertException) exception;
+            columnIndex = ex.getColumnIndex() + 1;
+            errorMsg = String.format("鍒梉%s]鏁版嵁鏍煎紡閿欒: %s",
+                    ex.getCellData().getStringValue(),
+                    errorMsg
+            );
+        }
+        // 鎵撳嵃瀹屾暣閿欒鍫嗘爤锛堣皟璇曟椂寮�鍚級
+        log.error("Sheet[{}] 绗瑊}琛岀{}鍒楄В鏋愬け璐�: {}", sheetName, rowIndex, columnIndex, errorMsg);
+    }
+}
\ No newline at end of file
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java
index 8fdbc4a..e926a00 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java
@@ -1,11 +1,11 @@
 package com.ruoyi.basic.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.basic.dto.ProductDTO1;
 import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.framework.mybatis_config.MyBaseMapper;
 import org.apache.ibatis.annotations.Param;
 
 /**
@@ -14,7 +14,7 @@
 * @createDate 2024-04-26 01:11:02
 * @Entity com.ruoyi.basic.pojo.Product
 */
-public interface ProductMapper extends BaseMapper<Product> {
+public interface ProductMapper extends MyBaseMapper<Product> {
 
     IPage<Product> selectProductListByObjectId(Page page, @Param("ew") QueryWrapper<ProductDTO1> ew, @Param("partNo") String partNo);
 }
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java
index 449d6f0..ae82d26 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java
@@ -1,12 +1,14 @@
 package com.ruoyi.basic.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.basic.dto.PageTestObjectDto;
 import com.ruoyi.basic.pojo.StructureTestObject;
+import com.ruoyi.framework.mybatis_config.MyBaseMapper;
 import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * 妫�娴嬪璞�(StructureTestObject)琛ㄦ暟鎹簱璁块棶灞�
@@ -14,7 +16,7 @@
  * @author makejava
  * @since 2024-02-26 17:36:41
  */
-public interface StructureTestObjectMapper extends BaseMapper<StructureTestObject> {
+public interface StructureTestObjectMapper extends MyBaseMapper<StructureTestObject> {
 
     IPage<PageTestObjectDto> selectTestObjectList(Page page, @Param("ew") QueryWrapper<PageTestObjectDto> ew, @Param("specimenName") String specimenName);
 
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java
index 7faa8be..a2b34ba 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
+import com.alibaba.excel.annotation.ExcelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
@@ -14,108 +15,235 @@
  * @author makejava
  * @since 2024-02-26 16:21:17
  */
-@TableName(value ="structure_item_parameter")
+@TableName(value = "structure_item_parameter")
 @Data
 public class StructureItemParameter implements Serializable {
+
+    /**
+     * 涓婚敭
+     */
     @ApiModelProperty(value = "涓婚敭")
     @TableId(type = IdType.AUTO)
     private Integer id;
 
+    /**
+     * 妫�楠岄」
+     */
     @ApiModelProperty(value = "妫�楠岄」")
+    @ExcelProperty(value = "妫�娴嬪弬鏁板悕绉�",index = 4)
     private String inspectionItem;
 
+    /**
+     * 妫�楠岄」EN
+     */
     @ApiModelProperty(value = "妫�楠岄」EN")
+    @ExcelProperty(value = "妫�娴嬪弬鏁板悕绉帮紙EN锛�",index = 5)
     private String inspectionItemEn;
 
+    /**
+     * 妫�楠屽瓙椤�
+     */
     @ApiModelProperty(value = "妫�楠屽瓙椤�")
+    @ExcelProperty(value = "妫�娴嬪瓙椤�",index = 6)
     private String inspectionItemSubclass;
 
+    /**
+     * 妫�楠屽瓙椤笶N
+     */
     @ApiModelProperty(value = "妫�楠屽瓙椤笶N")
+    @ExcelProperty(value = "妫�娴嬪瓙椤�(EN)",index = 7)
     private String inspectionItemSubclassEn;
 
+    /**
+     * 妫�楠屽璞�
+     */
     @ApiModelProperty(value = "妫�楠屽璞�")
+    @ExcelProperty(value = "娴嬭瘯瀵硅薄",index = 1)
     private String sample;
 
+    /**
+     * 鍗曚环(鍏�)
+     */
     @ApiModelProperty(value = "鍗曚环(鍏�)")
+    @ExcelProperty(value = "鍗曚环",index = 13)
     private String price;
 
+    /**
+     * 鍦烘墍
+     */
     @ApiModelProperty(value = "鍦烘墍")
+    @ExcelProperty(value = "鍦烘墍",index = 24)
     private String laboratory;
 
+    /**
+     * 璇曢獙瀹�
+     */
     @ApiModelProperty(value = "璇曢獙瀹�")
+    @ExcelProperty(value = "璇曢獙瀹�",index = 9)
     private String sonLaboratory;
 
+    /**
+     * 瑕佹眰鎻忚堪
+     */
     @ApiModelProperty(value = "瑕佹眰鎻忚堪")
+    @ExcelProperty(value = "鏍囧噯鏄剧ず",index = 11)
     private String askTell;
 
+    /**
+     * 瑕佹眰鍊�
+     */
     @ApiModelProperty(value = "瑕佹眰鍊�")
+    @ExcelProperty(value = "鍒ゆ柇瑕佹眰",index = 12)
     private String ask;
 
+    /**
+     * 璁¢噺鍗曚綅
+     */
     @ApiModelProperty(value = "璁¢噺鍗曚綅")
+    @ExcelProperty(value = "璁¢噺鍗曚綅",index = 10)
     private String unit;
 
+    /**
+     * 璇曢獙鏂规硶
+     */
     @ApiModelProperty(value = "璇曢獙鏂规硶")
+    @ExcelProperty(value = "鏂规硶鍚嶇О",index = 8)
     private String method;
 
+    /**
+     * 宸ユ椂(H)
+     */
     @ApiModelProperty(value = "宸ユ椂(H)")
+    @ExcelProperty(value = "宸ユ椂绯绘暟",index = 14)
     private Double manHour;
 
+    /**
+     * 棰勮鏃堕棿(H)
+     */
     @ApiModelProperty(value = "棰勮鏃堕棿(H)")
+    @ExcelProperty(value = "棰勮瀹屾垚鏃堕棿",index = 16)
     private Integer manDay;
 
+    /**
+     * 宸ユ椂鍒嗙粍
+     */
     @ApiModelProperty(value = "宸ユ椂鍒嗙粍")
+    @ExcelProperty(value = "宸ユ椂鍒嗙粍",index = 15)
     private String manHourGroup;
 
+    /**
+     * 妫�楠岄」绫诲瀷
+     */
     @ApiModelProperty(value = "妫�楠岄」绫诲瀷")
+    @ExcelProperty(value = "鏁版嵁绫诲瀷",index = 17)
     private String inspectionItemType;
 
+    /**
+     * 妫�楠屽�肩被鍨�
+     */
     @ApiModelProperty(value = "妫�楠屽�肩被鍨�")
+    @ExcelProperty(value = "妫�楠屽�肩被鍨�",index = 18)
     private String inspectionValueType;
 
+    /**
+     * 妫�楠屾鏁�
+     */
     @ApiModelProperty(value = "妫�楠屾鏁�")
     private Integer checkoutNumber;
 
+    /**
+     * 鍖洪棿
+     */
     @ApiModelProperty(value = "鍖洪棿")
     private String section;
 
+    /**
+     * 鐗规畩鏍囪瘑
+     */
     @ApiModelProperty(value = "鐗规畩鏍囪瘑")
+    @ExcelProperty(value = "鐗规畩鏍囪瘑",index = 19)
     private String bsm;
 
+    /**
+     * 鍘熷璁板綍妯℃澘
+     */
     @ApiModelProperty(value = "鍘熷璁板綍妯℃澘")
     private Integer templateId;
 
+    @TableField(exist = false)
+    @ExcelProperty(value = "鍘熷璁板綍妯℃澘",index = 21)
+    private String templateName;
+
+    /**
+     * 鍒涘缓浜篿d
+     */
     @ApiModelProperty(value = "鍒涘缓浜篿d")
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
+    /**
+     * 淇敼浜篿d
+     */
     @ApiModelProperty(value = "淇敼浜篿d")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
+    /**
+     * 鍒涘缓鏃堕棿
+     */
     @ApiModelProperty(value = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
+    /**
+     * 淇敼鏃堕棿
+     */
     @ApiModelProperty(value = "淇敼鏃堕棿")
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
+    /**
+     * 瀛楀吀绫诲瀷
+     */
     @ApiModelProperty(value = "瀛楀吀绫诲瀷")
+    @ExcelProperty(value = "鏁版嵁瀛楀吀",index = 20)
     private String dic;
 
+    /**
+     * 妫�楠岄」鍒嗙被
+     */
     @ApiModelProperty(value = "妫�楠岄」鍒嗙被")
+    @ExcelProperty(value = "妫�楠岄」鍒嗙被",index = 22)
     private String inspectionItemClass;
 
+    /**
+     * 妫�楠岄」鍒嗙被EN
+     */
     @ApiModelProperty(value = "妫�楠岄」鍒嗙被EN")
+    @ExcelProperty(value = "妫�楠岄」鍒嗙被",index = 23)
     private String inspectionItemClassEn;
 
+    /**
+     * 鏉′欢
+     */
     @ApiModelProperty(value = "鏉′欢")
+    @ExcelProperty(value = "璇曢獙鏉′欢",index = 25)
     private String radiusList;
 
+    /**
+     * 鏀惰垂鏍囧噯(鍏�/娆�)
+     */
     @ApiModelProperty(value = "鏀惰垂鏍囧噯(鍏�/娆�)")
+    @ExcelProperty(value = "鏀惰垂鏍囧噯",index = 26)
     private String rates;
 
-}
+    @TableField(exist = false)
+    @ExcelProperty(value = "浜у搧",index = 2)
+    private String product;
 
+    @ExcelProperty(value = "妫�娴嬪弬鏁扮紪鍙�",index = 3)
+    @TableField(exist = false)
+    private String parameterNumber;
+}
\ No newline at end of file
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java
index c58580b..d59f70f 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java
@@ -2,10 +2,8 @@
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -22,11 +20,10 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 妫�楠岄」鐩弬鏁�(StructureItemParameter)琛ㄦ湇鍔″疄鐜扮被
@@ -192,132 +189,228 @@
     public List<TestItemDto> getItemTree() {
         return structureItemParameterMapper.getItemTree();
     }
-
+    
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void importPartExcel(List<StructureTestObjectData> list) {
-        // 鎵归噺鏌ヨ StructureTestObject
-        Map<String, StructureTestObject> structureTestObjectMap = getStructureTestObjectMap(list);
-        // 鎵归噺鏌ヨ WorkShop
-        Map<String, WorkShop> workShopMap = getWorkShopMap(list);
+        // 闃舵1: 鏁版嵁棰勫鐞�
+        // 鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑鏍囨湰淇℃伅
+        Set<String> specimenKeys = list.stream()
+                .map(i -> i.getSpecimenName() + "|" + i.getSpecimenNameEn())
+                .collect(Collectors.toSet());
 
-        List<StructureTestObject> insertStructureTestObjects = new ArrayList<>();
-        List<StructureTestObject> updateStructureTestObjects = new ArrayList<>();
-        List<Product> insertProducts = new ArrayList<>();
-        List<Product> updateProducts = new ArrayList<>();
+        // 闃舵2: 鎵归噺鏌ヨ鐜版湁缁撴瀯娴嬭瘯瀵硅薄
+        Map<String, StructureTestObject> existStructureTestObjects = structureTestObjectMapper.selectList(
+                Wrappers.<StructureTestObject>lambdaQuery()
+                        .in(StructureTestObject::getSpecimenName, list.stream().map(StructureTestObjectData::getSpecimenName).collect(Collectors.toSet()))
+                        .in(StructureTestObject::getSpecimenNameEn, list.stream().map(StructureTestObjectData::getSpecimenNameEn).collect(Collectors.toSet()))
+        ).stream().collect(Collectors.toMap(
+                obj -> obj.getSpecimenName() + "|" + obj.getSpecimenNameEn(),
+                Function.identity(),
+                (existing, replacement) -> existing  // 澶勭悊閲嶅閿�
+        ));
 
-        for (StructureTestObjectData data : list) {
-            String key = data.getSpecimenName() + "_" + data.getSpecimenNameEn();
-            StructureTestObject structureTestObject = structureTestObjectMap.get(key);
-
-            if (ObjectUtils.isEmpty(structureTestObject)) {
-                structureTestObject = createStructureTestObject(data);
-                insertStructureTestObjects.add(structureTestObject);
-            } else {
-                updateStructureTestObject(structureTestObject, data);
-                updateStructureTestObjects.add(structureTestObject);
-            }
-
-            String productKey = data.getName() + "_" + data.getNameEn();
-            Product product = productMapper.selectOne(new LambdaQueryWrapper<Product>()
-                    .eq(Product::getName, data.getName())
-                    .eq(Product::getNameEn, data.getNameEn()));
-
-            if (ObjectUtils.isEmpty(product)) {
-                product = createProduct(data, structureTestObject.getId(), workShopMap);
-                insertProducts.add(product);
-            } else {
-                updateProduct(product, data, structureTestObject.getId(), workShopMap);
-                updateProducts.add(product);
-            }
-        }
-
-        // 鎵归噺鎻掑叆鍜屾洿鏂�
-        if (!insertStructureTestObjects.isEmpty()) {
-            structureTestObjectService.saveOrUpdateBatch(insertStructureTestObjects);
-        }
-        if (!updateStructureTestObjects.isEmpty()) {
-            structureTestObjectService.updateBatchById(updateStructureTestObjects);
-        }
-        if (!insertProducts.isEmpty()) {
-            productService.saveOrUpdateBatch(insertProducts);
-        }
-        if (!updateProducts.isEmpty()) {
-            productService.updateBatchById(updateProducts);
-        }
-    }
-
-    private Map<String, StructureTestObject> getStructureTestObjectMap(List<StructureTestObjectData> list) {
-        List<String> specimenNames = list.stream().map(StructureTestObjectData::getSpecimenName).collect(Collectors.toList());
-        List<String> specimenNamesEn = list.stream().map(StructureTestObjectData::getSpecimenNameEn).collect(Collectors.toList());
-        List<StructureTestObject> structureTestObjects = structureTestObjectMapper.selectList(new LambdaQueryWrapper<StructureTestObject>()
-                .in(StructureTestObject::getSpecimenName, specimenNames)
-                .in(StructureTestObject::getSpecimenNameEn, specimenNamesEn));
-        Map<String, StructureTestObject> map = new HashMap<>();
-        for (StructureTestObject obj : structureTestObjects) {
-            map.put(obj.getSpecimenName() + "_" + obj.getSpecimenNameEn(), obj);
-        }
-        return map;
-    }
-
-    private Map<String, WorkShop> getWorkShopMap(List<StructureTestObjectData> list) {
-        List<String> workShopNames = list.stream()
+        // 闃舵3: 棰勫鐞嗚溅闂翠俊鎭�
+        Set<String> workShopNames = list.stream()
                 .map(StructureTestObjectData::getWorkShopName)
                 .filter(StringUtils::isNotEmpty)
-                .distinct()
-                .collect(Collectors.toList());
-        List<WorkShop> workShops = workShopMapper.selectList(new LambdaQueryWrapper<WorkShop>()
-                .in(WorkShop::getName, workShopNames));
-        Map<String, WorkShop> map = new HashMap<>();
-        for (WorkShop workShop : workShops) {
-            map.put(workShop.getName(), workShop);
-        }
-        return map;
-    }
+                .collect(Collectors.toSet());
 
-    private StructureTestObject createStructureTestObject(StructureTestObjectData data) {
-        StructureTestObject structureTestObject = new StructureTestObject();
-        structureTestObject.setLaboratoryId(9);
-        structureTestObject.setSpecimenName(data.getSpecimenName());
-        structureTestObject.setSpecimenNameEn(data.getSpecimenNameEn());
-        structureTestObject.setCode(data.getCode());
-        structureTestObject.setWorkShopName("");
-        return structureTestObject;
-    }
+        Map<String, WorkShop> workShopCache = workShopNames.isEmpty() ?
+                Collections.emptyMap() :
+                workShopMapper.selectList(Wrappers.<WorkShop>lambdaQuery()
+                                .in(WorkShop::getName, workShopNames))
+                        .stream()
+                        .collect(Collectors.toMap(WorkShop::getName, Function.identity()));
 
-    private void updateStructureTestObject(StructureTestObject structureTestObject, StructureTestObjectData data) {
-        structureTestObject.setCode(data.getCode());
-        structureTestObject.setLaboratoryId(9);
-    }
+        // 闃舵4: 鍑嗗鎵归噺鎿嶄綔鏁版嵁
+        List<StructureTestObject> structureTestObjectsToInsert = new ArrayList<>();
+        List<StructureTestObject> structureTestObjectsToUpdate = new ArrayList<>();
+        List<Product> productsToInsert = new ArrayList<>();
+        List<Product> productsToUpdate = new ArrayList<>();
 
-    private Product createProduct(StructureTestObjectData data, Integer objectId, Map<String, WorkShop> workShopMap) {
-        Product product = new Product();
-        product.setName(data.getName());
-        product.setNameEn(data.getNameEn());
-        if (StringUtils.isNotEmpty(data.getWorkShopName())) {
-            WorkShop workShop = workShopMap.get(data.getWorkShopName());
-            if (workShop == null) {
-                throw new BaseException("璇峰厛缁存姢杞﹂棿淇℃伅");
+        // 闃舵5: 涓诲鐞嗛�昏緫锛堜粎澶勭悊缁撴瀯娴嬭瘯瀵硅薄锛�
+        List<StructureTestObjectData> pendingProducts = new ArrayList<>(); // 鏂板锛氭殏瀛樺緟澶勭悊鐨勪骇鍝佹暟鎹�
+
+        for (StructureTestObjectData i : list) {
+            // 澶勭悊缁撴瀯娴嬭瘯瀵硅薄锛堥�昏緫涓嶅彉锛�
+            String specimenKey = i.getSpecimenName() + "|" + i.getSpecimenNameEn();
+            StructureTestObject structureTestObject = existStructureTestObjects.get(specimenKey);
+
+            if (structureTestObject == null) {
+                StructureTestObject newObj = createNewStructureTestObject(i, workShopCache); // 淇敼锛氫紶鍏ヨ溅闂寸紦瀛�
+                structureTestObjectsToInsert.add(newObj);
+                existStructureTestObjects.put(specimenKey, newObj);
+            } else {
+                updateExistingStructureTestObject(structureTestObject, i);
+                structureTestObjectsToUpdate.add(structureTestObject);
             }
-            product.setWorkShopId(workShop.getId());
+
+            // 鏆傚瓨浜у搧澶勭悊鏁版嵁锛堟柊澧烇級
+            pendingProducts.add(i);
         }
-        product.setWorkShopName(data.getWorkShopName());
-        product.setObjectId(objectId);
-        return product;
+
+        // 闃舵6: 鍏堝鐞嗙粨鏋勬祴璇曞璞℃壒閲忔搷浣�
+        executeStructureTestObjectBatch(structureTestObjectsToInsert, structureTestObjectsToUpdate);
+
+        // 闃舵7: 鏇存柊缂撳瓨涓殑ID锛堝叧閿柊澧炴楠わ級
+        refreshStructureTestObjectIds(existStructureTestObjects, structureTestObjectsToInsert);
+
+        // 闃舵8: 澶勭悊浜у搧鏁版嵁
+        processProducts(pendingProducts, existStructureTestObjects, workShopCache,
+                productsToInsert, productsToUpdate);
+
+        // 闃舵9: 鎵ц浜у搧鎵归噺鎿嶄綔
+        executeProductBatch(productsToInsert, productsToUpdate);
     }
 
-    private void updateProduct(Product product, StructureTestObjectData data, Integer objectId, Map<String, WorkShop> workShopMap) {
-        if (StringUtils.isNotEmpty(data.getWorkShopName())) {
-            WorkShop workShop = workShopMap.get(data.getWorkShopName());
-            if (workShop == null) {
-                throw new BaseException("璇峰厛缁存姢杞﹂棿淇℃伅");
-            }
-            product.setWorkShopId(workShop.getId());
+    // 鏇存柊鐜版湁缁撴瀯娴嬭瘯瀵硅薄
+    private void updateExistingStructureTestObject(StructureTestObject obj, StructureTestObjectData data) {
+        obj.setCode(data.getCode());
+        obj.setLaboratoryId(9);
+    }
+
+    // 澶勭悊浜у搧鏁版嵁
+    private void processProductData(StructureTestObjectData data,
+                                    Integer objectId,
+                                    Map<String, WorkShop> workShopCache,
+                                    List<Product> insertList,
+                                    List<Product> updateList) {
+        // 鏋勫缓浜у搧鍞竴鏍囪瘑
+        String productKey = data.getName() + "|" + data.getNameEn();
+
+        // 妫�鏌ュ唴瀛樹腑鏄惁宸插鐞嗚繃璇ヤ骇鍝�
+        Optional<Product> existingProduct = findProductInBatchLists(productKey, insertList, updateList);
+
+        // 濡傛灉鍐呭瓨涓笉瀛樺湪锛屾煡璇㈡暟鎹簱
+        if (!existingProduct.isPresent()) {
+            Product dbProduct = productMapper.selectOne(Wrappers.<Product>lambdaQuery()
+                    .eq(Product::getName, data.getName())
+                    .eq(Product::getNameEn, data.getNameEn())
+                    .last("limit 1"));
+            existingProduct = Optional.ofNullable(dbProduct);
         }
-        product.setWorkShopName(data.getWorkShopName());
+
+        // 鍒涘缓鎴栨洿鏂颁骇鍝�
+        Product product = existingProduct.orElseGet(Product::new);
+        boolean isNew = product.getId() == null;
+
+        // 璁剧疆浜у搧灞炴��
+        setupProduct(product, data, objectId, workShopCache);
+
+        // 鍔犲叆瀵瑰簲鍒楄〃
+        if (isNew) {
+            insertList.add(product);
+        } else {
+            updateList.add(product);
+        }
+    }
+
+    // 鍦ㄤ骇鍝佹壒閲忓垪琛ㄤ腑鏌ユ壘
+    private Optional<Product> findProductInBatchLists(String productKey,
+                                                      List<Product> insertList,
+                                                      List<Product> updateList) {
+        return Stream.concat(insertList.stream(), updateList.stream())
+                .filter(p -> (p.getName() + "|" + p.getNameEn()).equals(productKey))
+                .findFirst();
+    }
+
+    // 璁剧疆浜у搧淇℃伅
+    private void setupProduct(Product product,
+                              StructureTestObjectData data,
+                              Integer objectId,
+                              Map<String, WorkShop> workShopCache) {
         product.setName(data.getName());
         product.setNameEn(data.getNameEn());
         product.setObjectId(objectId);
+        // 澶勭悊杞﹂棿淇℃伅
+        if (StringUtils.isNotEmpty(data.getWorkShopName())) {
+            WorkShop workShop = workShopCache.get(data.getWorkShopName());
+            if (workShop == null) {
+                throw new BaseException("杞﹂棿淇℃伅鏈淮鎶�: " + data.getWorkShopName());
+            }
+            product.setWorkShopId(workShop.getId());
+            product.setWorkShopName(data.getWorkShopName());
+        }
     }
+
+    // 鍒涘缓缁撴瀯娴嬭瘯瀵硅薄锛堜娇鐢ㄧ紦瀛樿溅闂翠俊鎭級
+    private StructureTestObject createNewStructureTestObject(StructureTestObjectData data,
+                                                             Map<String, WorkShop> workShopCache) {
+        StructureTestObject obj = new StructureTestObject();
+        obj.setLaboratoryId(9);
+        obj.setSpecimenName(data.getSpecimenName());
+        obj.setSpecimenNameEn(data.getSpecimenNameEn());
+        obj.setCode(data.getCode());
+        obj.setObjectType(data.getObjectType());
+
+        // 浣跨敤缂撳瓨鑾峰彇杞﹂棿淇℃伅
+        if (StringUtils.isNotEmpty(data.getWorkShopName())) {
+            WorkShop workShop = workShopCache.get(data.getWorkShopName());
+            if (workShop == null) {
+                throw new BaseException("杞﹂棿淇℃伅鏈淮鎶�: " + data.getWorkShopName());
+            }
+            obj.setWorkShopId(workShop.getId());
+            obj.setWorkShopName(data.getWorkShopName());
+        } else {
+            obj.setWorkShopName("");
+        }
+        return obj;
+    }
+
+    // 鍒锋柊缁撴瀯娴嬭瘯瀵硅薄ID锛堝叧閿柟娉曪級
+    private void refreshStructureTestObjectIds(
+            Map<String, StructureTestObject> existStructureTestObjects,
+            List<StructureTestObject> insertedObjects) {
+
+        insertedObjects.forEach(obj -> {
+            String key = obj.getSpecimenName() + "|" + obj.getSpecimenNameEn();
+            existStructureTestObjects.get(key).setId(obj.getId()); // 鏇存柊缂撳瓨涓殑ID
+        });
+    }
+
+    // 澶勭悊浜у搧鏁版嵁锛堢嫭绔嬫柟娉曪級
+    private void processProducts(List<StructureTestObjectData> pendingProducts,
+                                 Map<String, StructureTestObject> structureTestObjectCache,
+                                 Map<String, WorkShop> workShopCache,
+                                 List<Product> insertList,
+                                 List<Product> updateList) {
+
+        // 闃舵5鍘熸湁浜у搧澶勭悊閫昏緫杩佺Щ鑷虫
+        pendingProducts.forEach(i -> {
+            String specimenKey = i.getSpecimenName() + "|" + i.getSpecimenNameEn();
+            StructureTestObject sto = structureTestObjectCache.get(specimenKey);
+
+            processProductData(
+                    i,
+                    sto.getId(), // 姝ゆ椂ID宸叉纭缃�
+                    workShopCache,
+                    insertList,
+                    updateList
+            );
+        });
+    }
+
+    // 鍒嗘媶鎵归噺鎿嶄綔鏂规硶
+    private void executeStructureTestObjectBatch(List<StructureTestObject> toInsert,
+                                                 List<StructureTestObject> toUpdate) {
+        if (!toInsert.isEmpty()) {
+            structureTestObjectMapper.insertBatchSomeColumn(toInsert);
+        }
+        if (!toUpdate.isEmpty()) {
+            structureTestObjectService.updateBatchById(toUpdate);
+        }
+    }
+
+    private void executeProductBatch(List<Product> toInsert,
+                                     List<Product> toUpdate) {
+        if (!toInsert.isEmpty()) {
+            productMapper.insertBatchSomeColumn(toInsert);
+        }
+        if (!toUpdate.isEmpty()) {
+            productService.updateBatchById(toUpdate);
+        }
+    }
+
 }
 
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java
index e78edbf..4b893f1 100644
--- a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java
@@ -171,58 +171,76 @@
     }
 
     public void addStructureTest(List<Object> structureTestObjectIdList, List<StandardMethod> standardMethodList) {
+        // 鐢ㄤ簬瀛樺偍鏂板銆佹洿鏂板拰鍒犻櫎鐨勬暟鎹�
         List<StandardMethod> updateList = new ArrayList<>();
         List<Integer> deleteListId = new ArrayList<>();
         List<StandardMethod> addList = new ArrayList<>();
 
-        // 鍏堝皢 Excel 鏁版嵁鎸� key 鍒嗙粍
+        // 鍏堝皢 Excel 鏁版嵁鎸� code 鍒嗙粍锛屽苟鍚堝苟 field
         Map<String, StandardMethod> excelDataMap = new HashMap<>();
         for (StandardMethod excelMethod : standardMethodList) {
             String key = generateKey(excelMethod);
-            excelDataMap.put(key, excelMethod);
+            if (excelDataMap.containsKey(key)) {
+                // 濡傛灉宸插瓨鍦ㄧ浉鍚岀殑 code锛屽垯鍚堝苟 field
+                StandardMethod existingMethod = excelDataMap.get(key);
+                String mergedField = mergeFields(existingMethod.getField(), excelMethod.getField());
+                existingMethod.setField(mergedField);
+            } else {
+                // 鍚﹀垯鐩存帴娣诲姞鍒� map 涓�
+                excelDataMap.put(key, excelMethod);
+            }
         }
 
-//        if (!structureTestObjectIdList.isEmpty()) {
-            // 浠� excel 涓殑缁勫悕鏌ヨ鏁版嵁搴撲腑鐨勫垎缁�
-            List<StandardMethod> allDbMethods = new ArrayList<>();
-            for (Object j : structureTestObjectIdList) {
-                List<StandardMethod> standardMethods = baseMapper.selectList(new LambdaQueryWrapper<StandardMethod>()
-                        .like(StandardMethod::getStructureTestObjectId, "\"" + j + "\""));
-                allDbMethods.addAll(standardMethods);
-            }
+        // 鏌ヨ鏁版嵁搴撲腑鐨勫垎缁勬暟鎹�
+        List<StandardMethod> allDbMethods = new ArrayList<>();
+        for (Object j : structureTestObjectIdList) {
+            List<StandardMethod> standardMethods = baseMapper.selectList(
+                    new LambdaQueryWrapper<StandardMethod>()
+                            .apply("JSON_CONTAINS(structure_test_object_id, {0})", j) // MySQL JSON 鏌ヨ
+            );
+            allDbMethods.addAll(standardMethods);
+        }
 
-            // 灏嗘暟鎹簱鏁版嵁鎸� key 鍒嗙粍
-            Map<String, StandardMethod> dbDataMap = new HashMap<>();
-            for (StandardMethod dbMethod : allDbMethods) {
-                String key = generateKey(dbMethod);
+        // 灏嗘暟鎹簱鏁版嵁鎸� code 鍒嗙粍锛屽苟鍚堝苟 field
+        Map<String, StandardMethod> dbDataMap = new HashMap<>();
+        for (StandardMethod dbMethod : allDbMethods) {
+            String key = generateKey(dbMethod);
+            if (dbDataMap.containsKey(key)) {
+                // 濡傛灉宸插瓨鍦ㄧ浉鍚岀殑 code锛屽垯鍚堝苟 field
+                StandardMethod existingMethod = dbDataMap.get(key);
+                String mergedField = mergeFields(existingMethod.getField(), dbMethod.getField());
+                existingMethod.setField(mergedField);
+            } else {
+                // 鍚﹀垯鐩存帴娣诲姞鍒� map 涓�
                 dbDataMap.put(key, dbMethod);
             }
+        }
 
-            // 澶勭悊鏇存柊鍜屾柊澧�
-            for (Map.Entry<String, StandardMethod> entry : excelDataMap.entrySet()) {
-                String key = entry.getKey();
-                StandardMethod excelMethod = entry.getValue();
-                StandardMethod dbMethod = dbDataMap.get(key);
-                if (dbMethod != null) {
-                    // 鏇存柊
-                    excelMethod.setId(dbMethod.getId());
-                    updateList.add(excelMethod);
-                } else {
-                    // 鏂板
-                    addList.add(excelMethod);
-                }
+        // 澶勭悊鏇存柊鍜屾柊澧�
+        for (Map.Entry<String, StandardMethod> entry : excelDataMap.entrySet()) {
+            String key = entry.getKey();
+            StandardMethod excelMethod = entry.getValue();
+            StandardMethod dbMethod = dbDataMap.get(key);
+            if (dbMethod != null) {
+                // 鏇存柊
+                excelMethod.setId(dbMethod.getId());
+                updateList.add(excelMethod);
+            } else {
+                // 鏂板
+                addList.add(excelMethod);
             }
+        }
 
-            // 澶勭悊鍒犻櫎
-            for (Map.Entry<String, StandardMethod> entry : dbDataMap.entrySet()) {
-                String key = entry.getKey();
-                if (!excelDataMap.containsKey(key)) {
-                    StandardMethod dbMethod = entry.getValue();
-                    deleteListId.add(dbMethod.getId());
-                }
+        // 澶勭悊鍒犻櫎
+        for (Map.Entry<String, StandardMethod> entry : dbDataMap.entrySet()) {
+            String key = entry.getKey();
+            if (!excelDataMap.containsKey(key)) {
+                StandardMethod dbMethod = entry.getValue();
+                deleteListId.add(dbMethod.getId());
             }
+        }
 
-
+            // 鎵ц鎵归噺鎿嶄綔
         if (!addList.isEmpty()) {
             // 鏂板
             baseMapper.insertBatchSomeColumn(addList);
@@ -241,8 +259,26 @@
         }
     }
 
+    private String mergeFields(String field1, String field2) {
+        if (field1 == null || field1.isEmpty()) {
+            return field2;
+        }
+        if (field2 == null || field2.isEmpty()) {
+            return field1;
+        }
+
+        // 浣跨敤 Set 鍘婚噸
+        String[] fields1 = field1.split(",");
+        String[] fields2 = field2.split(",");
+        Set<String> uniqueFields = new HashSet<>(Arrays.asList(fields1));
+        uniqueFields.addAll(Arrays.asList(fields2));
+
+        // 杩斿洖閫楀彿鎷兼帴鐨勭粨鏋�
+        return String.join(",", uniqueFields);
+    }
+
     private String generateKey(StandardMethod method) {
-        return method.getStructureTestObjectId() + "-" + method.getCode() + "-" + method.getField();
+        return method.getCode();
     }
 
     // 鏍煎紡鍖栨暟鎹�
diff --git a/cnas-device/src/main/java/com/ruoyi/device/mapper/DeviceMapper.java b/cnas-device/src/main/java/com/ruoyi/device/mapper/DeviceMapper.java
index 1637118..e7b0af4 100644
--- a/cnas-device/src/main/java/com/ruoyi/device/mapper/DeviceMapper.java
+++ b/cnas-device/src/main/java/com/ruoyi/device/mapper/DeviceMapper.java
@@ -1,11 +1,11 @@
 package com.ruoyi.device.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.device.dto.DeviceDto;
 import com.ruoyi.device.pojo.Device;
+import com.ruoyi.framework.mybatis_config.MyBaseMapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -15,7 +15,7 @@
 /**
  * 璁惧(Device)琛ㄦ暟鎹簱璁块棶灞�
  */
-public interface DeviceMapper extends BaseMapper<Device> {
+public interface DeviceMapper extends MyBaseMapper<Device> {
 
     IPage<Device> selectDeviceParameter(Page page, QueryWrapper<Device> ew);
     List<Device> selectEquipmentOverview(Page page, QueryWrapper<Device> ew);
diff --git a/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceServiceImpl.java b/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceServiceImpl.java
index f1aacac..3f9b658 100644
--- a/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceServiceImpl.java
+++ b/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceServiceImpl.java
@@ -607,12 +607,12 @@
             }
         }
 
-        // 鎵归噺鎻掑叆锛堜娇鐢∕yBatis-Plus鐨刬nsertBatch锛岄粯璁atchSize=1000锛�
+        // 鎵归噺鎻掑叆
         if (CollUtil.isNotEmpty(toInsert)) {
-            saveOrUpdateBatch(toInsert);
+            baseMapper.insertBatchSomeColumn(toInsert);
         }
 
-        // 鎵归噺鏇存柊锛堜娇鐢∕yBatis-Plus鐨剈pdateBatchById锛岄粯璁atchSize=1000锛�
+        // 鎵归噺鏇存柊
         if (CollUtil.isNotEmpty(toUpdate)) {
             updateBatchById(toUpdate);
         }
diff --git a/pom.xml b/pom.xml
index 2a75212..bc9706c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,7 +44,7 @@
         <minio.version>8.4.3</minio.version>
         <okhttp.version>4.9.0</okhttp.version>
         <hutool.version>5.8.18</hutool.version>
-        <easyexcel.version>3.3.2</easyexcel.version>
+        <easyexcel.version>3.3.3</easyexcel.version>
         <poi.tl.version>1.12.2</poi.tl.version>
     </properties>
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonDto.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonDto.java
index 50e8481..38b73f9 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonDto.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonDto.java
@@ -17,4 +17,6 @@
 
     private Integer roleId;
 
+    private Integer deptId;
+
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonnelHeaderApi.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonnelHeaderApi.java
index 120e899..38b17d1 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonnelHeaderApi.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/PersonnelHeaderApi.java
@@ -183,6 +183,7 @@
                 user.setIsCustom(0);
                 user.setPassword(SecurityUtils.encryptPassword("zttZTT123!"));
                 user.setCompany(BeanUtil.isNotEmpty(custom) ? (custom.getId() + "") : companyName);
+                user.setDeptId(personDto.getDeptId());
                 userMapper.insert(user);
             } else {
                 user.setName(person.getName());
@@ -190,6 +191,7 @@
                 user.setEmail(person.getCompanyEmail());
                 user.setIsCustom(0);
                 user.setCompany(BeanUtil.isNotEmpty(custom) ? (custom.getId() + "") : companyName);
+                user.setDeptId(personDto.getDeptId());
                 userMapper.updateById(user);
             }
         });

--
Gitblit v1.9.3