From 1fb9069acd396eb8bdbd65252f6eb10d3e8362b7 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 02 六月 2026 13:56:57 +0800
Subject: [PATCH] feat(staff): 修改员工入职服务接口增加用户添加标识参数

---
 src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java |  489 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 489 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java b/src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java
new file mode 100644
index 0000000..54ad922
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java
@@ -0,0 +1,489 @@
+package com.ruoyi.quality.utils;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.quality.service.IQualityInspectParamService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.usermodel.Range;
+import org.apache.poi.hwpf.usermodel.Table;
+import org.apache.poi.hwpf.usermodel.TableCell;
+import org.apache.poi.hwpf.usermodel.TableIterator;
+import org.apache.poi.hwpf.usermodel.TableRow;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Word template export helper for process inspection.
+ */
+@Component
+@RequiredArgsConstructor
+public class QualityInspectTemplateExportHelper {
+
+    private static final String WEILONG_TEMPLATE = "/static/浼熼緳妯$増.doc";
+    private static final String BAISHI_TEMPLATE = "/static/鐧句簨妯$増.doc";
+    private static final String DALI_TEMPLATE = "/static/杈惧埄妯$増.doc";
+
+    private final QualityInspectMapper qualityInspectMapper;
+    private final IQualityInspectParamService qualityInspectParamService;
+
+    public void exportWeiLong(HttpServletResponse response, Long inspectId) {
+        export(response, inspectId, WEILONG_TEMPLATE, "浼熼緳妯$増妫�楠岀粨鏋�");
+    }
+
+    public void exportBaiShi(HttpServletResponse response, Long inspectId) {
+        export(response, inspectId, BAISHI_TEMPLATE, "鐧句簨妯$増妫�楠岀粨鏋�");
+    }
+
+    public void exportDaLi(HttpServletResponse response, Long inspectId) {
+        export(response, inspectId, DALI_TEMPLATE, "杈惧埄妯$増妫�楠岀粨鏋�");
+    }
+
+    private void export(HttpServletResponse response, Long inspectId, String templatePath, String fileName) {
+        if (inspectId == null) {
+            throw new ServiceException("妫�楠屽崟ID涓嶈兘涓虹┖");
+        }
+
+        QualityInspect inspect = qualityInspectMapper.selectById(inspectId);
+        if (inspect == null) {
+            throw new ServiceException("妫�楠屽崟涓嶅瓨鍦�");
+        }
+
+        List<QualityInspectParam> paramList = qualityInspectParamService.list(
+                Wrappers.<QualityInspectParam>lambdaQuery()
+                        .eq(QualityInspectParam::getInspectId, inspectId)
+                        .orderByAsc(QualityInspectParam::getId));
+        Map<String, String> valueMap = buildValueMap(paramList, inspect);
+
+        try (InputStream inputStream = getClass().getResourceAsStream(templatePath)) {
+            if (inputStream == null) {
+                throw new ServiceException("妯℃澘鏂囦欢涓嶅瓨鍦細" + templatePath);
+            }
+
+            HWPFDocument document = new HWPFDocument(inputStream);
+            fillDocument(document, valueMap);
+
+            response.reset();
+            response.setContentType("application/msword");
+            response.setCharacterEncoding("UTF-8");
+            String encodedName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+            response.setHeader("Content-Disposition", "attachment;filename=" + encodedName + ".doc");
+
+            try (OutputStream outputStream = response.getOutputStream()) {
+                document.write(outputStream);
+                outputStream.flush();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("瀵煎嚭澶辫触", e);
+        }
+    }
+
+    private void fillDocument(HWPFDocument document, Map<String, String> valueMap) {
+        Range range = document.getRange();
+        TableIterator iterator = new TableIterator(range);
+        while (iterator.hasNext()) {
+            Table table = iterator.next();
+            fillTable(table, valueMap);
+        }
+    }
+
+    private void fillTable(Table table, Map<String, String> valueMap) {
+        String currentGroupLabel = "";
+        // 璁板綍缁撹鍒楃殑浣嶇疆锛岄伩鍏嶅湪缁撹鍒椾笅闈㈢户缁~鍏�
+        int conclusionCellIndex = -1;
+
+        for (int rowIndex = 0; rowIndex < table.numRows(); rowIndex++) {
+            TableRow row = table.getRow(rowIndex);
+            String firstCellText = getCellText(row, 0);
+            String secondCellText = getCellText(row, 1);
+
+            if (StringUtils.isNotBlank(firstCellText)) {
+                currentGroupLabel = firstCellText;
+            }
+
+            // 鍏堝垽鏂槸鍚︿负缁撹琛�
+            String normalizedFirstCell = normalizeKey(firstCellText);
+            boolean isConclusionRow = matchesSummaryRow(normalizedFirstCell);
+
+            // 濡傛灉鏄粨璁鸿锛岀粨璁哄垪濮嬬粓鏄渶鍚庝竴鍒�
+            if (isConclusionRow) {
+                conclusionCellIndex = row.numCells() - 1;
+            }
+
+            String value = resolveValue(valueMap, currentGroupLabel, firstCellText, secondCellText, isConclusionRow);
+            if (StringUtils.isBlank(value)) {
+                continue;
+            }
+
+            // 鏌ユ壘缁撴灉鍒椾綅缃�
+            int resultCellIndex;
+            if (isConclusionRow) {
+                resultCellIndex = conclusionCellIndex;
+            } else {
+                // 鏅�氳锛氭壘绗竴涓┖鐧藉崟鍏冩牸浣滀负缁撴灉鍒楋紝浣嗚鎺掗櫎缁撹鍒�
+                resultCellIndex = findResultCellIndex(row, conclusionCellIndex);
+                if (resultCellIndex < 0) {
+                    // 涓嶄娇鐢ㄦ渶鍚庝竴鍒楋紝閬垮厤涓庣粨璁哄垪鍐茬獊
+                    int lastCellIndex = row.numCells() - 1;
+                    if (lastCellIndex > 1 && lastCellIndex != conclusionCellIndex) {
+                        resultCellIndex = lastCellIndex - 1;
+                    }
+                }
+            }
+
+            if (resultCellIndex < 0 || resultCellIndex == conclusionCellIndex && !isConclusionRow) {
+                continue;
+            }
+
+            TableCell resultCell = row.getCell(resultCellIndex);
+            String cellText = cleanCellText(resultCell.text());
+
+            // 涓ユ牸妫�鏌ワ細鍙湁绌虹櫧鎴栧崰浣嶇鎵嶅~鍏�
+            if (!isBlankLike(cellText) && !isPlaceholder(cellText)) {
+                continue;
+            }
+
+            // 浣跨敤鏇村畨鍏ㄧ殑濉厖鏂瑰紡
+            safeWriteCellText(resultCell, value);
+        }
+    }
+
+    /**
+     * 鏌ユ壘缁撴灉鍒楋紝鎺掗櫎缁撹鍒�
+     */
+    private int findResultCellIndex(TableRow row, int excludeIndex) {
+        for (int i = 1; i < row.numCells(); i++) {
+            if (i == excludeIndex) {
+                continue;
+            }
+            String cellText = cleanCellText(row.getCell(i).text());
+            if (isBlankLike(cellText) || isPlaceholder(cellText)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * 瀹夊叏鍐欏叆鍗曞厓鏍兼枃鏈紝閬垮厤褰卞搷鍏朵粬琛�
+     */
+    private void safeWriteCellText(TableCell cell, String value) {
+        if (StringUtils.isBlank(value)) {
+            return;
+        }
+
+        String originalText = cell.text();
+        String cleanedOriginal = cleanCellText(originalText);
+
+        // 濡傛灉鍗曞厓鏍煎凡鏈夊唴瀹逛笖涓嶆槸鍗犱綅绗︼紝涓嶅啓鍏�
+        if (StringUtils.isNotBlank(cleanedOriginal) && !isPlaceholder(cleanedOriginal)) {
+            return;
+        }
+
+        // 鍙娇鐢╮eplaceText锛屼笉浣跨敤insertBefore
+        try {
+            if (StringUtils.isNotBlank(originalText)) {
+                cell.replaceText(originalText, value);
+            } else {
+                // 绌哄崟鍏冩牸鐩存帴璁剧疆鏂囨湰
+                cell.insertBefore(value);
+            }
+        } catch (Exception e) {
+            // 澶囩敤鏂规锛氫娇鐢╣etRange鏂瑰紡
+            try {
+//                cell.getRange().insertAfter(value);
+            } catch (Exception ignored) {}
+        }
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓哄崰浣嶇
+     */
+    private boolean isPlaceholder(String text) {
+        if (StringUtils.isBlank(text)) {
+            return false;
+        }
+        String cleaned = text.trim();
+        // 甯歌鍗犱綅绗︽ā寮�
+        return cleaned.equals("鈥�") ||
+               cleaned.equals("-") ||
+               cleaned.equals("_") ||
+               cleaned.equals("/") ||
+               cleaned.equals("\\") ||
+               cleaned.equals("鈻�") ||
+               cleaned.equals("鈻�") ||
+               cleaned.equals("鈼�") ||
+               cleaned.equals("鈼�") ||
+               cleaned.equals("鈥�") ||
+               cleaned.equals("*") ||
+               cleaned.matches("^\\.{2,}$") || // 澶氫釜鐐�
+               cleaned.matches("^{2,}$") || // 澶氫釜澶ф嫭鍙�
+               cleaned.equalsIgnoreCase("N/A") ||
+               cleaned.equalsIgnoreCase("NA") ||
+               cleaned.equals("寰呮") ||
+               cleaned.equals("寰呭~") ||
+               cleaned.equals("绌虹櫧");
+    }
+
+    private int findResultCellIndex(TableRow row) {
+        for (int i = 1; i < row.numCells(); i++) {
+            if (isBlankLike(row.getCell(i).text())) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private String resolveValue(Map<String, String> valueMap,
+                                String currentGroupLabel,
+                                String firstCellText,
+                                String secondCellText,
+                                boolean isConclusionRow) {
+        LinkedHashSet<String> candidates = new LinkedHashSet<>();
+        addCandidate(candidates, firstCellText);
+        addCandidate(candidates, secondCellText);
+        addCandidate(candidates, firstCellText + secondCellText);
+        if (StringUtils.isNotBlank(currentGroupLabel) && StringUtils.isNotBlank(secondCellText)) {
+            addCandidate(candidates, currentGroupLabel + secondCellText);
+        }
+        if (StringUtils.isNotBlank(currentGroupLabel)
+                && StringUtils.isNotBlank(firstCellText)
+                && StringUtils.isBlank(secondCellText)) {
+            addCandidate(candidates, currentGroupLabel);
+        }
+
+
+        // 缁撹琛屼笉濉厖锛屼繚鐣欐ā鏉垮師濮嬫暟鎹�
+        if (isConclusionRow) {
+            return null;
+        }
+
+        // 鏅�氳锛氬厛鏌ユ楠屽弬鏁板�硷紝鏈�鍚庢墠鍖归厤缁撹琛屽叧閿瘝
+        for (String candidate : candidates) {
+            String normalized = normalizeKey(candidate);
+            // 鏅�氳璺宠繃缁撹鍏抽敭璇嶅尮閰�
+            if (matchesSummaryRow(normalized)) {
+                continue;
+            }
+            String value = lookupValue(valueMap, normalized);
+            if (StringUtils.isNotBlank(value)) {
+                return value;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean matchesSummaryRow(String normalizedText) {
+        if (StringUtils.isBlank(normalizedText)) {
+            return false;
+        }
+        return normalizedText.contains("璐ㄩ噺璇勫畾")
+                || normalizedText.contains("妫�楠岀粨璁�")
+                || normalizedText.contains("Gradeestimation")
+                || normalizedText.contains("Conclusion")
+                || normalizedText.contains("Evaluation")
+                || normalizedText.contains("璇勫畾")
+                || normalizedText.contains("缁撹");
+    }
+
+    private String lookupValue(Map<String, String> valueMap, String normalizedCandidate) {
+        if (StringUtils.isBlank(normalizedCandidate)) {
+            return null;
+        }
+
+        String value = valueMap.get(normalizedCandidate);
+        if (StringUtils.isNotBlank(value)) {
+            return value;
+        }
+
+        String chineseCandidate = stripEnglishLetters(normalizedCandidate);
+        value = valueMap.get(chineseCandidate);
+        if (StringUtils.isNotBlank(value)) {
+            return value;
+        }
+
+        for (Map.Entry<String, String> entry : valueMap.entrySet()) {
+            String key = entry.getKey();
+            if (StringUtils.contains(key, normalizedCandidate)
+                    || StringUtils.contains(normalizedCandidate, key)
+                    || StringUtils.contains(key, chineseCandidate)
+                    || StringUtils.contains(chineseCandidate, key)) {
+                return entry.getValue();
+            }
+        }
+        return null;
+    }
+
+    private Map<String, String> buildValueMap(List<QualityInspectParam> paramList, QualityInspect inspect) {
+        Map<String, String> valueMap = new LinkedHashMap<>();
+        for (QualityInspectParam param : paramList) {
+            String value = StringUtils.trimToNull(param.getTestValue());
+            if (StringUtils.isBlank(value)) {
+                continue;
+            }
+            putValue(valueMap, param.getParameterItem(), value);
+        }
+
+        String checkResult = StringUtils.trimToNull(inspect.getCheckResult());
+        if (StringUtils.isNotBlank(checkResult)) {
+            putValue(valueMap, "璐ㄩ噺璇勫畾", checkResult);
+            putValue(valueMap, "妫�楠岀粨鏋�", checkResult);
+            putValue(valueMap, "妫�楠岀粨璁�", checkResult);
+            putValue(valueMap, "Grade estimation", checkResult);
+            putValue(valueMap, "Test Results", checkResult);
+        }
+        return valueMap;
+    }
+
+    private void putValue(Map<String, String> valueMap, String key, String value) {
+        String normalizedKey = normalizeKey(key);
+        if (StringUtils.isBlank(normalizedKey)) {
+            return;
+        }
+        valueMap.put(normalizedKey, value);
+
+        String chineseKey = stripEnglishLetters(normalizedKey);
+        if (StringUtils.isNotBlank(chineseKey)) {
+            valueMap.putIfAbsent(chineseKey, value);
+        }
+    }
+
+    private void writeCellText(TableCell cell, String value) {
+        if (StringUtils.isBlank(value)) {
+            return;
+        }
+
+        String originalText = cell.text();
+        try {
+            cell.replaceText(originalText, value);
+        } catch (Exception ignored) {
+            // Fallback below.
+        }
+
+        String cleanedText = cleanCellText(cell.text());
+        if (!cleanedText.contains(value)) {
+            cell.insertBefore(value);
+        }
+    }
+
+    private String getCellText(TableRow row, int index) {
+        if (row.numCells() <= index) {
+            return "";
+        }
+        return cleanCellText(row.getCell(index).text());
+    }
+
+    private String cleanCellText(String text) {
+        if (text == null) {
+            return "";
+        }
+        return text.replace("\u0007", "")
+                .replace("\r", "")
+                .replace("\n", "")
+                .trim();
+    }
+
+    private boolean isBlankLike(String text) {
+        String cleaned = cleanCellText(text);
+        return StringUtils.isBlank(cleaned)
+                || "-".equals(cleaned)
+                || "_".equals(cleaned)
+                || "鈥�".equals(cleaned)
+                || "路".equals(cleaned);
+    }
+
+    private void addCandidate(LinkedHashSet<String> candidates, String text) {
+        if (StringUtils.isBlank(text)) {
+            return;
+        }
+        candidates.add(text);
+    }
+
+    private String normalizeKey(String text) {
+        String value = cleanCellText(text);
+        if (StringUtils.isBlank(value)) {
+            return "";
+        }
+        value = value.replace("\u00A0", "");
+        value = value.replaceAll("\\s+", "");
+        value = value.replace("锛�", "");
+        value = value.replace("锛�", "");
+        value = value.replace("(", "");
+        value = value.replace(")", "");
+        value = value.replace("锛�", "");
+        value = value.replace(",", "");
+        value = value.replace("銆�", "");
+        value = value.replace("锛�", "");
+        value = value.replace(":", "");
+        value = value.replace("锛�", "");
+        value = value.replace(";", "");
+        value = value.replace("銆�", "");
+        value = value.replace("鈥�", "");
+        value = value.replace("鈥�", "");
+        value = value.replace("銆�", "");
+        value = value.replace("銆�", "");
+        value = value.replace("%", "");
+        return value;
+    }
+
+    private String stripEnglishLetters(String text) {
+        if (StringUtils.isBlank(text)) {
+            return "";
+        }
+        return text.replaceAll("[A-Za-z]", "");
+    }
+
+    /**
+     * 璋冭瘯鏂规硶锛氬垎鏋愭ā鏉胯〃鏍肩粨鏋�
+     */
+    public String analyzeTemplate(String templatePath) {
+        StringBuilder sb = new StringBuilder();
+        try (InputStream inputStream = getClass().getResourceAsStream(templatePath)) {
+            if (inputStream == null) {
+                return "妯℃澘鏂囦欢涓嶅瓨鍦細" + templatePath;
+            }
+
+            HWPFDocument document = new HWPFDocument(inputStream);
+            Range range = document.getRange();
+            TableIterator iterator = new TableIterator(range);
+
+            int tableIndex = 0;
+            while (iterator.hasNext()) {
+                Table table = iterator.next();
+                sb.append("=== 琛ㄦ牸 ").append(tableIndex++).append(" ===\n");
+                sb.append("琛屾暟: ").append(table.numRows()).append("\n");
+
+                for (int rowIndex = 0; rowIndex < table.numRows(); rowIndex++) {
+                    TableRow row = table.getRow(rowIndex);
+                    sb.append("琛�").append(rowIndex).append(": ");
+                    for (int cellIndex = 0; cellIndex < row.numCells(); cellIndex++) {
+                        String cellText = cleanCellText(row.getCell(cellIndex).text());
+                        sb.append("[鍒�").append(cellIndex).append(": ").append(cellText).append("] ");
+                    }
+                    sb.append("\n");
+                }
+                sb.append("\n");
+            }
+        } catch (Exception e) {
+            sb.append("鍒嗘瀽澶辫触: ").append(e.getMessage());
+        }
+        return sb.toString();
+    }
+}

--
Gitblit v1.9.3