zss
2024-10-18 1f15333b0a97a327865f7aab8f1e3f9ba8fc16f8
inspect-server/src/main/java/com/yuanchu/mom/service/impl/InsReportServiceImpl.java
@@ -17,6 +17,7 @@
import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.*;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.data.style.TableStyle;
import com.deepoove.poi.util.TableTools;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.DocumentException;
@@ -37,9 +38,12 @@
import com.yuanchu.mom.utils.JackSonUtil;
import com.yuanchu.mom.utils.MatrixToImageWriter;
import com.yuanchu.mom.utils.QueryWrappers;
import com.yuanchu.mom.utils.WordUtils;
import com.yuanchu.mom.vo.Result;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.util.Strings;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
@@ -103,6 +107,9 @@
    private InsOrderStateMapper insOrderStateMapper;
    @Resource
    WordUtils wordUtils;
    @Resource
    private InsProductMapper insProductMapper;
    @Resource
@@ -110,6 +117,9 @@
    @Resource
    private InsProductResult2Mapper insProductResult2Mapper;
    @Resource
    private InsOrderUserMapper insOrderUserMapper;
    @Resource
    private InsSampleMapper insSampleMapper;
@@ -380,7 +390,8 @@
        Long count = insOrderStateMapper.selectCount(Wrappers.<InsOrderState>lambdaQuery().eq(InsOrderState::getInsOrderId, insReportDto.getId()).eq(InsOrderState::getInsState, 5));
        if (count > 0) {
            if (insReportDto.getState() == 1) {
                generateReport(insReportDto.getId(), insReportDto.getInsReportDto1s());
                List<InsReportDto1> insReportDto1s = insReportDto.getInsReportDto1s();
                wordUtils.generateReport(insReportDto.getId(), insReportDto1s);
            } else {
                //结束订单
                InsOrder insOrder = new InsOrder();
@@ -593,370 +604,6 @@
            over.addImage(img);
        }
        stamp.close();
    }
    //生成报告
    private void generateReport(Integer orderId, List<InsReportDto1> insReportDto1s) {
        LocalDateTime now = LocalDateTime.now();
        InsOrder insOrder = insOrderMapper.selectById(orderId);
        //委托部门 departLims
        String departLims = userMapper.selectDepartLims(insOrder.getPrepareUser());
        //samples是过滤掉没有检验项目的样品
        List<SampleProductDto> samples = insSampleMapper.selectSampleProductListByOrderId(orderId);
        String sampleCode = samples.get(0).getSampleCode();
        InsReport insReport = new InsReport();
        insReport.setCode(insOrder.getEntrustCode().replace("WT","TXJC"));
        insReport.setInsOrderId(orderId);
        List<Map<String, Object>> tables = new ArrayList<>();
        Set<String> standardMethod = new HashSet<>();
        Set<String> deviceSet = new HashSet<>();
        Set<String> models = new HashSet<>();
        AtomicReference<Integer> productSize = new AtomicReference<>(0);
        AtomicReference<Integer> productSize1 = new AtomicReference<>(0);
        AtomicReference<Integer> productSize2 = new AtomicReference<>(0);
        AtomicReference<Integer> productSize3 = new AtomicReference<>(0);
        String[] monthNames = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
        samples.forEach(s -> {
            models.add(s.getModel());
            standardMethod.addAll(standardMethodListMapper.selectList(Wrappers.<StandardMethodList>lambdaQuery()
                    .in(StandardMethodList::getId,Arrays.stream(s.getStandardMethodListId().replaceAll("[\\[\\]]", "").split(","))
                            .map(String::trim).map(Integer::parseInt).collect(Collectors.toList()))).stream().map(aa->{return aa.getCode()+" "+aa.getName();}).distinct().collect(Collectors.toList()));
            //总数
            Long productCount = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
                    .eq(InsProduct::getInsSampleId, s.getId()));
            productSize.set(productSize.get() + Integer.parseInt(productCount + ""));
            //不判定
            Long productCount1 = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
                    .eq(InsProduct::getInsSampleId, s.getId())
                    .eq(InsProduct::getInsResult, 3));
            productSize1.set(productSize1.get() + Integer.parseInt(productCount1 + ""));
            //不合格
            Long productCount2 = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
                    .eq(InsProduct::getInsSampleId, s.getId())
                    .eq(InsProduct::getInsResult, 0));
            productSize2.set(productSize2.get() + Integer.parseInt(productCount2 + ""));
            //合格
            Long productCount3 = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
                    .eq(InsProduct::getInsSampleId, s.getId())
                    .eq(InsProduct::getInsResult, 1));
            productSize3.set(productSize3.get() + Integer.parseInt(productCount3 + ""));
            //将项目按照站点进行分类
            Map<String, List<InsProduct>> listMap = s.getInsProduct().stream().collect(Collectors.groupingBy(InsProduct::getLaboratory));
            // 创建一个 Map 将站点和项目ID的映射关系
            Map<String, Set<Integer>> labToDeviceMap = new HashMap<>();
            // 获取所有站点的项目ID 列表
            for (Map.Entry<String, List<InsProduct>> entry : listMap.entrySet()) {
                Set<Integer> deviceIds = entry.getValue().stream()
                        .map(InsProduct::getId)
                        .collect(Collectors.toSet());
                labToDeviceMap.put(entry.getKey(), deviceIds);
            }
            for (InsReportDto1 insReportDto1 : insReportDto1s) {
                String laboratory = insReportDto1.getLaboratory();
                if (!labToDeviceMap.containsKey(laboratory)) {
                    continue;
                }
                Set<Integer> deviceIds = labToDeviceMap.get(laboratory);
                Integer num = insReportDto1.getNum();
                List<InsProductResult> insProductResults = insProductResultMapper.selectList(
                        Wrappers.<InsProductResult>lambdaQuery()
                                .eq(InsProductResult::getNum, num)
                                .in(InsProductResult::getInsProductId, deviceIds));
                for (InsProductResult insProductResult : insProductResults) {
                    List<JSONObject> jsonObjects = JSON.parseArray(insProductResult.getEquipValue(), JSONObject.class);
                    for (JSONObject jsonObject : jsonObjects) {
                        String value = jsonObject.getString("v");
                        if (value != null && !value.isEmpty()) {
                            deviceSet.add(value);
                        }
                    }
                }
                List<InsProductResult2> insProductResult2s = insProductResult2Mapper.selectList(
                        Wrappers.<InsProductResult2>lambdaQuery()
                                .eq(InsProductResult2::getNum, num)
                                .in(InsProductResult2::getInsProductId, deviceIds));
                for (InsProductResult2 result2 : insProductResult2s) {
                    String equipValue = result2.getEquipValue();
                    if (equipValue != null && !equipValue.isEmpty()) {
                        deviceSet.add(equipValue);
                    }
                }
            }
        });
        String url;
        try {
            InputStream inputStream = this.getClass().getResourceAsStream("/static/report-template.docx");
            File file = File.createTempFile("temp", ".tmp");
            OutputStream outputStream = new FileOutputStream(file);
            IOUtils.copy(inputStream, outputStream);
            url = file.getAbsolutePath();
        } catch (FileNotFoundException e) {
            throw new ErrorException("找不到模板文件");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        StringBuilder standardMethod2 = new StringBuilder();
        for (String s : standardMethod) {
            standardMethod2.append(";\n").append(s);
        }
        standardMethod2.append(";\n").append("GB/T 9410-2008 《移动通信天线通用技术规范》");
        standardMethod2.replace(0, 1, "");
        tables.forEach(table -> {
            table.put("tableSize", tables.size() + 1);
        });
        List<Map<String, String>> deviceList = null;
        if (deviceSet.size() != 0) {
            deviceList = insOrderMapper.selectDeviceList(deviceSet);
        }
        Map<String, String> codeStr = new HashMap<>();
        codeStr.put("报告编号", insReport.getCode());
        codeStr.put("样品名称", insOrder.getSample());
        codeStr.put("规格型号", samples.get(0).getModel());
        codeStr.put("发放日期", now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        String codePath;
        try {
            codePath = new MatrixToImageWriter().code(JackSonUtil.marshal(codeStr).replaceAll("\\{", "")
                    .replaceAll("}", "").replaceAll(",", "").replaceAll("\"", ""), twoCode);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String modelStr = "";
        for (String model : models) {
            modelStr += "," + model;
        }
        String finalModelStr = modelStr;
        String sampleEn = insSampleMapper.getSampleEn(insOrder.getSample());
        String orderType = insOrderMapper.getEnumLabelByValue(insOrder.getOrderType());
        String formType = insOrderMapper.getEnumLabelByValue(insOrder.getFormType());
        ConfigureBuilder builder = Configure.builder();
        builder.useSpringEL(true);
        List<Map<String, String>> finalDeviceList = deviceList;
        List<Map<String, String>> sampleList = insSampleMapper.selectSampleList(orderId);
        Integer userId = insSampleUserMapper.selectOne(Wrappers.<InsSampleUser>lambdaQuery()
                .eq(InsSampleUser::getInsSampleId, orderId).last("limit 1")).getUserId();
        String signatureUrl;
        try {
            signatureUrl = userMapper.selectById(userId).getSignatureUrl();
        } catch (Exception e) {
            throw new ErrorException("找不到检验人的签名");
        }
        if (ObjectUtils.isEmpty(signatureUrl) || signatureUrl.equals("")) {
            throw new ErrorException("找不到检验人的签名");
        }
        Custom custom = customMapper.selectById(insOrder.getCompanyId());
        /*获取附件图片类型*/
        List<Map<String, Object>> images = new ArrayList<>();
        List<InsOrderFile> insOrderFiles = insOrderFileMapper.selectList(Wrappers.<InsOrderFile>lambdaQuery().eq(InsOrderFile::getType, 1).eq(InsOrderFile::getInsOrderId, orderId));
        if (CollectionUtils.isNotEmpty(insOrderFiles)) {
            insOrderFiles.forEach(insOrderFile -> {
                Map<String, Object> image = new HashMap<>();
                PictureRenderData pictureRenderData = Pictures.ofLocal(imgUrl + "/" + insOrderFile.getFileUrl()).sizeInCm(17, 20).create();
                image.put("url", pictureRenderData);
                image.put("report", insReport);
                images.add(image);
            });
        }
        //委托人和电话字段判断
        if (ObjectUtils.isEmpty(insOrder.getPrepareUser())) {
            insOrder.setPrepareUser("/");
        }
        if (ObjectUtils.isEmpty(insOrder.getPhone())) {
            insOrder.setPhone("/");
        }
        //检验项目的环境
        InsProduct insProduct = insProductMapper.selectList(Wrappers.<InsProduct>lambdaQuery().eq(InsProduct::getState, 1).eq(InsProduct::getInsSampleId, samples.get(0).getId())).get(0);
        String environment = "";
        environment = (ObjectUtils.isNotEmpty(insProduct.getTemperature()) ? insProduct.getTemperature() + "℃ " : "") + (ObjectUtils.isNotEmpty(insProduct.getHumidity()) ? insProduct.getHumidity() + "%" : "");
        String finalEnvironment = environment;
        List<SampleProductDto> finalSamples = samples;
        XWPFTemplate template = XWPFTemplate.compile(url, builder.build()).render(
                new HashMap<String, Object>() {{
                    put("order", insOrder);
                    put("report", insReport);
                    put("departLims", departLims);
                    put("sampleCode", sampleCode);
                    put("environment", finalEnvironment);
                    put("custom", custom);
                    put("sampleSize", finalSamples.size());
                    put("tables", tables);
                    put("tableSize", tables.size() + 1);
                    put("standardMethod", (standardMethod2.toString().equals("null") ? "" : standardMethod2));
                    put("deviceList", finalDeviceList);
                    put("sampleList", sampleList);
                    put("twoCode", Pictures.ofLocal(codePath).create());
                    put("models", finalModelStr.replace(",", ""));
                    put("productSize", productSize);
                    put("productSize1", productSize1);
                    put("productSize2", productSize2);
                    put("productSize3", productSize3);
                    put("createTime", now.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
                    put("createTimeEn", monthNames[now.getMonthValue() - 1] + " " + now.getDayOfMonth() + ", " + now.getYear());
                    put("insTime", insOrder.getInsTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
                    put("insTimeEn", monthNames[insOrder.getInsTime().getMonthValue() - 1] + " " + insOrder.getInsTime().getDayOfMonth() + ", " + insOrder.getInsTime().getYear());
                    put("writeUrl", null);
                    put("insUrl", Pictures.ofLocal(imgUrl + "/" + signatureUrl).create());
                    put("images", images);
                    put("examineUrl", null);
                    put("ratifyUrl", null);
                    put("sampleEn", sampleEn);
                    put("orderType", orderType);
                    put("getTime", insOrder.getExamineTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
                    put("getTimeEn", monthNames[insOrder.getExamineTime().getMonthValue() - 1] + " " + insOrder.getExamineTime().getDayOfMonth() + ", " + insOrder.getExamineTime().getYear());
                    put("seal1", null);
                    put("seal2", null);
                    put("formTypeCh", formType);
                    put("formTypeEn", insOrder.getFormType());
                }});
        try {
            String name = insReport.getCode().replace("/", "") + ".docx";
            template.writeAndClose(Files.newOutputStream(Paths.get(wordUrl + "/" + name)));
            insReport.setUrl("/word/" + name);
            insReportMapper.insert(insReport);
            insOrder.setInsState(5);
            insOrderMapper.updateById(insOrder);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 处理合并单元格的问题
        String path = wordUrl + "/" + insReport.getCode().replace("/", "") + ".docx";
        try {
            FileInputStream stream = new FileInputStream(path);
            XWPFDocument document = new XWPFDocument(stream);
            List<XWPFTable> xwpfTables = document.getTables();
            for (int i = 1; i < xwpfTables.size() - (deviceList == null ? 1 : 2); i++) {
                Set<String> set1 = new HashSet<>();
                Map<String, Map<String, Integer>> maps = new HashMap<>();
                for (int j = 0; j < xwpfTables.get(i).getRows().size(); j++) {
                    for (int k = 0; k < xwpfTables.get(i).getRows().get(j).getTableCells().size(); k++) {
                        if (xwpfTables.get(i).getRows().get(j).getTableCells().get(k).getText().indexOf("∑") > -1) {
                            String[] split = xwpfTables.get(i).getRows().get(j).getTableCells().get(k).getText().split("∑");
                            if (set1.add(split[1])) {
                                Map<String, Integer> map = new HashMap<>();
                                map.put("sr", j);
                                map.put("sc", k);
                                map.put("er", j + 0);
                                map.put("ec", k + 0);
                                maps.put(split[1], map);
                            } else {
                                Map<String, Integer> map1 = maps.get(split[1]);
                                if (j == map1.get("sr")) {
                                    map1.put("ec", map1.get("ec") + 1);
                                } else if (k == map1.get("sc")) {
                                    map1.put("er", map1.get("er") + 1);
                                }
                            }
                            String str = xwpfTables.get(i).getRows().get(j).getTableCells().get(k).getText().split("∑")[0];
                            xwpfTables.get(i).getRows().get(j).getTableCells().get(k).removeParagraph(0);
                            xwpfTables.get(i).getRows().get(j).getTableCells().get(k).setText(str);
                            xwpfTables.get(i).getRows().get(j).getTableCells().get(k).setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                            xwpfTables.get(i).getRows().get(j).getTableCells().get(k).getParagraphArray(0).setAlignment(org.apache.poi.xwpf.usermodel.ParagraphAlignment.CENTER);
                        }
                    }
                }
                List<String> list = new ArrayList<>();
                for (String s : maps.keySet()) {
                    list.add(s);
                }
                for (int a = list.size() - 1; a >= 0; a--) {
                    Map<String, Integer> v = maps.get(list.get(a));
                    for (int j = 0; j < v.get("er") - v.get("sr") + 1; j++) {
                        if (v.get("ec") > v.get("sc")) {
                            try {
                                TableTools.mergeCellsHorizonal(xwpfTables.get(i), v.get("sr") + j, v.get("sc"), v.get("ec"));
                            } catch (Exception e) {
                            }
                        }
                    }
                    if (v.get("er") > v.get("sr")) {
                        try {
                            TableTools.mergeCellsVertically(xwpfTables.get(i), v.get("sc"), v.get("sr"), v.get("er"));
                        } catch (Exception e) {
                        }
                    }
                }
            }
            FileOutputStream fileOutputStream = new FileOutputStream(path);
            document.write(fileOutputStream);
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //处理中英文换行的问题
        try {
            FileInputStream stream1 = new FileInputStream(path);
            XWPFDocument document1 = new XWPFDocument(stream1);
            List<XWPFTable> xwpfTables1 = document1.getTables();
            for (int i = 1; i < xwpfTables1.size() - (deviceList == null ? 1 : 2); i++) {
                for (int j = 0; j < xwpfTables1.get(i).getRows().size(); j++) {
                    for (int k = 0; k < xwpfTables1.get(i).getRows().get(j).getTableCells().size(); k++) {
                        if (xwpfTables1.get(i).getRows().get(j).getTableCells().get(k).getText().contains("@")) {
                            String text = xwpfTables1.get(i).getRows().get(j).getTableCells().get(k).getText();
                            String[] split = text.split("@");
                            xwpfTables1.get(i).getRows().get(j).getTableCells().get(k).removeParagraph(0);
                            XWPFParagraph xwpfParagraph = xwpfTables1.get(i).getRows().get(j).getTableCells().get(k).addParagraph();
                            XWPFRun run = xwpfParagraph.createRun();
                            run.setText(split[0]);
                            if (ObjectUtils.isNotNull(split[1])) {
                                run.addBreak();
                                run.setText(split[1]);
                            }
                            xwpfParagraph.setAlignment(org.apache.poi.xwpf.usermodel.ParagraphAlignment.CENTER);
                        }
                    }
                }
            }
            FileOutputStream fileOutputStream1 = new FileOutputStream(path);
            document1.write(fileOutputStream1);
            fileOutputStream1.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    // 计算行高的方法
    private int calculateRowHeight(RowRenderData rowRenderData) {
        // 实现计算逻辑,可能需要根据单元格内容和字体等参数进行计算
        int height = 0;
        for (CellRenderData cell : rowRenderData.getCells()) {
            int cellHeight = estimateCellHeight(cell); // 根据内容估算单元格高度
            if (cellHeight > height) {
                height = cellHeight;
            }
        }
        return height;
    }
    //根据单元格的文本内容计算实际行高
    private int estimateCellHeight(CellRenderData cellRenderData) {
        // 假设默认行高是40
        int defaultHeight = 40;
        // 获取单元格中的所有段落
        List<ParagraphRenderData> paragraphs = cellRenderData.getParagraphs();
        int estimatedHeight = 0;
        // 遍历段落,估算每个段落的高度
        for (ParagraphRenderData paragraph : paragraphs) {
            List<RenderData> contents = paragraph.getContents();
            for (RenderData content : contents) {
                if (content instanceof TextRenderData) {
                    TextRenderData text = (TextRenderData) content;
                    Style style = text.getStyle();
                    // 假设每行文本的高度为字体大小的1.2倍
                    Double fontSize = Objects.isNull(style.getFontSize()) ? 12.0 : style.getFontSize();
                    int lines = (int) Math.ceil(text.getText().length() / 15.0); // 假设每行约15个字符
                    int textHeight = (int) (fontSize * 1.2 * lines);
                    // 累加段落的高度
                    estimatedHeight += textHeight;
                }
            }
        }
        // 返回最大值,确保高度不低于默认高度
        return Math.max(estimatedHeight, defaultHeight);
    }
}