| | |
| | | import com.ruoyi.device.service.DeviceRecordService; |
| | | import com.ruoyi.system.domain.vo.SysRoleVo; |
| | | import com.ruoyi.system.mapper.SysRoleMenuMapper; |
| | | import org.apache.poi.xwpf.usermodel.BreakType; |
| | | import org.apache.poi.xwpf.usermodel.ParagraphAlignment; |
| | | import org.apache.poi.xwpf.usermodel.TableRowAlign; |
| | | import org.apache.poi.xwpf.usermodel.UnderlinePatterns; |
| | |
| | | private static final String RECORD_NUMBER = "LMSY-CX07-JL03"; |
| | | private static final String FONT_NAME = "宋体"; |
| | | private static final int[] COLUMN_WIDTHS = {1622, 4168, 1288, 1107, 1137, 1076, 940, 1182, 1288, 1350}; |
| | | private static final String[] HEADER_FIRST_ROW = {"使用日期", "样品编号", "时间 24 小时制", "", "设备状况", "", "环境条件", "", "使用人", "备注"}; |
| | | private static final String[] HEADER_FIRST_ROW = {"使用日期", "样品名称", "时间 24 小时制", "", "设备状况", "", "环境条件", "", "使用人", "备注"}; |
| | | private static final String[] HEADER_SECOND_ROW = {"", "", "开始", "结束", "使用前", "使用后", "℃", "%RH", "", ""}; |
| | | private static final int[] COMBINED_COLUMN_WIDTHS = {1300, 2000, 1500, 1600, 2000, 900, 900, 800, 800, 650, 750, 950, 1008}; |
| | | private static final String[] COMBINED_HEADER_FIRST_ROW = {"使用日期", "设备名称", "设备型号", "设备编号", "样品编号", "时间 24 小时制", "", "设备状况", "", "环境条件", "", "使用人", "备注"}; |
| | | private static final String[] COMBINED_HEADER_SECOND_ROW = {"", "", "", "", "", "开始", "结束", "使用前", "使用后", "℃", "%RH", "", ""}; |
| | | private static final String FOOTNOTE = "注:设备使用前后一栏,正常划“√”;不正常划“×”并写明情况。"; |
| | | private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
| | | private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm"); |
| | | |
| | |
| | | private SysRoleMenuMapper sysRoleMenuMapper; |
| | | |
| | | @Override |
| | | public IPage<DeviceRecordDto> deviceRecordPage(Integer deviceId, Page page, String sampleCode, String managementNumber) { |
| | | public IPage<DeviceRecordDto> deviceRecordPage(Integer deviceId, Page page, String deviceName, |
| | | String specificationModel, String sampleCode, |
| | | String managementNumber) { |
| | | // todo:仅看自己 |
| | | Long userId = SecurityUtils.getUserId(); |
| | | // 获取权限判断是否是仅看我 |
| | |
| | | testUserId = SecurityUtils.getUserId().intValue(); |
| | | } |
| | | |
| | | return baseMapper.deviceRecordPage(deviceId, page, sampleCode, managementNumber, testUserId); |
| | | return baseMapper.deviceRecordPage(deviceId, page, deviceName, specificationModel, |
| | | sampleCode, managementNumber, testUserId); |
| | | } |
| | | |
| | | @Override |
| | | public void exportUseRecord(Integer deviceId, String sampleCode, String managementNumber, String exportDate, HttpServletResponse response) { |
| | | List<DeviceRecordDto> records = baseMapper.selectExportList(deviceId, sampleCode, managementNumber, exportDate); |
| | | public void exportUseRecord(Integer deviceId, String deviceName, String specificationModel, |
| | | String managementNumber, String sampleCode, HttpServletResponse response) { |
| | | List<DeviceRecordDto> records = baseMapper.selectExportList(deviceId, deviceName, |
| | | specificationModel, managementNumber, sampleCode); |
| | | if (records == null || records.isEmpty()) { |
| | | throw new ServiceException(exportDate == null || exportDate.isEmpty() |
| | | ? "没有可导出的使用记录,无法导出" |
| | | : exportDate + " 没有可导出的使用记录,无法导出"); |
| | | throw new ServiceException("没有可导出的使用记录,无法导出"); |
| | | } |
| | | |
| | | // 单台设备沿用截图表头; 多台设备合并到一张表, 每行带设备信息 |
| | | // 一台设备一本运行记录,多台设备在同一 Word 内按设备分页 |
| | | Map<Integer, List<DeviceRecordDto>> deviceRecords = new LinkedHashMap<>(); |
| | | for (DeviceRecordDto record : records) { |
| | | deviceRecords.computeIfAbsent(record.getDeviceId(), key -> new ArrayList<>()).add(record); |
| | |
| | | |
| | | try (XWPFDocument document = new XWPFDocument()) { |
| | | setupPage(document); |
| | | if (deviceRecords.size() == 1) { |
| | | List<DeviceRecordDto> group = deviceRecords.values().iterator().next(); |
| | | renderForm(document, group.get(0), group); |
| | | } else { |
| | | renderCombinedForm(document, records); |
| | | boolean first = true; |
| | | for (List<DeviceRecordDto> group : deviceRecords.values()) { |
| | | if (!first) { |
| | | addPageBreak(document); |
| | | } |
| | | renderForm(document, group.get(0), mergeSameConditionRecords(group)); |
| | | first = false; |
| | | } |
| | | |
| | | response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); |
| | |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导出失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 同一设备、同一天、起止时间/温湿度/使用人/使用前后状况相同的记录合并一行,样品编号用“、”拼接。 |
| | | */ |
| | | private List<DeviceRecordDto> mergeSameConditionRecords(List<DeviceRecordDto> records) { |
| | | Map<String, DeviceRecordDto> merged = new LinkedHashMap<>(); |
| | | for (DeviceRecordDto record : records) { |
| | | String key = String.join("|", |
| | | formatDate(record.getUseStartDate()), |
| | | formatTime(record.getUseStartDate()), |
| | | formatTime(record.getUseEndDate()), |
| | | valueOrEmpty(record.getTemperature()), |
| | | valueOrEmpty(record.getHumidity()), |
| | | valueOrEmpty(record.getUsePerson()), |
| | | String.valueOf(record.getUseBefore()), |
| | | String.valueOf(record.getUseAfter())); |
| | | DeviceRecordDto existing = merged.get(key); |
| | | if (existing == null) { |
| | | merged.put(key, record); |
| | | } else { |
| | | existing.setSampleCode(appendDistinct(existing.getSampleCode(), record.getSampleCode())); |
| | | existing.setRemark(appendDistinct(existing.getRemark(), record.getRemark())); |
| | | } |
| | | } |
| | | return new ArrayList<>(merged.values()); |
| | | } |
| | | |
| | | private String appendDistinct(String existing, String addition) { |
| | | if (addition == null || addition.trim().isEmpty()) { |
| | | return existing; |
| | | } |
| | | if (existing == null || existing.trim().isEmpty()) { |
| | | return addition; |
| | | } |
| | | List<String> parts = java.util.Arrays.asList(existing.split("、")); |
| | | return parts.contains(addition) ? existing : existing + "、" + addition; |
| | | } |
| | | |
| | | private void addPageBreak(XWPFDocument document) { |
| | | XWPFParagraph paragraph = document.createParagraph(); |
| | | paragraph.setSpacingAfter(0); |
| | | paragraph.createRun().addBreak(BreakType.PAGE); |
| | | } |
| | | |
| | | private void setupPage(XWPFDocument document) { |
| | |
| | | setCellText(row.getCell(j), values[j]); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void renderCombinedForm(XWPFDocument document, List<DeviceRecordDto> records) { |
| | | XWPFParagraph recordNumber = addParagraph(document, "记录编号:" + RECORD_NUMBER, 10.5, false, ParagraphAlignment.LEFT); |
| | | recordNumber.setSpacingAfter(240); |
| | | |
| | | XWPFParagraph title = addParagraph(document, FORM_TITLE, 22, true, ParagraphAlignment.CENTER); |
| | | title.setSpacingAfter(240); |
| | | |
| | | XWPFTable table = document.createTable(2 + records.size(), COMBINED_COLUMN_WIDTHS.length); |
| | | configureTable(table, COMBINED_COLUMN_WIDTHS); |
| | | |
| | | for (int i = 0; i < table.getNumberOfRows(); i++) { |
| | | XWPFTableRow row = table.getRow(i); |
| | | row.setHeight(i < 2 ? 560 : 520); |
| | | for (int j = 0; j < COMBINED_COLUMN_WIDTHS.length; j++) { |
| | | setCellWidth(row.getCell(j), COMBINED_COLUMN_WIDTHS[j]); |
| | | } |
| | | setRowProperties(row, i < 2); |
| | | } |
| | | |
| | | XWPFTableRow firstHeader = table.getRow(0); |
| | | for (int i = 0; i < COMBINED_HEADER_FIRST_ROW.length; i++) { |
| | | setCellText(firstHeader.getCell(i), COMBINED_HEADER_FIRST_ROW[i]); |
| | | } |
| | | XWPFTableRow secondHeader = table.getRow(1); |
| | | for (int i = 0; i < COMBINED_HEADER_SECOND_ROW.length; i++) { |
| | | setCellText(secondHeader.getCell(i), COMBINED_HEADER_SECOND_ROW[i]); |
| | | } |
| | | |
| | | mergeHorizontal(firstHeader, COMBINED_COLUMN_WIDTHS, 9, 2); |
| | | mergeHorizontal(firstHeader, COMBINED_COLUMN_WIDTHS, 7, 2); |
| | | mergeHorizontal(firstHeader, COMBINED_COLUMN_WIDTHS, 5, 2); |
| | | mergeVertical(firstHeader.getCell(0), secondHeader.getCell(0)); |
| | | mergeVertical(firstHeader.getCell(1), secondHeader.getCell(1)); |
| | | mergeVertical(firstHeader.getCell(2), secondHeader.getCell(2)); |
| | | mergeVertical(firstHeader.getCell(3), secondHeader.getCell(3)); |
| | | mergeVertical(firstHeader.getCell(4), secondHeader.getCell(4)); |
| | | mergeVertical(firstHeader.getCell(8), secondHeader.getCell(11)); |
| | | mergeVertical(firstHeader.getCell(9), secondHeader.getCell(12)); |
| | | |
| | | for (int i = 0; i < records.size(); i++) { |
| | | XWPFTableRow row = table.getRow(2 + i); |
| | | String[] values = buildCombinedRowValues(records.get(i)); |
| | | for (int j = 0; j < values.length; j++) { |
| | | setCellText(row.getCell(j), values[j]); |
| | | } |
| | | } |
| | | XWPFParagraph footnote = addParagraph(document, FOOTNOTE, 10.5, false, ParagraphAlignment.LEFT); |
| | | footnote.setSpacingBefore(120); |
| | | footnote.setSpacingAfter(0); |
| | | } |
| | | |
| | | private XWPFParagraph addParagraph(XWPFDocument document, String text, double fontSize, boolean bold, ParagraphAlignment alignment) { |
| | |
| | | }; |
| | | } |
| | | |
| | | private String[] buildCombinedRowValues(DeviceRecordDto record) { |
| | | return new String[]{ |
| | | formatDate(record.getUseStartDate()), |
| | | valueOrEmpty(record.getDeviceName()), |
| | | valueOrEmpty(record.getSpecificationModel()), |
| | | valueOrEmpty(record.getManagementNumber()), |
| | | valueOrEmpty(record.getSampleCode()), |
| | | formatTime(record.getUseStartDate()), |
| | | formatTime(record.getUseEndDate()), |
| | | statusText(record.getUseBefore()), |
| | | statusText(record.getUseAfter()), |
| | | valueOrEmpty(record.getTemperature()), |
| | | valueOrEmpty(record.getHumidity()), |
| | | valueOrEmpty(record.getUsePerson()), |
| | | valueOrEmpty(record.getRemark()) |
| | | }; |
| | | } |
| | | |
| | | private String formatDate(LocalDateTime value) { |
| | | return value == null ? "" : value.format(DATE_FORMATTER); |
| | | } |
| | |
| | | if (value == null) { |
| | | return ""; |
| | | } |
| | | return value == 0 ? "异常" : "良好"; |
| | | return value == 0 ? "异常" : "正常"; |
| | | } |
| | | |
| | | private String valueOrEmpty(String value) { |