From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/print/WendingxingKaocaHuizongRenderer.java |  302 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 302 insertions(+), 0 deletions(-)

diff --git a/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/print/WendingxingKaocaHuizongRenderer.java b/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/print/WendingxingKaocaHuizongRenderer.java
new file mode 100644
index 0000000..8f95350
--- /dev/null
+++ b/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/print/WendingxingKaocaHuizongRenderer.java
@@ -0,0 +1,302 @@
+package jnpf.limsService.print;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import jnpf.exception.DataException;
+import jnpf.limsEntity.LimsJianyanXiangEntity;
+import jnpf.limsEntity.LimsPrintTemplateEntity;
+import jnpf.limsEntity.LimsQingyandanEntity;
+import jnpf.limsEntity.LimsWendingxingKaocaJihuaEntity;
+import jnpf.limsEntity.LimsWendingxingKaocaJihuaZhouqiEntity;
+import jnpf.limsMapper.LimsJianyanXiangMapper;
+import jnpf.limsMapper.LimsQingyandanMapper;
+import jnpf.limsMapper.LimsWendingxingKaocaJihuaMapper;
+import jnpf.limsMapper.LimsWendingxingKaocaJihuaZhouqiMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 绋冲畾鎬ц�冨療姹囨�绘ā鏉挎覆鏌撳櫒锛坱emplate_id = wendingxing_kaoca_huizong锛夈��
+ */
+@Component
+public class WendingxingKaocaHuizongRenderer implements PrintTemplateRenderer {
+
+    public static final String TEMPLATE_ID = "wendingxing_kaoca_huizong";
+    private static final String EMPTY_RESULT = "/";
+
+    @Autowired
+    private LimsWendingxingKaocaJihuaMapper jihuaMapper;
+
+    @Autowired
+    private LimsWendingxingKaocaJihuaZhouqiMapper zhouqiMapper;
+
+    @Autowired
+    private LimsQingyandanMapper qingyandanMapper;
+
+    @Autowired
+    private LimsJianyanXiangMapper jianyanXiangMapper;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Override
+    public String getTemplateId() {
+        return TEMPLATE_ID;
+    }
+
+    @Override
+    public Map<String, Object> render(String baogaoId, LimsPrintTemplateEntity tpl) {
+        if (baogaoId == null || baogaoId.trim().isEmpty()) {
+            throw new DataException("缂哄皯绋冲畾鎬ц�冨療璁″垝 id");
+        }
+
+        LimsWendingxingKaocaJihuaEntity jihua = selectJihua(baogaoId);
+        if (jihua == null) {
+            throw new DataException("绋冲畾鎬ц�冨療璁″垝涓嶅瓨鍦ㄦ垨宸插垹闄�: " + baogaoId);
+        }
+
+        Map<String, Object> config = parseConfig(tpl);
+        List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles = selectCycles(baogaoId);
+        Map<String, List<LimsQingyandanEntity>> qingyandanByCycle = selectQingyandan(baogaoId, cycles);
+        Map<String, List<LimsJianyanXiangEntity>> itemsByQingyandan = selectItems(qingyandanByCycle);
+
+        LinkedHashMap<String, String> periodLabels = buildPeriodLabels(cycles, config.get("zhouqiDanwei"));
+        Map<String, Object> data = new LinkedHashMap<>();
+        data.put("schemeName", jihua.getKaocaMingcheng());
+        data.put("periods", new ArrayList<>(periodLabels.values()));
+        data.put("reports", buildReports(cycles, periodLabels, qingyandanByCycle, itemsByQingyandan));
+        return data;
+    }
+
+    private LimsWendingxingKaocaJihuaEntity selectJihua(String baogaoId) {
+        QueryWrapper<LimsWendingxingKaocaJihuaEntity> query = new QueryWrapper<>();
+        query.eq("f_id", baogaoId);
+        query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
+        return jihuaMapper.selectOne(query);
+    }
+
+    /**
+     *
+     * 鏍规嵁璁″垝 ID 鏌ヨ鍛ㄦ湡鍒楄〃鏁版嵁
+     *
+     * @param baogaoId
+     * @return
+     */
+    private List<LimsWendingxingKaocaJihuaZhouqiEntity> selectCycles(String baogaoId) {
+        QueryWrapper<LimsWendingxingKaocaJihuaZhouqiEntity> query = new QueryWrapper<>();
+        query.eq("kaoca_jihua_id", baogaoId);
+        query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
+        query.and(w -> w.isNull("shifou_jixu_zhixing").or().ne("shifou_jixu_zhixing", "no"));
+        query.orderByAsc("jiahua_anpai_riqi", "f_id");
+        return zhouqiMapper.selectList(query);
+    }
+
+    private Map<String, List<LimsQingyandanEntity>> selectQingyandan(
+            String baogaoId, List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles) {
+        if (cycles.isEmpty()) {
+            return Collections.emptyMap();
+        }
+
+        List<String> cycleIds = cycles.stream()
+                .map(LimsWendingxingKaocaJihuaZhouqiEntity::getId)
+                .collect(Collectors.toList());
+        QueryWrapper<LimsQingyandanEntity> query = new QueryWrapper<>();
+        query.eq("wendingxing_jilu_id", baogaoId);
+        query.in("wendingxing_zhouqi_id", cycleIds);
+        query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
+        query.orderByAsc("f_id");
+
+        Map<String, List<LimsQingyandanEntity>> result = new HashMap<>();
+        for (LimsQingyandanEntity row : qingyandanMapper.selectList(query)) {
+            result.computeIfAbsent(row.getWendingxingZhouqiId(), key -> new ArrayList<>()).add(row);
+        }
+        return result;
+    }
+
+    private Map<String, List<LimsJianyanXiangEntity>> selectItems(
+            Map<String, List<LimsQingyandanEntity>> qingyandanByCycle) {
+        List<String> qingyandanIds = qingyandanByCycle.values().stream()
+                .flatMap(List::stream)
+                .map(LimsQingyandanEntity::getId)
+                .collect(Collectors.toList());
+        if (qingyandanIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+
+        QueryWrapper<LimsJianyanXiangEntity> query = new QueryWrapper<>();
+        query.in("qingyandan_id", qingyandanIds);
+        query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
+        query.orderByAsc("f_id");
+
+        Map<String, List<LimsJianyanXiangEntity>> result = new HashMap<>();
+        for (LimsJianyanXiangEntity row : jianyanXiangMapper.selectList(query)) {
+            result.computeIfAbsent(row.getQingyandanId(), key -> new ArrayList<>()).add(row);
+        }
+        return result;
+    }
+
+    private LinkedHashMap<String, String> buildPeriodLabels(
+            List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles, Object unitConfig) {
+        LinkedHashMap<String, String> result = new LinkedHashMap<>();
+        for (LimsWendingxingKaocaJihuaZhouqiEntity cycle : cycles) {
+            String key = periodKey(cycle);
+            result.putIfAbsent(key, formatNumber(cycle.getZhouqi())
+                    + resolveUnit(cycle.getZhouqiDanwei(), unitConfig));
+        }
+        return result;
+    }
+
+    private List<Map<String, Object>> buildReports(
+            List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles,
+            LinkedHashMap<String, String> periodLabels,
+            Map<String, List<LimsQingyandanEntity>> qingyandanByCycle,
+            Map<String, List<LimsJianyanXiangEntity>> itemsByQingyandan) {
+        LinkedHashMap<String, List<LimsWendingxingKaocaJihuaZhouqiEntity>> cyclesByBatch =
+                new LinkedHashMap<>();
+        for (LimsWendingxingKaocaJihuaZhouqiEntity cycle : cycles) {
+            cyclesByBatch.computeIfAbsent(valueOrEmpty(cycle.getPihao()), key -> new ArrayList<>())
+                    .add(cycle);
+        }
+
+        List<Map<String, Object>> reports = new ArrayList<>();
+        for (Map.Entry<String, List<LimsWendingxingKaocaJihuaZhouqiEntity>> batch
+                : cyclesByBatch.entrySet()) {
+            LinkedHashMap<String, ReportRow> rows = new LinkedHashMap<>();
+            for (LimsWendingxingKaocaJihuaZhouqiEntity cycle : batch.getValue()) {
+                String periodKey = periodKey(cycle);
+                for (LimsQingyandanEntity qingyandan
+                        : qingyandanByCycle.getOrDefault(cycle.getId(), Collections.emptyList())) {
+                    for (LimsJianyanXiangEntity item
+                            : itemsByQingyandan.getOrDefault(qingyandan.getId(), Collections.emptyList())) {
+                        String rowKey = valueOrEmpty(item.getJianyanXiangmuMingcheng()) + "\u0000"
+                                + valueOrEmpty(item.getBiaozhunGuiding());
+                        String standard = resultOrSlash(item.getBiaozhunGuiding());
+                        String value = resultOrSlash(item.getJianyanJieguo());
+                        if ("鏁板��".equals(item.getShujuLeixing())) {
+                            value += item.getFenjianDanwei();
+                            standard += item.getFenjianDanwei();
+                        }
+                        String finalStandard = standard;
+                        ReportRow row = rows.computeIfAbsent(rowKey,
+                                key -> new ReportRow(item.getJianyanXiangmuMingcheng(), finalStandard));
+                        if (!row.values.containsKey(periodKey)
+                                || EMPTY_RESULT.equals(row.values.get(periodKey))) {
+                            row.values.put(periodKey, value);
+                        }
+                    }
+                }
+            }
+
+            List<Map<String, Object>> reportRows = new ArrayList<>();
+            for (ReportRow source : rows.values()) {
+                Map<String, Object> row = new LinkedHashMap<>();
+                row.put("item", source.item);
+                row.put("standard", source.standard);
+                List<String> values = periodLabels.keySet().stream()
+                        .map(key -> source.values.getOrDefault(key, EMPTY_RESULT))
+                        .collect(Collectors.toList());
+                row.put("values", values);
+                reportRows.add(row);
+            }
+
+            Map<String, Object> report = new LinkedHashMap<>();
+            report.put("batchNo", batch.getKey());
+            report.put("rows", reportRows);
+            reports.add(report);
+        }
+        return reports;
+    }
+
+    private Map<String, Object> parseConfig(LimsPrintTemplateEntity tpl) {
+        if (tpl == null || tpl.getConfig() == null || tpl.getConfig().trim().isEmpty()) {
+            return Collections.emptyMap();
+        }
+        try {
+            return objectMapper.readValue(tpl.getConfig(), new TypeReference<Map<String, Object>>() { });
+        } catch (Exception e) {
+            throw new DataException("鎵撳嵃妯℃澘 config JSON 瑙f瀽澶辫触: " + e.getMessage());
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private String resolveUnit(String code, Object config) {
+        String source = valueOrEmpty(code);
+        if (config instanceof Map) {
+            Object configured = ((Map<String, Object>) config).get(source);
+            return labelOf(configured, source);
+        }
+        if (config instanceof List) {
+            for (Object entry : (List<?>) config) {
+                if (!(entry instanceof Map)) {
+                    continue;
+                }
+                Map<String, Object> option = (Map<String, Object>) entry;
+                String value = firstString(option, "value", "id", "code", "enCode");
+                if (source.equals(value)) {
+                    return firstNonEmpty(firstString(option, "label", "name", "fullName", "text"), source);
+                }
+            }
+        }
+        return source;
+    }
+
+    @SuppressWarnings("unchecked")
+    private String labelOf(Object configured, String fallback) {
+        if (configured instanceof Map) {
+            return firstNonEmpty(firstString((Map<String, Object>) configured,
+                    "label", "name", "fullName", "text", "value"), fallback);
+        }
+        return configured == null ? fallback : configured.toString();
+    }
+
+    private String firstString(Map<String, Object> values, String... keys) {
+        for (String key : keys) {
+            Object value = values.get(key);
+            if (value != null && !value.toString().trim().isEmpty()) {
+                return value.toString();
+            }
+        }
+        return "";
+    }
+
+    private String periodKey(LimsWendingxingKaocaJihuaZhouqiEntity cycle) {
+        return formatNumber(cycle.getZhouqi()) + "\u0000" + valueOrEmpty(cycle.getZhouqiDanwei());
+    }
+
+    private String formatNumber(BigDecimal value) {
+        return value == null ? "" : value.stripTrailingZeros().toPlainString();
+    }
+
+    private String resultOrSlash(String value) {
+        return value == null || value.trim().isEmpty() ? EMPTY_RESULT : value;
+    }
+
+    private String firstNonEmpty(String value, String fallback) {
+        return value == null || value.trim().isEmpty() ? fallback : value;
+    }
+
+    private String valueOrEmpty(String value) {
+        return value == null ? "" : value;
+    }
+
+    private static final class ReportRow {
+        private final String item;
+        private final String standard;
+        private final Map<String, String> values = new HashMap<>();
+
+        private ReportRow(String item, String standard) {
+            this.item = item;
+            this.standard = standard;
+        }
+    }
+}

--
Gitblit v1.8.0