| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | import org.apache.poi.xwpf.usermodel.ParagraphAlignment; |
| | | import org.apache.poi.xwpf.usermodel.XWPFDocument; |
| | | import org.apache.poi.xwpf.usermodel.XWPFParagraph; |
| | | import org.apache.poi.xwpf.usermodel.XWPFRun; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTable; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTableCell; |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** 新版方法验证主表导出;原始记录和验证结果仍作为附件保存。 */ |
| | | /** 按客户提供的横向方法验证表导出;原始记录和验证结果仍作为附件保存。 */ |
| | | private void exportWordVerification(ProcessMethodVerify verify, HttpServletResponse response) { |
| | | JSONObject content = JSONUtil.parseObj(verify.getVerificationContent()); |
| | | String[][] checks = { |
| | | {"personnel", "1. 人员能力"}, {"equipment", "2. 检测设备"}, |
| | | {"reagents", "3. 试剂要求"}, {"conditions", "4. 试验条件"}, |
| | | {"sample", "5. 样品处置"}, {"steps", "6. 试验步骤"}, |
| | | {"processing", "7. 数据处理"}, {"qualityControl", "质量控制方法"}, |
| | | {"result", "方法验证结果"} |
| | | }; |
| | | try (XWPFDocument document = new XWPFDocument()) { |
| | | XWPFParagraph title = document.createParagraph(); |
| | | title.setAlignment(ParagraphAlignment.CENTER); |
| | | title.createRun().setText("方法验证记录"); |
| | | String[] checkKeys = {"personnel", "equipment", "reagents", "conditions", "sample", "steps", |
| | | "processing", "qualityControl", "result"}; |
| | | InputStream templateStream = getClass().getResourceAsStream("/static/method-verification-customer.docx"); |
| | | if (templateStream == null) throw new IllegalStateException("方法验证导出模板不存在"); |
| | | try (InputStream inputStream = templateStream; XWPFDocument document = new XWPFDocument(inputStream)) { |
| | | XWPFTable table = document.getTables().get(0); |
| | | setTemplateCell(table, 0, 1, verify.getStandardName()); |
| | | setTemplateCell(table, 0, 3, verify.getStandardCode()); |
| | | setTemplateCell(table, 1, 1, verify.getVerifyItem()); |
| | | |
| | | XWPFTable basic = document.createTable(2, 4); |
| | | setCells(basic, 0, "标准名称", verify.getStandardName(), "标准编号", verify.getStandardCode()); |
| | | setCells(basic, 1, "验证项目", verify.getVerifyItem(), "", ""); |
| | | |
| | | XWPFTable table = document.createTable(checks.length + 1, 4); |
| | | setCells(table, 0, "验证内容", "方法要求", "实验室能力", "是否满足"); |
| | | JSONArray entries = content.getJSONArray("checks"); |
| | | for (int i = 0; i < checks.length; i++) { |
| | | JSONObject entry = findCheck(entries, checks[i][0]); |
| | | for (int i = 0; i < checkKeys.length; i++) { |
| | | JSONObject entry = findCheck(entries, checkKeys[i]); |
| | | Integer satisfied = entry == null ? null : entry.getInt("satisfied"); |
| | | setCells(table, i + 1, checks[i][1], field(entry, "requirement"), |
| | | field(entry, "capability"), satisfied == null ? "" : satisfied == 1 ? "是" : "否"); |
| | | int row = i + 3; |
| | | if (row <= 8) { |
| | | setTemplateCell(table, row, 1, field(entry, "requirement")); |
| | | setTemplateCell(table, row, 2, field(entry, "capability")); |
| | | setTemplateCell(table, row, 3, satisfiedText(satisfied)); |
| | | } else { |
| | | setTemplateCell(table, row, 1, mergedCheckText(entry)); |
| | | setTemplateCell(table, row, 2, satisfiedText(satisfied)); |
| | | } |
| | | } |
| | | setTemplateCell(table, 12, 1, field(content, "conclusion")); |
| | | setTemplateCell(table, 13, 1, decisionText(field(content, "reviewDecision"), |
| | | "评审人员", field(content, "reviewer"), field(content, "reviewDate"))); |
| | | setTemplateCell(table, 14, 1, decisionText(field(content, "approvalDecision"), |
| | | "技术负责人", field(content, "approver"), field(content, "approvalDate"))); |
| | | |
| | | XWPFTable conclusion = document.createTable(1, 2); |
| | | setCells(conclusion, 0, "验证结论", field(content, "conclusion")); |
| | | XWPFTable decisions = document.createTable(2, 4); |
| | | setCells(decisions, 0, "评审意见", field(content, "reviewDecision"), |
| | | "评审人员:" + field(content, "reviewer"), field(content, "reviewDate")); |
| | | setCells(decisions, 1, "审批意见", field(content, "approvalDecision"), |
| | | "技术负责人:" + field(content, "approver"), field(content, "approvalDate")); |
| | | |
| | | document.createParagraph().createRun().setText("附件1 原始记录;附件2 验证结果(附件在系统中查看)"); |
| | | response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); |
| | | String fileName = URLEncoder.encode("方法验证记录", "UTF-8"); |
| | | response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx"); |
| | |
| | | return object == null ? "" : StrUtil.nullToEmpty(object.getStr(key)); |
| | | } |
| | | |
| | | private void setCells(XWPFTable table, int row, String... values) { |
| | | for (int i = 0; i < values.length; i++) { |
| | | XWPFTableCell cell = table.getRow(row).getCell(i); |
| | | cell.setText(StrUtil.nullToEmpty(values[i])); |
| | | private String satisfiedText(Integer satisfied) { |
| | | return satisfied == null ? "" : satisfied == 1 ? "是" : "否"; |
| | | } |
| | | |
| | | private String mergedCheckText(JSONObject entry) { |
| | | String requirement = field(entry, "requirement").trim(); |
| | | String capability = field(entry, "capability").trim(); |
| | | if (requirement.isEmpty()) return capability; |
| | | if (capability.isEmpty() || requirement.equals(capability)) return requirement; |
| | | return "方法要求:" + requirement + "\n实验室能力:" + capability; |
| | | } |
| | | |
| | | private String decisionText(String decision, String personLabel, String person, String date) { |
| | | StringBuilder value = new StringBuilder(); |
| | | for (String choice : new String[]{"同意使用", "不能使用", "限制使用"}) { |
| | | if (value.length() > 0) value.append(" "); |
| | | value.append(choice.equals(decision) ? "☑" : "□").append(choice); |
| | | } |
| | | value.append("\n").append(personLabel).append(":").append(person); |
| | | if (StringUtils.isNotBlank(date)) { |
| | | String[] parts = date.split("-"); |
| | | value.append(" 日期:"); |
| | | value.append(parts.length == 3 ? parts[0] + "年" + parts[1] + "月" + parts[2] + "日" : date); |
| | | } |
| | | return value.toString(); |
| | | } |
| | | |
| | | private void setTemplateCell(XWPFTable table, int row, int cellIndex, String value) { |
| | | XWPFTableCell cell = table.getRow(row).getCell(cellIndex); |
| | | XWPFParagraph paragraph = cell.getParagraphs().get(0); |
| | | XWPFRun run = paragraph.getRuns().get(0); |
| | | String[] lines = StrUtil.nullToEmpty(value).replace("\r\n", "\n").split("\n", -1); |
| | | run.setText(lines[0], 0); |
| | | for (int i = 1; i < lines.length; i++) { |
| | | run.addBreak(); |
| | | run.setText(lines[i]); |
| | | } |
| | | } |
| | | |