| | |
| | | import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.deepoove.poi.XWPFTemplate; |
| | | import com.deepoove.poi.config.Configure; |
| | | import com.ruoyi.common.constant.MenuJumpPathConstants; |
| | | import com.ruoyi.common.core.domain.entity.InformationNotification; |
| | | import com.ruoyi.common.core.domain.entity.User; |
| | |
| | | import com.ruoyi.device.pojo.DeviceExaminePlanDetails; |
| | | import com.ruoyi.device.pojo.DeviceExamineRecord; |
| | | import com.ruoyi.device.pojo.DeviceExamineRecordDetail; |
| | | import com.ruoyi.device.service.DeviceExaminePlanService; |
| | | import com.ruoyi.device.service.DeviceExamineRecordDetailService; |
| | | import com.ruoyi.device.service.DeviceExamineRecordService; |
| | | import com.ruoyi.framework.exception.ErrorException; |
| | | import com.ruoyi.inspect.util.HackLoopTableRenderPolicy; |
| | | import com.ruoyi.inspect.util.UserUtils; |
| | | import com.ruoyi.system.mapper.UserMapper; |
| | | import com.ruoyi.system.service.InformationNotificationService; |
| | | 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; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTableRow; |
| | | import org.apache.xmlbeans.XmlCursor; |
| | | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
| | | import org.w3c.dom.Element; |
| | | import org.w3c.dom.Node; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.net.URLEncoder; |
| | | import java.util.HashMap; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public class DeviceExamineRecordServiceImpl extends ServiceImpl<DeviceExamineRecordMapper, DeviceExamineRecord> implements DeviceExamineRecordService { |
| | | |
| | | /** 按设备套用的期间核查记录模板(与设备名称/型号匹配) */ |
| | | private static final String TEMPLATE_BALANCE_PERCENT = "/static/word/examine/examine-balance-percent.docx"; |
| | | private static final String TEMPLATE_BALANCE_PERCENT_BSA2202S = "/static/word/examine/examine-balance-percent-bsa2202s.docx"; |
| | | private static final String TEMPLATE_BALANCE_THOUSANDTH = "/static/word/examine/examine-balance-thousandth.docx"; |
| | | private static final String TEMPLATE_BALANCE_0_1MG_ME204E = "/static/word/examine/examine-balance-0.1mg-me204e.docx"; |
| | | private static final String TEMPLATE_BALANCE_0_1MG_AL204 = "/static/word/examine/examine-balance-0.1mg-al204.docx"; |
| | | private static final String TEMPLATE_SURFACE_TENSION = "/static/word/examine/examine-surface-tension.docx"; |
| | | private static final String TEMPLATE_ROTARY_VISCOSITY = "/static/word/examine/examine-rotary-viscosity.docx"; |
| | | private static final String TEMPLATE_VISCOSITY_PIN = "/static/word/examine/examine-viscosity-pin.docx"; |
| | | private static final String TEMPLATE_SPECTROPHOTOMETER = "/static/word/examine/examine-spectrophotometer.docx"; |
| | | /** 没有对应设备专用模板时套用的通用期间核查记录表 */ |
| | | private static final String TEMPLATE_GENERIC = "/static/word/examine/examine-generic.docx"; |
| | | |
| | | private static final String WORD_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; |
| | | private static final String RECORD_NUMBER_TEXT = "记录编号:LMSY-CX09-JL02"; |
| | | |
| | | @Resource |
| | | private DeviceExamineRecordDetailService deviceExamineRecordDetailService; |
| | | @Resource |
| | | private DeviceExaminePlanService deviceExaminePlanService; |
| | | @Resource |
| | | private DeviceExaminePlanDetailsMapper deviceExaminePlanDetailsMapper; |
| | | @Resource |
| | |
| | | if (dto.getPlanDetailsId() == null) { |
| | | throw new ErrorException("缺少计划详细信息id"); |
| | | } |
| | | LambdaUpdateWrapper<DeviceExamineRecord> wrapper = Wrappers.<DeviceExamineRecord>lambdaUpdate() |
| | | .eq(DeviceExamineRecord::getPlanDetailsId, dto.getPlanDetailsId()) |
| | | .set(DeviceExamineRecord::getReviewStatus, dto.getReviewStatus()) |
| | | .set(DeviceExamineRecord::getReviewRemark, dto.getReviewRemark()); |
| | | |
| | | // 为0清除审核人 |
| | | if (dto.getReviewStatus().equals(0)) { |
| | | wrapper.set(DeviceExamineRecord::getReviewUserId, null) |
| | | .set(DeviceExamineRecord::getReviewUser, null); |
| | | DeviceExaminePlanDetails planDetails = deviceExaminePlanDetailsMapper.selectById(dto.getPlanDetailsId()); |
| | | if (planDetails == null) { |
| | | throw new ErrorException("核查计划明细不存在"); |
| | | } |
| | | if (planDetails.getCheckChargerUserId() == null && StringUtils.isBlank(planDetails.getCheckChargerUser())) { |
| | | throw new ErrorException("请先在编辑中填写核查负责人"); |
| | | } |
| | | |
| | | this.update(wrapper); |
| | | Integer reviewStatus = dto.getReviewStatus(); |
| | | Integer reviewerId = SecurityUtils.getUserId().intValue(); |
| | | User reviewer = userMapper.selectById(reviewerId); |
| | | |
| | | LambdaUpdateWrapper<DeviceExamineRecord> wrapper = Wrappers.<DeviceExamineRecord>lambdaUpdate() |
| | | .eq(DeviceExamineRecord::getPlanDetailsId, dto.getPlanDetailsId()) |
| | | .set(DeviceExamineRecord::getReviewStatus, reviewStatus) |
| | | .set(DeviceExamineRecord::getReviewRemark, dto.getReviewRemark()) |
| | | // 审核动作时间即核查完成时间,列表「核查时间」按它显示 |
| | | .set(DeviceExamineRecord::getUpdateTime, LocalDateTime.now()); |
| | | |
| | | // 为0清除审核人 |
| | | if (reviewStatus != null && reviewStatus == 0) { |
| | | wrapper.set(DeviceExamineRecord::getReviewUserId, null) |
| | | .set(DeviceExamineRecord::getReviewUser, null); |
| | | } else { |
| | | wrapper.set(DeviceExamineRecord::getReviewUserId, reviewerId) |
| | | .set(DeviceExamineRecord::getReviewUser, reviewer == null ? null : reviewer.getName()); |
| | | } |
| | | |
| | | boolean updated = this.update(wrapper); |
| | | // 计划行尚未录入核查记录时,补一条审核结果记录,保证列表能显示通过/不通过状态 |
| | | if (!updated) { |
| | | DeviceExamineRecord record = new DeviceExamineRecord(); |
| | | record.setPlanDetailsId(dto.getPlanDetailsId()); |
| | | record.setReviewStatus(reviewStatus); |
| | | record.setReviewRemark(dto.getReviewRemark()); |
| | | record.setCheckerUserId(planDetails.getCheckChargerUserId()); |
| | | record.setCheckerUser(planDetails.getCheckChargerUser()); |
| | | if (reviewStatus != null && reviewStatus == 1) { |
| | | record.setReviewUserId(reviewerId); |
| | | record.setReviewUser(reviewer == null ? null : reviewer.getName()); |
| | | } |
| | | this.save(record); |
| | | } |
| | | |
| | | // 复核通过后,设备档案的最近/下次核查日期按审核当天滚动;计划行的检查日期是计划日期,审核不改它 |
| | | if (reviewStatus != null && reviewStatus == 1) { |
| | | deviceExaminePlanService.updateDeviceExamineDate(dto.getPlanDetailsId()); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | |
| | | public void exportReviewExamineRecordDetail(Integer planDetailsId, HttpServletResponse response) { |
| | | // 查询复核核查记录 |
| | | DeviceExamineRecordDto deviceExamineRecordDto = baseMapper.selectReviewExamineRecordDto(planDetailsId); |
| | | if (deviceExamineRecordDto == null) { |
| | | throw new ErrorException("该计划明细暂无核查记录,请先录入后再导出"); |
| | | } |
| | | DeviceExaminePlanDetails planDetails = deviceExaminePlanDetailsMapper.selectById(planDetailsId); |
| | | Device device = planDetails != null && planDetails.getDeviceId() != null |
| | | ? deviceMapper.selectById(planDetails.getDeviceId()) : null; |
| | | |
| | | // 查询复核核查记录详情 |
| | | List<DeviceExamineRecordDetail> deviceExamineRecordDetailList = deviceExamineRecordDetailService.list(Wrappers.<DeviceExamineRecordDetail>lambdaQuery().eq(DeviceExamineRecordDetail::getRecordId, deviceExamineRecordDto.getRecordId())); |
| | | |
| | | // 获取路径 |
| | | InputStream inputStream = this.getClass().getResourceAsStream("/static/word/examine-record.docx"); |
| | | Configure configure = Configure.builder() |
| | | .bind("deviceExamineRecordDetailList", new HackLoopTableRenderPolicy()) |
| | | .build(); |
| | | XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render( |
| | | new HashMap<String, Object>() {{ |
| | | put("deviceExamineRecordDto", deviceExamineRecordDto); |
| | | put("deviceExamineRecordDetailList", deviceExamineRecordDetailList); |
| | | //获取核查人的签名地址 |
| | | put("checkerUserUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceExamineRecordDto.getCheckerUserId())); |
| | | //获取审查人的签名地址 |
| | | put("reviewUserUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceExamineRecordDto.getReviewUserId())); |
| | | }}); |
| | | |
| | | String deviceName = StringUtils.isNotEmpty(deviceExamineRecordDto.getDeviceName()) ? deviceExamineRecordDto.getDeviceName() : ""; |
| | | String fileName; |
| | | try { |
| | | fileName = URLEncoder.encode(deviceName + "期间核查记录.docx", "UTF-8"); |
| | | } catch (Exception e) { |
| | | fileName = "examine-record.docx"; |
| | | } |
| | | |
| | | // 按设备匹配专用模板,匹配不到时套用通用期间核查记录表 |
| | | String templatePath = resolveExamineRecordTemplate(planDetails, device); |
| | | exportByDeviceTemplate(templatePath, planDetails, deviceExamineRecordDto, fileName, response); |
| | | } |
| | | |
| | | /** |
| | | * 按设备名称/型号匹配期间核查记录模板 |
| | | */ |
| | | private String resolveExamineRecordTemplate(DeviceExaminePlanDetails planDetails, Device device) { |
| | | String deviceName = planDetails == null ? null : planDetails.getDeviceName(); |
| | | if (StringUtils.isBlank(deviceName) && device != null) { |
| | | deviceName = device.getDeviceName(); |
| | | } |
| | | String deviceModel = planDetails == null ? null : planDetails.getDeviceModel(); |
| | | if (StringUtils.isBlank(deviceModel) && device != null) { |
| | | deviceModel = device.getSpecificationModel(); |
| | | } |
| | | String name = deviceName == null ? "" : deviceName.trim(); |
| | | String model = deviceModel == null ? "" : deviceModel.trim().toUpperCase(); |
| | | if (name.contains("表面张力")) { |
| | | return TEMPLATE_SURFACE_TENSION; |
| | | } |
| | | if (name.contains("旋转粘度") || name.contains("六速")) { |
| | | return TEMPLATE_ROTARY_VISCOSITY; |
| | | } |
| | | if (name.contains("品氏")) { |
| | | return TEMPLATE_VISCOSITY_PIN; |
| | | } |
| | | if (name.contains("分光光度")) { |
| | | return TEMPLATE_SPECTROPHOTOMETER; |
| | | } |
| | | // 电子天平先按型号细分,再按档位名称 |
| | | if (model.contains("BSA2202S")) { |
| | | return TEMPLATE_BALANCE_PERCENT_BSA2202S; |
| | | } |
| | | if (model.contains("ME204E")) { |
| | | return TEMPLATE_BALANCE_0_1MG_ME204E; |
| | | } |
| | | if (model.contains("AL204")) { |
| | | return TEMPLATE_BALANCE_0_1MG_AL204; |
| | | } |
| | | if (name.contains("万分之")) { |
| | | return TEMPLATE_BALANCE_0_1MG_AL204; |
| | | } |
| | | if (name.contains("千分之")) { |
| | | return TEMPLATE_BALANCE_THOUSANDTH; |
| | | } |
| | | if (name.contains("百分之")) { |
| | | return TEMPLATE_BALANCE_PERCENT; |
| | | } |
| | | return TEMPLATE_GENERIC; |
| | | } |
| | | |
| | | /** |
| | | * 按设备专用模板导出:只填表头信息,检测结果表格留空 |
| | | */ |
| | | private void exportByDeviceTemplate(String templatePath, DeviceExaminePlanDetails planDetails, |
| | | DeviceExamineRecordDto recordDto, String fileName, HttpServletResponse response) { |
| | | try (InputStream inputStream = this.getClass().getResourceAsStream(templatePath)) { |
| | | if (inputStream == null) { |
| | | throw new ErrorException("核查记录模板不存在:" + templatePath); |
| | | } |
| | | XWPFDocument document = new XWPFDocument(inputStream); |
| | | // 通用表按参考图带记录编号;设备专用模板保持模板原样 |
| | | if (TEMPLATE_GENERIC.equals(templatePath)) { |
| | | insertRecordNumberLine(document); |
| | | } |
| | | if (!document.getTables().isEmpty()) { |
| | | fillTemplateTable(document.getTables().get(0), planDetails, recordDto); |
| | | } |
| | | response.setContentType("application/msword"); |
| | | String deviceName = StringUtils.isNotEmpty(deviceExamineRecordDto.getDeviceName()) ? deviceExamineRecordDto.getDeviceName() : ""; |
| | | String fileName = URLEncoder.encode( |
| | | deviceName+ "核查记录", "UTF-8"); |
| | | response.setHeader("Content-disposition", |
| | | "attachment;filename=" + fileName + ".docx"); |
| | | response.setHeader("Content-disposition", "attachment;filename=" + fileName); |
| | | OutputStream os = response.getOutputStream(); |
| | | template.write(os); |
| | | document.write(os); |
| | | os.flush(); |
| | | os.close(); |
| | | inputStream.close(); |
| | | document.close(); |
| | | } catch (ErrorException e) { |
| | | throw e; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | throw new RuntimeException("导出失败"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 在标题上方插入固定的记录编号行 |
| | | */ |
| | | private void insertRecordNumberLine(XWPFDocument document) { |
| | | List<XWPFParagraph> paragraphs = document.getParagraphs(); |
| | | if (paragraphs.isEmpty()) { |
| | | return; |
| | | } |
| | | XmlCursor cursor = paragraphs.get(0).getCTP().newCursor(); |
| | | XWPFParagraph paragraph = document.insertNewParagraph(cursor); |
| | | paragraph.setAlignment(ParagraphAlignment.LEFT); |
| | | XWPFRun run = paragraph.createRun(); |
| | | run.setFontFamily("宋体"); |
| | | run.setFontSize(10.5); |
| | | run.setText(RECORD_NUMBER_TEXT); |
| | | } |
| | | |
| | | /** |
| | | * 按标签定位并填写表头,仪器现状打勾,补填评价/审核人 |
| | | */ |
| | | private void fillTemplateTable(XWPFTable table, DeviceExaminePlanDetails planDetails, DeviceExamineRecordDto recordDto) { |
| | | String checkDate = StringUtils.isNotEmpty(recordDto.getUpdateTimeStr()) ? recordDto.getUpdateTimeStr() |
| | | : (planDetails == null ? "" : planDetails.getCheckTime()); |
| | | String checkerName = resolveCheckerName(planDetails, recordDto); |
| | | String reviewerName = resolveUserName(recordDto.getReviewUserId(), recordDto.getReviewUser()); |
| | | String appearanceStatus = planDetails == null ? null : planDetails.getAppearanceStatus(); |
| | | String runningStatus = planDetails == null ? null : planDetails.getRunningStatus(); |
| | | |
| | | for (XWPFTableRow row : table.getRows()) { |
| | | List<XWPFTableCell> cells = row.getTableCells(); |
| | | for (int i = 0; i < cells.size(); i++) { |
| | | String label = normalizeCellLabel(cells.get(i).getText()); |
| | | if ("外观情况".equals(label)) { |
| | | markOptionCells(cells, i + 1, appearanceStatus); |
| | | continue; |
| | | } |
| | | if ("运行是否正常".equals(label)) { |
| | | markOptionCells(cells, i + 1, runningStatus); |
| | | continue; |
| | | } |
| | | if (label.isEmpty() || i + 1 >= cells.size()) { |
| | | continue; |
| | | } |
| | | XWPFTableCell valueCell = cells.get(i + 1); |
| | | switch (label) { |
| | | case "仪器名称": |
| | | setCellText(valueCell, planDetails == null ? recordDto.getDeviceName() : planDetails.getDeviceName(), true); |
| | | break; |
| | | case "管理编号": |
| | | case "设备编号": |
| | | setCellText(valueCell, planDetails == null ? recordDto.getDeviceNumber() : planDetails.getDeviceNumber(), true); |
| | | break; |
| | | case "设备型号": |
| | | setCellText(valueCell, planDetails == null ? "" : planDetails.getDeviceModel(), true); |
| | | break; |
| | | case "检查日期": |
| | | setCellText(valueCell, checkDate == null ? "" : checkDate, true); |
| | | break; |
| | | case "核查人": |
| | | setCellText(valueCell, checkerName == null ? "" : checkerName, true); |
| | | break; |
| | | case "环境温湿度": |
| | | setCellText(valueCell, planDetails == null ? "" : planDetails.getEnvironment(), true); |
| | | break; |
| | | case "核查依据": |
| | | setCellText(valueCell, planDetails == null ? null : planDetails.getCheckBasis(), false); |
| | | break; |
| | | case "核查方式": |
| | | setCellText(valueCell, planDetails == null ? null : planDetails.getCheckMethod(), false); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | fillEvaluationCell(table, reviewerName, checkDate, appearanceStatus, runningStatus); |
| | | } |
| | | |
| | | /** |
| | | * 仪器现状三选一:选中项显示☑,其余保持□ |
| | | */ |
| | | private void markOptionCells(List<XWPFTableCell> cells, int startIndex, String selected) { |
| | | for (int i = startIndex; i < cells.size() && i <= startIndex + 2; i++) { |
| | | String option = normalizeCellLabel(cells.get(i).getText()); |
| | | if (!"良好".equals(option) && !"一般".equals(option) && !"损坏".equals(option) |
| | | && !"正常".equals(option) && !"异常".equals(option) && !"停机".equals(option)) { |
| | | continue; |
| | | } |
| | | setCellText(cells.get(i), option + (option.equals(selected) ? "☑" : "□"), true); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 核查结果评价勾选 + 审核人/时间填写 |
| | | */ |
| | | private void fillEvaluationCell(XWPFTable table, String reviewerName, String checkDate, |
| | | String appearanceStatus, String runningStatus) { |
| | | boolean hasStatus = StringUtils.isNotEmpty(appearanceStatus) || StringUtils.isNotEmpty(runningStatus); |
| | | boolean satisfied = hasStatus && !"损坏".equals(appearanceStatus) |
| | | && !"异常".equals(runningStatus) && !"停机".equals(runningStatus); |
| | | for (XWPFTableRow row : table.getRows()) { |
| | | for (XWPFTableCell cell : row.getTableCells()) { |
| | | for (XWPFParagraph paragraph : cell.getParagraphs()) { |
| | | String text = paragraph.getText(); |
| | | if (text == null) { |
| | | continue; |
| | | } |
| | | if (text.contains("核查结果评价") && text.contains("满足") && hasStatus) { |
| | | // 模板里两个复选框依次是“满足”“不满足” |
| | | markParagraphSymbol(paragraph, satisfied ? 0 : 1); |
| | | } |
| | | if (text.contains("审核人")) { |
| | | rebuildReviewerParagraph(paragraph, reviewerName, checkDate); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 修改段落里第 targetIndex 个 Wingdings 2 复选框为勾选状态(0x52=☑,0xA3=□) |
| | | */ |
| | | private void markParagraphSymbol(XWPFParagraph paragraph, int targetIndex) { |
| | | int index = 0; |
| | | for (XWPFRun run : paragraph.getRuns()) { |
| | | Node runNode = run.getCTR().getDomNode(); |
| | | for (Node child = runNode.getFirstChild(); child != null; child = child.getNextSibling()) { |
| | | if (child.getNodeType() == Node.ELEMENT_NODE && "sym".equals(child.getLocalName())) { |
| | | ((Element) child).setAttributeNS(WORD_NS, "w:char", index == targetIndex ? "0052" : "00A3"); |
| | | index++; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 重写“审核人/时间”行,填入审核人和日期 |
| | | */ |
| | | private void rebuildReviewerParagraph(XWPFParagraph paragraph, String reviewerName, String checkDate) { |
| | | String text = paragraph.getText(); |
| | | int labelIndex = text == null ? -1 : text.indexOf("审核人"); |
| | | if (labelIndex < 0) { |
| | | return; |
| | | } |
| | | String prefix = text.substring(0, labelIndex); |
| | | String dateLabel = text.contains("日期") ? "日期" : "时间"; |
| | | String newText = prefix + "审核人:" + (reviewerName == null ? "" : reviewerName) |
| | | + " " + dateLabel + ":" + (checkDate == null ? "" : checkDate); |
| | | List<XWPFRun> runs = paragraph.getRuns(); |
| | | if (runs.isEmpty()) { |
| | | XWPFRun run = paragraph.createRun(); |
| | | run.setFontFamily("宋体"); |
| | | run.setFontSize(12); |
| | | run.setText(newText); |
| | | return; |
| | | } |
| | | runs.get(0).setText(newText, 0); |
| | | for (int i = runs.size() - 1; i >= 1; i--) { |
| | | paragraph.removeRun(i); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 写入单元格文本;overwriteBlank=false 时保留模板里的固定文字 |
| | | */ |
| | | private void setCellText(XWPFTableCell cell, String text, boolean overwriteBlank) { |
| | | String value = text == null ? "" : text; |
| | | if (!overwriteBlank && value.trim().isEmpty()) { |
| | | return; |
| | | } |
| | | List<XWPFParagraph> paragraphs = cell.getParagraphs(); |
| | | XWPFParagraph paragraph = paragraphs.isEmpty() ? cell.addParagraph() : paragraphs.get(0); |
| | | for (int i = paragraphs.size() - 1; i >= 1; i--) { |
| | | cell.removeParagraph(i); |
| | | } |
| | | List<XWPFRun> runs = paragraph.getRuns(); |
| | | if (runs.isEmpty()) { |
| | | XWPFRun run = paragraph.createRun(); |
| | | run.setFontFamily("宋体"); |
| | | run.setFontSize(12); |
| | | run.setText(value); |
| | | return; |
| | | } |
| | | runs.get(0).setText(value, 0); |
| | | for (int i = runs.size() - 1; i >= 1; i--) { |
| | | paragraph.removeRun(i); |
| | | } |
| | | } |
| | | |
| | | private String normalizeCellLabel(String text) { |
| | | if (text == null) { |
| | | return ""; |
| | | } |
| | | return text.replace(" ", "").replace("\u00A0", "").replace("□", "").replace("☑", "") |
| | | .replace("\n", "").replace("\r", "").trim(); |
| | | } |
| | | |
| | | private String resolveCheckerName(DeviceExaminePlanDetails planDetails, DeviceExamineRecordDto recordDto) { |
| | | if (planDetails != null && StringUtils.isNotBlank(planDetails.getCheckChargerUser())) { |
| | | return planDetails.getCheckChargerUser(); |
| | | } |
| | | if (StringUtils.isNotBlank(recordDto.getCheckerUser())) { |
| | | return recordDto.getCheckerUser(); |
| | | } |
| | | Integer userId = planDetails != null && planDetails.getCheckChargerUserId() != null |
| | | ? planDetails.getCheckChargerUserId() : recordDto.getCheckerUserId(); |
| | | return resolveUserName(userId, null); |
| | | } |
| | | |
| | | private String resolveUserName(Integer userId, String userName) { |
| | | if (StringUtils.isNotBlank(userName)) { |
| | | return userName; |
| | | } |
| | | if (userId == null) { |
| | | return null; |
| | | } |
| | | User user = userMapper.selectById(userId); |
| | | return user == null ? null : user.getName(); |
| | | } |
| | | } |